定制Android系统开发之六——系统服务JNI的实现分析
来源:互联网 发布:js实现的简单的小特效 编辑:程序博客网 时间:2024/06/05 17:18
通过前面的几篇文章,已经将接口写到了XXXManagerService里面,下面的两篇博文将介绍怎么把接口的实现写到JNI里。
SystemServer.java
在前面,我提到过SystemServer.java文件。回顾一下,在这个文件中,我们通过
try { Slog.i(TAG, "radio service"); radioManagerService = new com.android.server.RadioManagerService(context); ServiceManager.addService(Context.RADIO_MANAGER_SERVICE, radioManagerService);} catch (Throwable e) { reportWtf("starting iflytek radio service", e);}
完成了服务的注册。
现在我们来看一下它的main函数。
public static void main(String[] args) { //此处省略很多行 System.loadLibrary("android_servers"); Slog.i(TAG, "Entered the Android system server!"); // Initialize native services. nativeInit(); // This used to be its own separate thread, but now it is // just the loop we run on the main thread. ServerThread thr = new ServerThread(); thr.initAndLoop();}
此处通过System.loadLibrary()这个库函数载入了android_servers这个jni库。这个jni库在哪里呢?在源码中grep一下“android_servers”这个字符串,可以定位到framework/base/services/jni/Android.mk这个文件:
LOCAL_MODULE:= libandroid_servers
看一下它的LOCAL_SRC_FILES:
LOCAL_SRC_FILES:= \com_android_server_AlarmManagerService.cpp \com_android_server_AssetAtlasService.cpp \com_android_server_ConsumerIrService.cpp \com_android_server_input_InputApplicationHandle.cpp \com_android_server_input_InputManagerService.cpp \com_android_server_input_InputWindowHandle.cpp \com_android_server_LightsService.cpp \com_android_server_power_PowerManagerService.cpp \com_android_server_SerialService.cpp \com_android_server_SystemServer.cpp \com_android_server_UsbDeviceManager.cpp \com_android_server_UsbHostManager.cpp \com_android_server_VibratorService.cpp \com_android_server_location_GpsLocationProvider.cpp \com_android_server_location_FlpHardwareProvider.cpp \com_android_server_connectivity_Vpn.cpp \onload.cpp
就是由这些文件编译成了libandroid_servers.so。
onload.cpp
java中函数与jni中函数的映射一般有两种方法,一种是通过函数名,也就是在jni函数的函数命中包含java函数所在的完整类名。另外一种就是在JNI_OnLoad()函数中注册。
在java中通过System.loadLibrary()函数载入lib的时候,JNI_OnLoad()函数将被调用。我们看一下这个函数。这个函数在on_load.cpp里面。
extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved){ JNIEnv* env = NULL; jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { ALOGE("GetEnv failed!"); return result; } ALOG_ASSERT(env, "Could not retrieve the env!"); register_android_server_PowerManagerService(env); register_android_server_SerialService(env); register_android_server_InputApplicationHandle(env); register_android_server_InputWindowHandle(env); register_android_server_InputManager(env); register_android_server_LightsService(env); register_android_server_AlarmManagerService(env); register_android_server_UsbDeviceManager(env); register_android_server_UsbHostManager(env); register_android_server_VibratorService(env); register_android_server_SystemServer(env); register_android_server_location_GpsLocationProvider(env); register_android_server_location_FlpHardwareProvider(env); register_android_server_connectivity_Vpn(env); register_android_server_AssetAtlasService(env); register_android_server_ConsumerIrService(env); return JNI_VERSION_1_4;}
首先它通过全局唯一的JavaVM获取JNIEnv的引用,然后调用一堆register方法。我们跟踪一下其中的一个方法。
int register_android_server_PowerManagerService(JNIEnv* env) { int res = jniRegisterNativeMethods(env, "com/android/server/power/PowerManagerService", gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods)); LOG_FATAL_IF(res < 0, "Unable to register native methods."); // Callbacks jclass clazz; FIND_CLASS(clazz, "com/android/server/power/PowerManagerService"); GET_METHOD_ID(gPowerManagerServiceClassInfo.wakeUpFromNative, clazz, "wakeUpFromNative", "(J)V"); GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleepFromNative, clazz, "goToSleepFromNative", "(JI)V"); GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz, "userActivityFromNative", "(JII)V"); // Initialize for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) { gLastEventTime[i] = LLONG_MIN; } gScreenOn = true; gScreenBright = true; gPowerManagerServiceObj = NULL; gPowerModule = NULL; return 0;}
在这个函数中,第一步就是注册jni函数:
int res = jniRegisterNativeMethods(env, "com/android/server/power/PowerManagerService", gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods));
这个函数的第一个参数是JNIEnv对象,第二个参数是定义native方法的java类的完整类名,第三个参数是一个数组(重要,马上就会讲),第四个参数我也不知道是什么,反正这么写就对了。
我们来看一下gPowerManagerServiceMethods这个数组的定义:
static JNINativeMethod gPowerManagerServiceMethods[] = { /* name, signature, funcPtr */ { "nativeInit", "()V", (void*) nativeInit }, { "nativeSetPowerState", "(ZZ)V", (void*) nativeSetPowerState }, { "nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V", (void*) nativeAcquireSuspendBlocker }, { "nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V", (void*) nativeReleaseSuspendBlocker }, { "nativeSetInteractive", "(Z)V", (void*) nativeSetInteractive }, { "nativeSetAutoSuspend", "(Z)V", (void*) nativeSetAutoSuspend },};
这就是一个二位数组,也就是说,这个数组的每个元素都是一个数组,用来表示java中定义的一个native函数。第一个元素是java中定义的函数名,第二个元素是这个native函数的签名,第三个元素是对应的jni函数的函数指针。
通过这样的一种注册机制,就完成了java函数到jni函数的映射。当调用java中的native函数时,就会执行对应的jni函数。需要注意的是,在gPowerManagerServiceMethods中,必须和java中定义的每一个native函数一一对应,也就是说,一个不能多,一个不能少,不然的话,虽然编译能通过,但是一运行起来,就会崩掉了。
- 定制Android系统开发之六——系统服务JNI的实现分析
- 定制Android系统开发之七——跟我实现系统服务的JNI调用
- 定制Android系统开发之四——系统服务实现的分析
- 定制Android系统开发之八——实现从JNI到Java的回调
- 定制Android系统开发之二——系统服务
- 定制Android系统开发之二——系统服务
- 定制Android系统开发之三——跟着我实现系统服务
- 定制Android系统开发之九——在系统服务中实现回调
- 定制Android系统开发之三——跟着我实现系统服务(测试可用)
- 定制Android系统开发之十——优化系统服务中的回调
- 系统服务JNI的实现分析
- 定制Android系统开发之五——ServiceFetcher
- 《BREW进阶与精通——3G移动增值业务的运营、定制与开发》连载之46---BREW SDK 九大功能之系统服务
- Android系统的定制
- Android系统JNI的实现方式
- Android系统JNI的实现方式
- Android系统JNI的实现方式
- 定制Android系统开发之一——提供接口的方式
- activiti与spring集成(maven)
- linux权限篇【一】
- MFC中获取各个窗体之间的句柄或者指针对象的方法 .
- WebLogic Tuxedo Connector 快速入门指南
- Python vs Matlab—— find 与 np.where
- 定制Android系统开发之六——系统服务JNI的实现分析
- iOS开发 在真机中将NSLog日志存入文件并保存到document目录
- SpringMVC filter设置例外的请求
- OSGI ——平台启动
- 矩阵及其运算
- linux权限篇【二】
- iOS 获取当前点击的cell相对于self.view的位置
- svm中的数学和算法
- JavaSE Collection