2021-04-27 Android 理解frameworks services jni hardware kernel 整个控制过程实例包括回调

Android 理解frameworks services jni hardware kernel 整个控制过程实例包括回调

一、这个例子的实现的功能是,app控制power pin和control pin,可以read feedback pin的电平,如果feedback pin的电平有变化,会触发中断,底层把这个中断信息通过一系列回调和侦听发送到app。

通过这个简单的实例可以了解frameworks services jni hardware kernel整个流程,里面涉及到回调和侦听还是需要花费很多精力去理解和调试。

二、kernel 驱动\kernel\drivers\char\moneybox.c,获取中断,控制gpio,提供杂项设备节点 /dev/moneybox以及下面3个控制节点

       /sys/devices/platform/moneybox/enpower

       /sys/devices/platform/moneybox/control

       /sys/devices/platform/moneybox/feedback

三、hardware 主要代码下面的代码

      hardware/libhardware/include/hardware/moneybox.h
      hardware/libhardware/modules/Android.mk
      hardware/libhardware/modules/moneybox/Android.mk
      hardware/libhardware/modules/moneybox/moneybox.cpp

   3.1 moneybox.cpp代码

   3.2 moneybox.h代码

#ifndef ANDROID_FREG_INTERFACE_H
#define ANDROID_FREG_INTERFACE_H

#include <hardware/hardware.h>

__BEGIN_DECLS

/**
 * The id of this module
 */
#define MONEYBOX_HARDWARE_MODULE_ID "moneybox"

/**
 * The id of this device
 */
#define MONEYBOX_HARDWARE_DEVICE_ID "moneybox"

struct moneybox_module_t {
	struct hw_module_t common;
};

/* Callback function type */
typedef void (*moneybox_notify_t)(int m,int n);



struct moneybox_device_t {
	struct hw_device_t common;
	int fd;
	moneybox_notify_t notify;
	int (*set_val)(struct moneybox_device_t* dev, int val);
	int (*set_enable_power)(struct moneybox_device_t* dev, int val);
	int (*set_control_val)(struct moneybox_device_t* dev, int val);
	int (*get_feedback_val)(struct moneybox_device_t* dev, int* val);
	int (*set_notify)(struct moneybox_device_t *dev, moneybox_notify_t notify);
};

__END_DECLS

#endif

四、JNI代码frameworks/base/services/core/jni/com_android_server_MoneyboxService.cpp

#define LOG_TAG "MoneyboxServiceJNI"

#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"

#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/moneybox.h>
#include <utils/Looper.h>
#include <android_os_MessageQueue.h>

#include <stdio.h>

static jobject mCallbacksObj = NULL;
static jmethodID javaCallback;

JNIEnv* m_env;
jobject mobj;
jclass jSdkClass;

jobject g_jobj;  //全局对象

namespace android
{
	static void moneybox_setVal(JNIEnv* env, jobject clazz, jint ptr, jint value) {
		moneybox_device_t* device = (moneybox_device_t*)ptr;
		if(!device) {
			ALOGE("Device moneybox is not open.");
			return;
		}	
	
		int val = value;

		ALOGI("Set value %d to device moneybox.", val);
		
		device->set_val(device, val);
	}
static void moneybox_set_enable_power(JNIEnv* env, jobject clazz, jint ptr, jint value) {
		moneybox_device_t* device = (moneybox_device_t*)ptr;
		if(!device) {
			ALOGE("Device moneybox is not open.");
			return;
		}	
		int val = value;
		device->set_enable_power(device, val);
		ALOGI("Set value %d to device moneybox.", val);
	}

	static void moneybox_set_control_val(JNIEnv* env, jobject clazz, jint ptr, jint value) {
		int val = value;
		moneybox_device_t* device = (moneybox_device_t*)ptr;
		if(!device) {
			ALOGE("Device moneybox is not open.");
			return;
		}		 	
		device->set_control_val(device, val);
		ALOGI("Set value %d to device moneybox.", val);
	}
	static inline int moneybox_device_open(const hw_module_t* module, struct moneybox_device_t** device) {
		return module->methods->open(module, MONEYBOX_HARDWARE_DEVICE_ID, (struct hw_device_t**)device);
	}
// Called by the HAL to notify us of moneybox events
    static void hal_notify_callback(int m,int n) {
      JNIEnv* env = AndroidRuntime::getJNIEnv();
	  if (!mCallbacksObj)
		  return;
	  jclass clz = env->GetObjectClass(mCallbacksObj);
	  jint   ret  =  env->CallStaticIntMethod(clz, javaCallback,(jint)m,(jint)n);
	  
	  ALOGI("hal_notify_callback ,m=%d,n=%d,ret=%d.",m,n,ret);
    }

