Android HAL实例解析(2)

4、第一种方法:直接调用service方法的实现过程

    下面分析第一种方法中,各层的关键代码。

1HAL

    一般来说HAL moudle需要涉及的是三个关键结构体:

struct hw_module_t;

struct hw_module_methods_t;

struct hw_device_t;

    下面结合代码说明这3个结构的用法。部分代码经过修改后面的章节会给出修改的原因。

文件:mokoid-read-only/hardware/modules/include/mokoid/led.h 

 
  1. struct led_module_t {  
  2.    struct hw_module_t common;  
  3. };  
  4. //HAL 规定不能直接使用hw_module_t结构,因此需要做这么一个继承。   
  5. struct led_control_device_t {    
  6. //自定义的一个针对Led控制的结构,包含hw_device_t和支持的API操作   
  7.    struct hw_device_t common;  
  8.    /* attributes */  
  9.    int fd;  //可用于具体的设备描述符   
  10.    /* supporting control APIs go here */  
  11.    int (*set_on)(struct led_control_device_t *dev, int32_t led);  
  12.    int (*set_off)(struct led_control_device_t *dev, int32_t led);  
  13. };  
  14. #define LED_HARDWARE_MODULE_ID "led"     
  15. //定义一个MODULE_ID,HAL层可以根据这个ID找到我们这个HAL stub  

文件mokoid-read-only/hardware/modules/led/led.c

  1. #define LOG_TAG "MokoidLedStub"  
  2. #include <hardware/hardware.h>  
  3. #include <fcntl.h>  
  4. #include <errno.h>  
  5. #include <cutils/log.h>  
  6. #include <cutils/atomic.h>   
  7. //#include <mokoid/led.h>  
  8. #include "../include/mokoid/led.h"   
  9. /*****************************************************************************/  
  10. int fd;             //硬件led的设备描述符 。你也可以用led_control_device_t结构中定义的fd  
  11. #define GPG3DAT2_ON 0x4800                 //ioctl控制命令  
  12. #define GPG3DAT2_OFF 0x4801   
  13. int led_device_close(struct hw_device_t* device)  
  14. {  
  15.     struct led_control_device_t* ctx = (struct led_control_device_t*)device;  
  16.     if (ctx) {  
  17.         free(ctx);  
  18.     }  
  19.     close(fd);  
  20.     return 0;  
  21. }  
  22. int led_on(struct led_control_device_t *dev, int32_t led)  
  23. {  
  24.     LOGI("LED Stub: set %d on.", led);  
  25.     ioctl(fd,GPG3DAT2_ON,NULL);           //控制Led亮灭,和硬件相关   
  26.     return 0;  
  27. }  
  28. int led_off(struct led_control_device_t *dev, int32_t led)  
  29. {  
  30.     LOGI("LED Stub: set %d off.", led);  
  31.     return 0;  
  32. }  
  33. static int led_device_open(const struct hw_module_t* module, const char* name,  
  34.         struct hw_device_t** device)   
  35. {  
  36.     struct led_control_device_t *dev;  
  37.     dev = (struct led_control_device_t *)malloc(sizeof(*dev));  
  38.     memset(dev, 0, sizeof(*dev));  
  39.     dev->common.tag =  HARDWARE_DEVICE_TAG;  
  40.     dev->common.version = 0;  
  41.     dev->common.module = module;  
  42.     dev->common.close = led_device_close;  
  43.     dev->set_on = led_on;        //实例化支持的操作   
  44.     dev->set_off = led_off;  
  45.     *device = &dev->common;     //将实例化后的led_control_device_t地址返回给jni层   
  46.                     //这样jni层就可以直接调用led_on、led_off、led_device_close方法了。   
  47.     if((fd=open("/dev/led",O_RDWR))==-1)      //打开硬件设备   
  48.     {  
  49.         LOGE("LED open error");  
  50.     }  
  51.     else  
  52.         LOGI("open ok");  
  53. success:  
  54.     return 0;  
  55. }  
  56. static struct hw_module_methods_t led_module_methods = {  
  57.     open: led_device_open  
  58. };  
  59. const struct led_module_t HAL_MODULE_INFO_SYM = {  
  60. //定义这个对象等于向系统注册了一个ID为LED_HARDWARE_MODULE_ID的stub。注意这里HAL_MODULE_INFO_SYM的名称不能改。   
  61.     common: {  
  62.         tag: HARDWARE_MODULE_TAG,  
  63.         version_major: 1,  
  64.         version_minor: 0,  
  65.         id: LED_HARDWARE_MODULE_ID,  
  66.         name: "Sample LED Stub",  
  67.         author: "The Mokoid Open Source Project",  
  68.         methods: &led_module_methods,  //实现了一个open的方法供jni层调用,   
  69.                                        //从而实例化led_control_device_t   
  70.     }  
  71.     /* supporting APIs go here */  
  72. };  

