本文轉載自:http://blog.csdn.net/luoshengyang/article/details/6575988java
在上兩篇文章中,咱們介紹瞭如何爲Android系統的硬件編寫驅動程序,包括如何在Linux內核空間實現內核驅動程序和在用戶空間實現硬件抽象層接口。實現這二者的目的是爲了向更上一層提供硬件訪問接口,即爲Android的Application Frameworks層提供硬件服務。咱們知道,Android系統的應用程序是用Java語言編寫的,而硬件驅動程序是用C語言來實現的,那麼,Java接口如何去訪問C接口呢?衆所周知,Java提供了JNI方法調用,一樣,在Android系統中,Java應用程序經過JNI來調用硬件抽象層接口。在這一篇文章中,咱們將介紹如何爲Android硬件抽象層接口編寫JNI方法,以便使得上層的Java應用程序可以使用下層提供的硬件服務。linux
一. 參照在Ubuntu上爲Android增長硬件抽象層(HAL)模塊訪問Linux內核驅動程序一文,準備好硬件抽象層模塊,確保Android系統鏡像文件system.img已經包含hello.default模塊。android
二. 進入到frameworks/base/services/jni目錄,新建com_android_server_HelloService.cpp文件:ide
USER-NAME@MACHINE-NAME:~/Android$ cd frameworks/base/services/jni函數
USER-NAME@MACHINE-NAME:~/Android/frameworks/base/services/jni$ vi com_android_server_HelloService.cppspa
在com_android_server_HelloService.cpp文件中,實現JNI方法。注意文件的命令方法,com_android_server前綴表示的是包名,表示硬件服務HelloService是放在frameworks/base/services/java目錄下的com/android/server目錄的,即存在一個命令爲com.android.server.HelloService的類。這裏,咱們暫時略去HelloService類的描述,在下一篇文章中,咱們將回到HelloService類來。簡單地說,HelloService是一個提供Java接口的硬件訪問服務類。.net
首先是包含相應的頭文件: code
1 #define LOG_TAG "HelloService" 2 #include "jni.h" 3 #include "JNIHelp.h" 4 #include "android_runtime/AndroidRuntime.h" 5 #include <utils/misc.h> 6 #include <utils/Log.h> 7 #include <hardware/hardware.h> 8 #include <hardware/hello.h> 9 #include <stdio.h>
接着定義hello_init、hello_getVal和hello_setVal三個JNI方法:server
1 namespace android 2 { 3 /*在硬件抽象層中定義的硬件訪問結構體,參考<hardware/hello.h>*/ 4 struct hello_device_t* hello_device = NULL; 5 /*經過硬件抽象層定義的硬件訪問接口設置硬件寄存器val的值*/ 6 static void hello_setVal(JNIEnv* env, jobject clazz, jint value) { 7 int val = value; 8 LOGI("Hello JNI: set value %d to device.", val); 9 if(!hello_device) { 10 LOGI("Hello JNI: device is not open."); 11 return; 12 } 13 14 hello_device->set_val(hello_device, val); 15 } 16 /*經過硬件抽象層定義的硬件訪問接口讀取硬件寄存器val的值*/ 17 static jint hello_getVal(JNIEnv* env, jobject clazz) { 18 int val = 0; 19 if(!hello_device) { 20 LOGI("Hello JNI: device is not open."); 21 return val; 22 } 23 hello_device->get_val(hello_device, &val); 24 25 LOGI("Hello JNI: get value %d from device.", val); 26 27 return val; 28 } 29 /*經過硬件抽象層定義的硬件模塊打開接口打開硬件設備*/ 30 static inline int hello_device_open(const hw_module_t* module, struct hello_device_t** device) { 31 return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device); 32 } 33 /*經過硬件模塊ID來加載指定的硬件抽象層模塊並打開硬件*/ 34 static jboolean hello_init(JNIEnv* env, jclass clazz) { 35 hello_module_t* module; 36 37 LOGI("Hello JNI: initializing......"); 38 if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) { 39 LOGI("Hello JNI: hello Stub found."); 40 if(hello_device_open(&(module->common), &hello_device) == 0) { 41 LOGI("Hello JNI: hello device is open."); 42 return 0; 43 } 44 LOGE("Hello JNI: failed to open hello device."); 45 return -1; 46 } 47 LOGE("Hello JNI: failed to get hello stub module."); 48 return -1; 49 } 50 /*JNI方法表*/ 51 static const JNINativeMethod method_table[] = { 52 {"init_native", "()Z", (void*)hello_init}, 53 {"setVal_native", "(I)V", (void*)hello_setVal}, 54 {"getVal_native", "()I", (void*)hello_getVal}, 55 }; 56 /*註冊JNI方法*/ 57 int register_android_server_HelloService(JNIEnv *env) { 58 return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table)); 59 } 60 };
注意,在hello_init函數中,經過Android硬件抽象層提供的hw_get_module方法來加載模塊ID爲HELLO_HARDWARE_MODULE_ID的硬件抽象層模塊,其中,HELLO_HARDWARE_MODULE_ID是在<hardware/hello.h>中定義的。Android硬件抽象層會根據HELLO_HARDWARE_MODULE_ID的值在Android系統的/system/lib/hw目錄中找到相應的模塊,而後加載起來,而且返回hw_module_t接口給調用者使用。在jniRegisterNativeMethods函數中,第二個參數的值必須對應HelloService所在的包的路徑,即com.android.server.HelloService。blog
三. 修改同目錄下的onload.cpp文件,首先在namespace android增長register_android_server_HelloService函數聲明:
1 namespace android { 2 3 .............................................................................................. 4 5 int register_android_server_HelloService(JNIEnv *env); 6 7 }; 8 9 在JNI_onLoad增長register_android_server_HelloService函數調用: 10 extern "C" jint JNI_onLoad(JavaVM* vm, void* reserved) 11 { 12 ................................................................................................. 13 register_android_server_HelloService(env); 14 ................................................................................................. 15 }
1 LOCAL_SRC_FILES:= \ 2 com_android_server_AlarmManagerService.cpp \ 3 com_android_server_BatteryService.cpp \ 4 com_android_server_InputManager.cpp \ 5 com_android_server_LightsService.cpp \ 6 com_android_server_PowerManagerService.cpp \ 7 com_android_server_SystemServer.cpp \ 8 com_android_server_UsbService.cpp \ 9 com_android_server_VibratorService.cpp \ 10 com_android_server_location_GpsLocationProvider.cpp \ 11 com_android_server_HelloService.cpp / 12 onload.cpp