	static jint moneybox_get_feedback_val(JNIEnv* env, jobject clazz, jint ptr) {
		int val = 0;
		moneybox_device_t* device = (moneybox_device_t*)ptr;
		if(!device) {
			ALOGE("Device moneybox is not open.");
			return 0;
		}
		device->get_feedback_val(device, &val);
		ALOGI("Get Value %d from device moneybox....", val);
		#if 0	
		   if (!mCallbacksObj)
				mCallbacksObj = env->NewGlobalRef(clazz);
			
            jclass clz = env->GetObjectClass(mCallbacksObj);
			//jint ret  = env->CallIntMethod(mCallbacksObj, javaCallback,(jint)val,(jint)val);
			jint ret  = env->CallStaticIntMethod(clz, javaCallback,(jint)val,(jint)val);
			if (env->ExceptionCheck()) {
                 ALOGE("An exception was thrown by callback");
                env->ExceptionClear();
            }
			ALOGI(" CallIntMethod mCallbacksObj env ret=%d",ret);
		#endif	
		return val;
	}

	static jint moneybox_init(JNIEnv* env, jobject clazz) {
		int err;
		moneybox_module_t* module;
		moneybox_device_t* device;
		
		ALOGI("Initializing HAL stub moneybox......");

		if(hw_get_module(MONEYBOX_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {
			ALOGI("Device moneybox found.");
			if(moneybox_device_open(&(module->common), &device) == 0) {
				ALOGI("Device moneybox is Opened.");
				
				err=device->set_notify(device, hal_notify_callback);
                if (err < 0) {
                    ALOGE("Failed in call to set_notify(), err=%d", err);
                }else
					ALOGI("Call to set_notify successfully!");
	
				if (!mCallbacksObj)
                      mCallbacksObj = env->NewGlobalRef(clazz);

					   ALOGI("moneybox_device_open   successfully!");

				return (jint)device;
			}
			ALOGE("Failed to open device moneybox.");
			return 0;
		}
		ALOGE("Failed to get HAL stub moneybox.");
		return 0;		
	}
static void moneybox_class_init_native(JNIEnv* env, jclass clazz) {
      ALOGE("moneybox_class_init_native   GetMethodID  moneybox_callback");
	  //javaCallback = env->GetMethodID(clazz, "moneybox_callback", "(II)I");
	  javaCallback = env->GetStaticMethodID(clazz, "moneybox_callback", "(II)I");
}


static const JNINativeMethod method_table[] = {
	{"class_init_native", "()V", (void *)moneybox_class_init_native},
	{"init_native", "()I", (void*)moneybox_init},
	{"setVal_native", "(II)V", (void*)moneybox_setVal},
	{"set_enable_power_native", "(II)V", (void*)moneybox_set_enable_power},
	{"set_control_val_native", "(II)V", (void*)moneybox_set_control_val},
	{"get_feedback_val_native", "(I)I", (void*)moneybox_get_feedback_val},
};

int register_android_server_MoneyboxService(JNIEnv *env) {
	int res = jniRegisterNativeMethods(env, "com/android/server/MoneyboxService", method_table, NELEM(method_table));
	/*
	jclass clazz;
	clazz=env->FindClass("com/android/server/MoneyboxService");
	javaCallback = env->GetMethodID(clazz, "moneybox_callback", "(II)I");
	*/
	ALOGI("register_android_server_MoneyboxService");
	return res;
}



};

五、frameworks/base/services/core/jni/onload.cpp注册jni

int register_android_server_MoneyboxService(JNIEnv* env);

六、添加服务文件frameworks/base/services/core/java/com/android/server/MoneyboxService.java

七,添加manager文件, frameworks/base/core/java/android/os/SystemMoneybox.java ,提供api个app

八、添加服务frameworks/base/services/java/com/android/server/SystemServer.java

	    try {
		traceBeginAndSlog("Moneybox Service");
		ServiceManager.addService("moneybox", new MoneyboxService(context));
	    } catch (Throwable e) {
		Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
	    }

九、注册服务  frameworks/base/core/java/android/app/SystemServiceRegistry.java

		registerService(Context.MONEYBOX_SERVICE, SystemMoneybox.class,
						 new CachedServiceFetcher<SystemMoneybox>() {
			@Override
			public SystemMoneybox createService(ContextImpl ctx) {
				//return new SystemMoneybox(ctx);//ctx.mMainThread.getHandler().getLooper()
				return new SystemMoneybox(ctx,ctx.mMainThread.getHandler().getLooper());
			}});

十、添加frameworks/base/core/java/android/os/IMoneyboxService.aidl进行跨进行binder通信

package android.os;

import android.os.IMoneyboxTListener;

interface IMoneyboxService {
	void setVal(int val);
	void set_enable_power(int val);
	void set_control_val(int val);
	int  get_feedback_val();
	void registerListener(IMoneyboxTListener listener);
}

十一、添加frameworks/base/core/java/android/os/IMoneyboxTListener.aidl用于回调binder通信

package android.os;

import android.os.Bundle;


oneway interface IMoneyboxTListener
{
      void onMoneyboxChanged(int i);
}

十二、添加frameworks/base/location/java/android/location/MoneyboxListener.java 用于侦听

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.location;

import android.os.Bundle;

/**
 * Used for receiving notifications from the LocationManager when
 * the location has changed. These methods are called if the
 * LocationListener has been registered with the location manager service
 * using the {@link LocationManager#requestLocationUpdates(String, long, float, LocationListener)}
 * method.
 *
 * <div class="special reference">
 * <h3>Developer Guides</h3>
 * <p>For more information about identifying user location, read the
 * <a href="{@docRoot}guide/topics/location/obtaining-user-location.html">Obtaining User
 * Location</a> developer guide.</p>
 * </div>
 */
public interface MoneyboxListener {

    void onMoneyboxChanged(int i);
}

十三、frameworks/base/Android.mk添加下面内容

core/java/android/os/IMoneyboxService.aidl \
core/java/android/os/IMoneyboxTListener.aidl \

十四、APP demo,app通过下面两种方法调用系统服务。

    IMoneyboxService.Stub.asInterface( ServiceManager.getService("moneybox"));

    或者

    (SystemMoneybox) getSystemService("moneybox");

十五、make update-api更新api,mmm frameworks/base/services/、mmm frameworks/base/编译出framework.jar、services.jar和libandroid_servers.so(jni),push到机器运行测试

           15.1、执行service list查看该服务是否已经start。

           15.2、确认是否已经生成杂项设备节点和平台总线控制node。

xxx:/ # ls -l /dev/moneybox
crwxrwxrwx 1 root root 10,  60 2021-04-27 00:26 /dev/moneybox
xxx:/ # ls /sys/devices/platform/moneybox/
control driver driver_override enpower feedback modalias of_node power subsystem uevent
xxx:/ #

           15.3、运行demo app

           15.3、点击demo里面的button调用framework接口,然后通过servies,jni、hardware、kernel控制gpio,然后feedback gpio电平有变化的时候会通过一系列回调传数据到app,看下面的log,

所有的通路都是测试ok。

十六、整个过程涉及到下面的文件。

DEMO APP代码在Moneyboxapp目录下,用mmm进行编译
A  packages/apps/Moneyboxapp/Android.mk
A  packages/apps/Moneyboxapp/AndroidManifest.xml
A  packages/apps/Moneyboxapp/res/drawable/icon.png
A  packages/apps/Moneyboxapp/res/layout/main.xml
A  packages/apps/Moneyboxapp/res/values/strings.xml
A  packages/apps/Moneyboxapp/src/giada/ibc/moneybox/Moneybox.java

Framework涉及到的代码:
M  device/rockchip/rk3288/device.mk
M  frameworks/base/Android.mk
M  frameworks/base/core/java/android/app/SystemServiceRegistry.java
M  frameworks/base/core/java/android/content/Context.java
A  frameworks/base/core/java/android/os/IMoneyboxService.aidl
A  frameworks/base/core/java/android/os/IMoneyboxTListener.aidl
A  frameworks/base/core/java/android/os/SystemMoneybox.java
A  frameworks/base/location/java/android/location/MoneyboxListener.java
A  frameworks/base/services/core/java/com/android/server/MoneyboxService.java
M  frameworks/base/services/core/jni/Android.mk
A  frameworks/base/services/core/jni/com_android_server_MoneyboxService.cpp
M  frameworks/base/services/core/jni/onload.cpp
M  frameworks/base/services/java/com/android/server/SystemServer.java


hardware的代码:
A  hardware/libhardware/include/hardware/moneybox.h
M  hardware/libhardware/modules/Android.mk
A  hardware/libhardware/modules/moneybox/Android.mk
A  hardware/libhardware/modules/moneybox/moneybox.cpp

底层驱动涉及到的代码:
M  device/rockchip/common/init.connectivity.rc
M  kernel/arch/arm/boot/dts/rk3288-giada-jhs66l-act8846.dts
M  kernel/drivers/char/Makefile
A  kernel/drivers/char/moneybox.c

十七、源码下载路径 frameworks_services_jni_hardware_kernel.zip-Linux文档类资源-CSDN下载 包含所有的文件。

十八、饮水思源,参考文章:

1、android 创建一个实时监听的系统Service

     android 创建一个实时监听的系统Service_lz强的博客-CSDN博客_android 监听service

2、安卓硬件服务实例:手把手教你如何从驱动到应用添加硬件服务

      安卓硬件服务实例:手把手教你如何从驱动到应用添加硬件服务_kavin.zhu的博客-CSDN博客_安卓硬件驱动

3、Android Hal层回调APP应用接口

      Android Hal层回调APP应用接口_yujd的博客-CSDN博客

4、Android硬件服务框架实例之Vibrator(驱动到应用)

      Android硬件服务框架实例之Vibrator(驱动到应用)_kavin.zhu的博客-CSDN博客_android振动代码

5、https://www.jianshu.com/p/0f46a95d576f (Android 添加一个系统服务的完整流程(SystemService))

​​​​​​​

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值