2JNI

文件:mokoid-read-only/frameworks/base/service/jni/com_mokoid_server_LedService.cpp

  1. struct led_control_device_t *sLedDevice = NULL;  
  2.   
  3. static jboolean mokoid_setOn(JNIEnv* env, jobject thiz, jint led)   
  4. {  
  5.     LOGI("LedService JNI: mokoid_setOn() is invoked.");  
  6.   
  7.     if (sLedDevice == NULL) {  
  8.         LOGI("LedService JNI: sLedDevice was not fetched correctly.");  
  9.         return -1;  
  10.     } else {  
  11.         return sLedDevice->set_on(sLedDevice, led);//调用hal层的注册的方法   
  12.     }  
  13. }  
  14.   
  15. static jboolean mokoid_setOff(JNIEnv* env, jobject thiz, jint led)   
  16. {  
  17.     LOGI("LedService JNI: mokoid_setOff() is invoked.");  
  18.   
  19.   
  20.     if (sLedDevice == NULL) {  
  21.         LOGI("LedService JNI: sLedDevice was not fetched correctly.");  
  22.         return -1;  
  23.     } else {  
  24.         return sLedDevice->set_off(sLedDevice, led); //调用hal层的注册的方法   
  25.     }  
  26. }  
  27.   
  28. /** helper APIs */  
  29. static inline int led_control_open(const struct hw_module_t* module,  
  30.         struct led_control_device_t** device) {  
  31.     return module->methods->open(module,  
  32.             LED_HARDWARE_MODULE_ID, (struct hw_device_t**)device);  
  33. //这个过程非常重要,jni通过LED_HARDWARE_MODULE_ID找到对应的stub   
  34. }  
  35.   
  36. static jboolean mokoid_init(JNIEnv *env, jclass clazz)  
  37. {  
  38.     led_module_t* module;  
  39.      LOGI("jni init-----------------------.");  
  40. if (hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) {  
  41. //根据LED_HARDWARE_MODULE_ID找到hw_module_t,参考hal层的实现   
  42.         LOGI("LedService JNI: LED Stub found.");  
  43.         if (led_control_open(&module->common, &sLedDevice) == 0) {    
  44.     //通过hw_module_t找到led_control_device_t   
  45.             LOGI("LedService JNI: Got Stub operations.");  
  46.             return 0;  
  47.         }  
  48.     }  
  49.   
  50.     LOGE("LedService JNI: Get Stub operations failed.");  
  51.     return -1;  
  52. }  
  53.   
  54. /* 
  55.  * Array of methods. 
  56. * Each entry has three fields: the name of the method, the method 
  57.  * signature, and a pointer to the native implementation. 
  58.  */  
  59. static const JNINativeMethod gMethods[] = {  
  60.     { "_init",      "()Z",  (void *)mokoid_init },//Framework层调用_init时促发   
  61.     { "_set_on",        "(I)Z", (void *)mokoid_setOn },  
  62.     { "_set_off",       "(I)Z", (void *)mokoid_setOff },  
  63. };  
  64. /* 
  65. *JNINativeMethod是jni层注册的方法,Framework层可以使用这些方法 
  66. *_init 、_set_on、_set_off是在Framework中调用的方法名称,函数的类型及返回值如下: 
  67. *()Z   无参数    返回值为bool型 
  68. * (I)Z   整型参数  返回值为bool型 
  69. */  
  70. static int registerMethods(JNIEnv* env) {  
  71.         static const charconst kClassName =  
  72.         "com/mokoid/server/LedService";//注意:必须和你Framework层的service类名相同   
  73.         jclass clazz;   
  74.       /* look up the class */  
  75.         clazz = env->FindClass(kClassName);  
  76.         if (clazz == NULL) {  
  77.                     LOGE("Can't find class %s/n", kClassName);  
  78.                     return -1;  
  79.         }  
  80.     /* register all the methods */  
  81.         if (env->RegisterNatives(clazz, gMethods,  
  82.                         sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)  
  83.         {  
  84.             LOGE("Failed registering methods for %s/n", kClassName);  
  85.             return -1;  
  86.         }  
  87.     /* fill out the rest of the ID cache */  
  88.         return 0;  
  89. }   
  90. jint JNI_OnLoad(JavaVM* vm, void* reserved) {//Framework层加载jni库时调用    
  91.         JNIEnv* env = NULL;  
  92.         jint result = -1;  
  93.         LOGI("JNI_OnLoad LED");  
  94.             if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {  
  95.             LOGE("ERROR: GetEnv failed/n");  
  96.             goto fail;  
  97.         }  
  98.             assert(env != NULL);  
  99.         if (registerMethods(env) != 0) { //注册你的JNINativeMethod   
  100.             LOGE("ERROR: PlatformLibrary native registration failed/n");  
  101.             goto fail;  
  102.         }  
  103.         /* success -- return valid version number */      
  104.         result = JNI_VERSION_1_4;  
  105. fail:  
  106.         return result;  
  107. }  

3service  属于Framework

文件:frameworks/base/service/java/com/mokoid/server/LedService.java

  1. package com.mokoid.server;  
  2. import Android.util.Config;  
  3. import Android.util.Log;  
  4. import Android.content.Context;  
  5. import Android.os.Binder;  
  6. import Android.os.Bundle;  
  7. import Android.os.RemoteException;  
  8. import Android.os.IBinder;  
  9. import mokoid.hardware.ILedService;  
  10. public final class LedService extends ILedService.Stub {  
  11. //对于这种直接模式不需要进程通讯,所以可以不加extends ILedService.Stub,此处加上主要是为了后面的第二种模式.   
  12.     static {  
  13.         System.load("/system/lib/libmokoid_runtime.so");//加载jni的动态库   
  14.     }  
  15.     public LedService() {  
  16.         Log.i("LedService""Go to get LED Stub...");  
  17.     _init();  
  18.     }  
  19.     /* 
  20.      * Mokoid LED native methods. 
  21.      */  
  22.     public boolean setOn(int led) {  
  23.         Log.i("MokoidPlatform""LED On");  
  24.     return _set_on(led);  
  25.     }  
  26.     public boolean setOff(int led) {  
  27.         Log.i("MokoidPlatform""LED Off");  
  28.     return _set_off(led);  
  29.     }  
  30.     private static native boolean _init();          //声明jni库可以提供的方法   
  31.     private static native boolean _set_on(int led);  
  32.     private static native boolean _set_off(int led);  
  33. }  

4APP 测试程序 (属于APP

文件:apps/LedClient/src/com/mokoid/LedClient/LedClient.java

 
  1. package com.mokoid.LedClient;  
  2. import com.mokoid.server.LedService;// 导入Framework层的LedService   
  3. import Android.app.Activity;  
  4. import Android.os.Bundle;  
  5. import Android.widget.TextView;  
  6.   
  7. public class LedClient extends Activity {  
  8.     @Override  
  9.     public void onCreate(Bundle savedInstanceState) {  
  10.         super.onCreate(savedInstanceState);  
  11.         // Call an API on the library.   
  12.     LedService ls = new LedService();  //实例化LedService   
  13.     ls.setOn(1);                       //通过LedService提供的方法,控制底层硬件   
  14.     ls.setOff(2);  
  15.           
  16.         TextView tv = new TextView(this);  
  17.         tv.setText("LED 1 is on. LED 2 is off.");  
  18.         setContentView(tv);  
  19.     }  
  20. }  

你可能感兴趣的:(android,jni,service,Module,attributes,methods)