Android HAL实例解析

来源:互联网 发布:linux vim 保存文件 编辑:程序博客网 时间:2024/05/08 02:05

一、本文源自刘洪涛,实际上源自台湾的Jollen的mokoid工程代码。

二、HAL介绍

有HAL架构由Patrick Brady (Google) 在2008 Google  I/O演中提出的,如下


Android的HAL是了保一些硬件提供商的知识产权而提出的,是了避linux的GPL束。思路是把控制硬件的作都放到了Android HAL中,而linux driver仅仅完成一些简单的数据交互作用,甚至把硬件寄存器空直接映射到user space。而Android是基于Aparch的license,因此硬件厂商可以只提供二制代,所以Android只是一个放的平台,并不是一个源的平台。也许也正是因Android不遵从GPL,所以Greg Kroah-Hartman才在2.6.33内核将Andorid驱动从linux中除。GPL和硬件厂商目前是有着无法弥合的裂痕。Android想要把问题处理好也是不容易的。

    总结下来,Android HAL存在的原因主要有:

    1. 并不是所有的硬件设备都有准的linux kernel的接口

    2. KERNEL DRIVER及到GPL的版。某些设备制造商并不原因公硬件驱动,所以才去用HAL方    式绕过GPL。

    3. 针对某些硬件,An有一些特殊的需求

三、HAL内容

1、HAL 主要的存于以下目

(注意:HAL在其它目录下也可以正常编译)

l  libhardware_legacy/ - 旧的架构、采取

l  libhardware/ - 新架构、 HAL stub 的

l  ril/ - Radio Interface Layer

l  msm7k  QUAL平台相

    主要包含以下一些模:Gps、Vibrator、Wifi、Copybit、Audio、Camera、Lights、Ril、Overlay等。

2、两种 HAL 架构比较

    目前存在两HAL架构,位于libhardware_legacy目下的“旧HAL架构”和位于libhardware目下的“新HAL架构”。两框架如下所示。


  libhardware_legacy 是将 *.so 文件当作shared library来使用,在runtime(JNI 部份)以 direct function call 使用 HAL module。通直接函数用的方式,来操作驱动程序。当然,用程序也可以不需要通 JNI 的方式行,直接加 *.so (dlopen)的做法用*.so 里的符号(symbol)也是一方式。而言之是没有经过封装,上可以直接操作硬件。

    在的libhardware 架构,就有stub的味道了。HAL stub 是一代理人(proxy)的概念,stub 然仍是以 *.so的形式存在,但HAL已将 *.so 档藏起来了。Stub 向 HAL提供操作函数(operations),而 runtime 是向 HAL 取得特定模(stub)的 operations,再 callback 些操作函数。这种以 indirect function call 的架构,HAL stub 成是一包含系,即 HAL 里包含了许许多多的 stub(代理人)。Runtime 只要型,即 module ID,就可以取得操作函数。于目前的HAL,可以认为Android定了HAL层结框架,通几个接口访问硬件从而一了用方式。

    下面例来分析HAL程方法。

四、mokoid 工程代码下载与结构分析

1、mokid项目概述

    modkoid工程提供了一个LedTest示例程序,是台湾的Jollen用于培的。对于理解android层次结构、Hal编程方法都非常有意义。

2、下载方法

    #svn checkout http://mokoid.googlecode.com/svn/trunk/mokoid-read-only

3、结构分析

[plain] view plaincopy
  1. |-- Android.mk    
  2. |-- apps      //两种应用测试方法  
  3. |   |-- Android.mk  
  4. |   |-- LedClient    //直接调用service来调用jni  
  5. |   |   |-- AndroidManifest.xml  
  6. |   |   |-- Android.mk  
  7. |   |   `-- src  
  8. |   |       `-- com  
  9. |   |           `-- mokoid  
  10. |   |               `-- LedClient  
  11. |   |                   `-- LedClient.java     //第1种方式应用程序实现代码  
  12. |   `-- LedTest        //通过manager来调用jni  
  13. |       |-- AndroidManifest.xml  
  14. |       |-- Android.mk  
  15. |       `-- src  
  16. |           `-- com  
  17. |               `-- mokoid  
  18. |                   `-- LedTest  
  19. |                       |-- LedSystemServer.java  //开启了一个后台service,下文会有解释  
  20. |                       `-- LedTest.java    //第2种方式应用程序实现代码  
  21. |-- frameworks     //框架代码  
  22. |   |-- Android.mk  
  23. |   `-- base  
  24. |       |-- Android.mk  
  25. |       |-- core  
  26. |       |   `-- java  
  27. |       |       `-- mokoid  
  28. |       |           `-- hardware  
  29. |       |               |-- ILedService.aidl  
  30. |       |               `-- LedManager.java     //实现了Manager,给第2种方法用  
  31. |       `-- service    
  32. |           |-- Android.mk  
  33. |           |-- com.mokoid.server.xml  
  34. |           |-- java  
  35. |           |   `-- com  
  36. |           |       `-- mokoid  
  37. |           |           `-- server  
  38. |           |               `-- LedService.java    //Framework service代码  
  39. |           `-- jni  
  40. |               |-- Android.mk  
  41. |               `-- com_mokoid_server_LedService.cpp  //jni代码  
  42. |-- hardware  
  43. |   `-- modules  
  44. |       |-- Android.mk  
  45. |       |-- include  
  46. |       |   `-- mokoid  
  47. |       |       `-- led.h  
  48. |       `-- led  
  49. |           |-- Android.mk  
  50. |           `-- led.c       //led stub 硬件控制代码  
[plain] view plaincopy
  1. |-- driver  
  2. |       `-- led  
  3. |           |-- Makefile  
  4. |           `-- led_drv.c       //led driver    
[plain] view plaincopy
  1. `-- README.txt  

 Android的HAL的实现需要通过JNI(Java Native Interface),JNI简单来说就是java程序可以调用C/C++写的动态链接库,这样的话,HAL可以使用C/C++语言编写,效率更高。在Android下访问HAL大致有以下两种方式:

 

  (1)Android的app可以直接通过service调用.so格式的jni


(2)经过Manager调用service


 上面两种方法应该说是各有优缺点,第一种方法简单高效,但不正规。第二种方法实现起来比较复杂,但更符合目前的Android框架。第二种方法中,LegManager和LedService(java)在两个进程中,需要通过进程通讯的方式来通讯。

     mokoid工程中实现了上述两种方法。下面将详细介绍这两种方法的实现原理。

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

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

(1)HAL层

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

[cpp] view plaincopy
  1. struct hw_module_t;  
  2. struct hw_module_methods_t;  
  3. struct hw_device_t;  

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

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

[cpp] view plaincopy
  1. <pre name="code" class="cpp"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  </pre>  
  16. <pre></pre>  
  17. <p></p>  
  18. <pre></pre>  
  19. <p></p>  
  20. <p style="font-family:宋体; font-size:10.5pt; color:rgb(51,51,51)"><span style="color:rgb(51,51,51); font-size:10.5pt; line-height:26px; text-align:left; font-family:宋体"><span lang="EN-US"><span style="color:rgb(51,51,51); font-size:10.5pt; line-height:26px; text-align:left; font-family:宋体">文件</span><span style="color:rgb(51,51,51); font-size:10.5pt; line-height:26px; text-align:left; font-family:宋体">:<span lang="EN-US">mokoid-read-only/hardware/modules/led/led.c</span></span></span></span></p>  
  21. <p style="color:rgb(51,51,51)"><span style="color:rgb(51,51,51); line-height:26px; text-align:left"><span lang="EN-US"></span></span></p>  
  22. <pre name="code" class="cpp" style="font-family: 宋体; font-size: 10.5pt; ">#define LOG_TAG "MokoidLedStub"    
  23. #include <hardware/hardware.h>    
  24. #include <fcntl.h>    
  25. #include <errno.h>    
  26. #include <cutils/log.h>    
  27. #include <cutils/atomic.h>    
  28. //#include <mokoid/led.h>    
  29. #include "../include/mokoid/led.h"    
  30. /*****************************************************************************/    
  31. int fd;             //硬件led的设备描述符 。你也可以用led_control_device_t结构中定义的fd    
  32. #define GPG3DAT2_ON 0x4800                 //ioctl控制命令    
  33. #define GPG3DAT2_OFF 0x4801    
  34. int led_device_close(struct hw_device_t* device)    
  35. {    
  36.     struct led_control_device_t* ctx = (struct led_control_device_t*)device;    
  37.     if (ctx) {    
  38.         free(ctx);    
  39.     }    
  40.     close(fd);    
  41.     return 0;    
  42. }    
  43. int led_on(struct led_control_device_t *dev, int32_t led)    
  44. {    
  45.     LOGI("LED Stub: set %d on.", led);    
  46.     ioctl(fd,GPG3DAT2_ON,NULL);           //控制Led亮灭,和硬件相关    
  47.     return 0;    
  48. }    
  49. int led_off(struct led_control_device_t *dev, int32_t led)    
  50. {    
  51.     LOGI("LED Stub: set %d off.", led);    
  52.     return 0;    
  53. }    
  54. static int led_device_open(const struct hw_module_t* module, const char* name,    
  55.         struct hw_device_t** device)     
  56. {    
  57.     struct led_control_device_t *dev;    
  58.     dev = (struct led_control_device_t *)malloc(sizeof(*dev));    
  59.     memset(dev, 0, sizeof(*dev));    
  60.     dev->common.tag =  HARDWARE_DEVICE_TAG;    
  61.     dev->common.version = 0;    
  62.     dev->common.module = module;    
  63.     dev->common.close = led_device_close;    
  64.     dev->set_on = led_on;        //实例化支持的操作    
  65.     dev->set_off = led_off;    
  66.     *device = &dev->common;     //将实例化后的led_control_device_t地址返回给jni层    
  67.                     //这样jni层就可以直接调用led_on、led_off、led_device_close方法了。    
  68.     if((fd=open("/dev/led",O_RDWR))==-1)      //打开硬件设备    
  69.     {    
  70.         LOGE("LED open error");    
  71.     }    
  72.     else    
  73.         LOGI("open ok");    
  74. success:    
  75.     return 0;    
  76. }    
  77. static struct hw_module_methods_t led_module_methods = {    
  78.     open: led_device_open    
  79. };    
  80. const struct led_module_t HAL_MODULE_INFO_SYM = {    
  81. //定义这个对象等于向系统注册了一个ID为LED_HARDWARE_MODULE_ID的stub。注意这里HAL_MODULE_INFO_SYM的名称不能改。    
  82.     common: {    
  83.         tag: HARDWARE_MODULE_TAG,    
  84.         version_major: 1,    
  85.         version_minor: 0,    
  86.         id: LED_HARDWARE_MODULE_ID,    
  87.         name: "Sample LED Stub",    
  88.         author: "The Mokoid Open Source Project",    
  89.         methods: &led_module_methods,  //实现了一个open的方法供jni层调用,    
  90.                                        //从而实例化led_control_device_t    
  91.     }    
  92.     /* supporting APIs go here */    
  93. };    
  94. </pre><br>  
  95. <br>  
  96. <p></p>  
  97. <h4 style="font-family:宋体; font-size:10.5pt"><a name="t9"></a>(2)JNI层</h4>  
  98. <p></p>  
  99. <p style="font-family:宋体; font-size:10.5pt">文件:mokoid-read-only/frameworks/base/service/jni/com_mokoid_server_LedService.cpp</p>  
  100. <p></p>  
  101. <pre name="code" class="cpp" style="font-family: 宋体; font-size: 10.5pt; ">struct led_control_device_t *sLedDevice = NULL;    
  102.     
  103. static jboolean mokoid_setOn(JNIEnv* env, jobject thiz, jint led)     
  104. {    
  105.     LOGI("LedService JNI: mokoid_setOn() is invoked.");    
  106.     
  107.     if (sLedDevice == NULL) {    
  108.         LOGI("LedService JNI: sLedDevice was not fetched correctly.");    
  109.         return -1;    
  110.     } else {    
  111.         return sLedDevice->set_on(sLedDevice, led);//调用hal层的注册的方法    
  112.     }    
  113. }    
  114.     
  115. static jboolean mokoid_setOff(JNIEnv* env, jobject thiz, jint led)     
  116. {    
  117.     LOGI("LedService JNI: mokoid_setOff() is invoked.");    
  118.     
  119.     
  120.     if (sLedDevice == NULL) {    
  121.         LOGI("LedService JNI: sLedDevice was not fetched correctly.");    
  122.         return -1;    
  123.     } else {    
  124.         return sLedDevice->set_off(sLedDevice, led); //调用hal层的注册的方法    
  125.     }    
  126. }    
  127.     
  128. /** helper APIs */    
  129. static inline int led_control_open(const struct hw_module_t* module,    
  130.         struct led_control_device_t** device) {    
  131.     return module->methods->open(module,    
  132.             LED_HARDWARE_MODULE_ID, (struct hw_device_t**)device);    
  133. //这个过程非常重要,jni通过LED_HARDWARE_MODULE_ID找到对应的stub    
  134. }    
  135.     
  136. static jboolean mokoid_init(JNIEnv *env, jclass clazz)    
  137. {    
  138.     led_module_t* module;    
  139.      LOGI("jni init-----------------------.");    
  140. if (hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) {    
  141. //根据LED_HARDWARE_MODULE_ID找到hw_module_t,参考hal层的实现    
  142.         LOGI("LedService JNI: LED Stub found.");    
  143.         if (led_control_open(&module->common, &sLedDevice) == 0) {      
  144.     //通过hw_module_t找到led_control_device_t    
  145.             LOGI("LedService JNI: Got Stub operations.");    
  146.             return 0;    
  147.         }    
  148.     }    
  149.     
  150.     LOGE("LedService JNI: Get Stub operations failed.");    
  151.     return -1;    
  152. }    
  153.     
  154. /*  
  155.  * Array of methods.  
  156. * Each entry has three fields: the name of the method, the method  
  157.  * signature, and a pointer to the native implementation.  
  158.  */    
  159. static const JNINativeMethod gMethods[] = {    
  160.     { "_init",      "()Z",  (void *)mokoid_init },//Framework层调用_init时促发    
  161.     { "_set_on",        "(I)Z", (void *)mokoid_setOn },    
  162.     { "_set_off",       "(I)Z", (void *)mokoid_setOff },    
  163. };    
  164. /*  
  165. *JNINativeMethod是jni层注册的方法,Framework层可以使用这些方法  
  166. *_init 、_set_on、_set_off是在Framework中调用的方法名称,函数的类型及返回值如下:  
  167. *()Z   无参数    返回值为bool型  
  168. * (I)Z   整型参数  返回值为bool型  
  169. */    
  170. static int registerMethods(JNIEnv* env) {    
  171.         static const charconst kClassName =    
  172.         "com/mokoid/server/LedService";//注意:必须和你Framework层的service类名相同    
  173.         jclass clazz;     
  174.       /* look up the class */    
  175.         clazz = env->FindClass(kClassName);    
  176.         if (clazz == NULL) {    
  177.                     LOGE("Can't find class %s/n", kClassName);    
  178.                     return -1;    
  179.         }    
  180.     /* register all the methods */    
  181.         if (env->RegisterNatives(clazz, gMethods,    
  182.                         sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)    
  183.         {    
  184.             LOGE("Failed registering methods for %s/n", kClassName);    
  185.             return -1;    
  186.         }    
  187.     /* fill out the rest of the ID cache */    
  188.         return 0;    
  189. }     
  190. jint JNI_OnLoad(JavaVM* vm, void* reserved) {//Framework层加载jni库时调用     
  191.         JNIEnv* env = NULL;    
  192.         jint result = -1;    
  193.         LOGI("JNI_OnLoad LED");    
  194.             if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {    
  195.             LOGE("ERROR: GetEnv failed/n");    
  196.             goto fail;    
  197.         }    
  198.             assert(env != NULL);    
  199.         if (registerMethods(env) != 0) { //注册你的JNINativeMethod    
  200.             LOGE("ERROR: PlatformLibrary native registration failed/n");    
  201.             goto fail;    
  202.         }    
  203.         /* success -- return valid version number */        
  204.         result = JNI_VERSION_1_4;    
  205. fail:    
  206.         return result;    
  207. }  </pre>  
  208. <p></p>  
  209. <h4 style="font-family:宋体; font-size:10.5pt"><a name="t10"></a>3)service  (属于Framework层)</h4>  
  210. <p></p>  
  211. <p style="font-family:宋体; font-size:10.5pt">文件:frameworks/base/service/java/com/mokoid/server/LedService.java</p>  
  212. <pre name="code" class="cpp" style="font-family: 宋体; font-size: 10.5pt; ">package com.mokoid.server;    
  213. import android.util.Config;    
  214. import android.util.Log;    
  215. import android.content.Context;    
  216. import android.os.Binder;    
  217. import android.os.Bundle;    
  218. import android.os.RemoteException;    
  219. import android.os.IBinder;    
  220. import mokoid.hardware.ILedService;    
  221. public final class LedService extends ILedService.Stub {    
  222. //对于这种直接模式不需要进程通讯,所以可以不加extends ILedService.Stub,此处加上主要是为了后面的第二种模式.    
  223.     static {    
  224.         System.load("/system/lib/libmokoid_runtime.so");//加载jni的动态库    
  225.     }    
  226.     public LedService() {    
  227.         Log.i("LedService""Go to get LED Stub...");    
  228.     _init();    
  229.     }    
  230.     /*  
  231.      * Mokoid LED native methods.  
  232.      */    
  233.     public boolean setOn(int led) {    
  234.         Log.i("MokoidPlatform""LED On");    
  235.     return _set_on(led);    
  236.     }    
  237.     public boolean setOff(int led) {    
  238.         Log.i("MokoidPlatform""LED Off");    
  239.     return _set_off(led);    
  240.     }    
  241.     private static native boolean _init();          //声明jni库可以提供的方法    
  242.     private static native boolean _set_on(int led);    
  243.     private static native boolean _set_off(int led);    
  244. }  </pre><br>  
  245. <h4 style="margin-top:6pt; margin-right:0cm; margin-bottom:6pt; margin-left:0cm; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left"><a name="t11"></a>  
  246. <span style="font-size:13px"><span style="color:rgb(128,128,128)"><span class="MsoSubtleEmphasis"><span style="font-family:宋体">(</span></span><span class="MsoSubtleEmphasis"><span style="font-family:Cambria,serif">4</span></span><span class="MsoSubtleEmphasis"><span style="font-family:宋体">)</span></span><span class="MsoSubtleEmphasis"><span style="font-family:Cambria,serif">APP </span></span><span class="MsoSubtleEmphasis"><span style="font-family:宋体">测试程序</span></span><span class="MsoSubtleEmphasis"><span style="font-family:Cambria,serif"> </span></span><span class="MsoSubtleEmphasis"><span style="font-family:宋体">(属于</span></span><span class="MsoSubtleEmphasis"><span style="font-family:Cambria,serif">APP</span></span><span class="MsoSubtleEmphasis"><span style="font-family:宋体">层</span></span><span class="MsoSubtleEmphasis"><span style="font-family:宋体">)</span></span></span></span><span class="MsoSubtleEmphasis"></span></h4>  
  247. <p style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left">  
  248. <span style="font-size:10.5pt; font-family:宋体">文件:<span lang="EN-US">apps/LedClient/src/com/mokoid/LedClient/LedClient.java</span></span></p>  
  249. <p class="PreformattedText" style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left; margin-top:0cm; margin-right:0cm; margin-bottom:0pt; margin-left:0cm">  
  250. </p>  
  251. <pre name="code" class="cpp">package com.mokoid.LedClient;    
  252. import com.mokoid.server.LedService;// 导入Framework层的LedService    
  253. import android.app.Activity;    
  254. import android.os.Bundle;    
  255. import android.widget.TextView;    
  256.     
  257. public class LedClient extends Activity {    
  258.     @Override    
  259.     public void onCreate(Bundle savedInstanceState) {    
  260.         super.onCreate(savedInstanceState);    
  261.         // Call an API on the library.    
  262.     LedService ls = new LedService();  //实例化LedService    
  263.     ls.setOn(1);                       //通过LedService提供的方法,控制底层硬件    
  264.     ls.setOff(2);    
  265.             
  266.         TextView tv = new TextView(this);    
  267.         tv.setText("LED 1 is on. LED 2 is off.");    
  268.         setContentView(tv);    
  269.     }    
  270. }  </pre>  
  271. <p></p>  
  272. <h3 style="margin-top:6pt; margin-right:0cm; margin-bottom:6pt; margin-left:0cm; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(51,51,51); font-family:Arial; line-height:26px; text-align:left"><a name="t12"></a>  
  273. <span style="font-size:13px"><span lang="EN-US" style="font-family:宋体">5</span><span style="font-family:宋体">、第二种方法</span><span style="font-family:宋体">:</span><span style="font-family:宋体">经过</span><span lang="EN-US" style="font-family:宋体">Manager</span><span style="font-family:宋体">调用</span><span lang="EN-US" style="font-family:宋体">service</span></span></h3>  
  274. <p></p>  
  275. <p class="PreformattedText" style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left; margin-top:0cm; margin-right:0cm; margin-bottom:0pt; margin-left:0cm">  
  276. <span lang="EN-US" style="font-size:10.5pt; font-family:宋体">    HAL</span><span style="font-size:10.5pt; font-family:宋体">、</span><span lang="EN-US" style="font-size:10.5pt; font-family:宋体">JNI</span><span style="font-size:10.5pt; font-family:宋体">两层和第一种方法一样</span><span style="font-size:10.5pt; font-family:宋体">,</span><span style="font-size:10.5pt; font-family:宋体">所以后面只分析其他的层次。</span></p>  
  277. <h4 style="margin-top:6pt; margin-right:0cm; margin-bottom:6pt; margin-left:0cm; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left"><a name="t13"></a>  
  278. <span style="font-size:13px"><span style="font-family:宋体">(<span lang="EN-US">1</span>)<span lang="EN-US">Manager </span></span><span style="color:rgb(128,128,128)"><span class="MsoSubtleEmphasis"><span style="font-family:宋体">(</span></span><span class="MsoSubtleEmphasis"><span style="font-family:宋体">属于</span></span><span class="MsoSubtleEmphasis"><span lang="EN-US" style="font-family:Cambria,serif">Framework</span></span><span class="MsoSubtleEmphasis"><span style="font-family:宋体">层</span></span><span class="MsoSubtleEmphasis"><span style="font-family:宋体">)</span></span></span></span></h4>  
  279. <p class="PreformattedText" style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left; margin-top:0cm; margin-right:0cm; margin-bottom:0pt; margin-left:0cm">  
  280. <span lang="EN-US" style="font-size:10.5pt; font-family:宋体">    APP</span><span style="font-size:10.5pt; font-family:宋体">通过这个</span><span lang="EN-US" style="font-size:10.5pt; font-family:宋体">Manager</span><span style="font-size:10.5pt; font-family:宋体">和</span><span lang="EN-US" style="font-size:10.5pt; font-family:宋体">service</span><span style="font-size:10.5pt; font-family:宋体">通讯。</span></p>  
  281. <p class="PreformattedText" style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left; margin-top:0cm; margin-right:0cm; margin-bottom:0pt; margin-left:0cm">  
  282. <span style="font-size:10.5pt; font-family:宋体">文件:<span lang="EN-US">mokoid-read-only /frameworks/base/core/java/mokoid/hardware/LedManager.java</span></span></p>  
  283. <p class="PreformattedText" style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left; margin-top:0cm; margin-right:0cm; margin-bottom:0pt; margin-left:0cm">  
  284. </p>  
  285. <pre name="code" class="cpp">package mokoid.hardware;    
  286. import android.content.Context;    
  287. import android.os.Binder;    
  288. import android.os.Bundle;    
  289. import android.os.Parcelable;    
  290. import android.os.ParcelFileDescriptor;    
  291. import android.os.Process;    
  292. import android.os.RemoteException;    
  293. import android.os.Handler;    
  294. import android.os.Message;    
  295. import android.os.ServiceManager;    
  296. import android.util.Log;    
  297. import mokoid.hardware.ILedService;    
  298.     
  299. /*  
  300.  * Class that lets you access the Mokoid LedService.  
  301.  */    
  302. public class LedManager    
  303. {    
  304.     private static final String TAG = "LedManager";    
  305.     private ILedService mLedService;    
  306.     public LedManager() {    
  307.         mLedService = ILedService.Stub.asInterface(ServiceManager.getService("led"));    
  308. /*  
  309. *这一步是关键,利用ServiceManager获取到LedService,从而调用它提供的方法。这要求LedService必  
  310. *须已经添加到了ServiceManager中,这个过程将在App中的一个service进程中完成。  
  311. */    
  312.     if (mLedService != null) {    
  313.             Log.i(TAG, "The LedManager object is ready.");    
  314.     }    
  315.     }    
  316.     public boolean LedOn(int n) {    
  317.         boolean result = false;    
  318.         try {    
  319.             result = mLedService.setOn(n);    
  320.         } catch (RemoteException e) {    
  321.             Log.e(TAG, "RemoteException in LedManager.LedOn:", e);    
  322.         }    
  323.         return result;    
  324.     }    
  325.     public boolean LedOff(int n) {    
  326.         boolean result = false;    
  327.         try {    
  328.             result = mLedService.setOff(n);    
  329.         } catch (RemoteException e) {    
  330.             Log.e(TAG, "RemoteException in LedManager.LedOff:", e);    
  331.         }    
  332.         return result;    
  333.     }    
  334. }  </pre>  
  335. <p></p>  
  336. <p class="PreformattedText" style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left; margin-top:0cm; margin-right:0cm; margin-bottom:0pt; margin-left:0cm; text-indent:31.5pt">  
  337. <span style="font-size:10.5pt; font-family:宋体">因为<span lang="EN-US">LedService</span>和<span lang="EN-US">LedManager</span>在不同的进程,所以要考虑到进程通讯的问题。<span lang="EN-US">Manager</span>通过增加一个<span lang="EN-US">aidl</span>文件来描述通讯接口。</span></p>  
  338. <p style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left">  
  339. <span style="font-size:10.5pt; font-family:宋体"></span></p>  
  340. <p class="PreformattedText" style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left; margin-top:0cm; margin-right:0cm; margin-bottom:0pt; margin-left:0cm">  
  341. <span style="font-size:10.5pt; font-family:宋体">文件</span><span style="font-size:10.5pt; font-family:宋体">:<span lang="EN-US">mokoid-read-only/frameworks/base/core/java/mokoid/hardware/ILedService.aidl</span></span></p>  
  342. <p class="PreformattedText" style="color:rgb(51,51,51); line-height:26px; text-align:left; margin-top:0cm; margin-right:0cm; margin-bottom:0pt; margin-left:0cm">  
  343. <span lang="EN-US"></span></p>  
  344. <pre name="code" class="cpp" style="font-family: 宋体; font-size: 10.5pt; ">package mokoid.hardware;    
  345. interface ILedService    
  346. {    
  347.     boolean setOn(int led);    
  348.     boolean setOff(int led);    
  349. }    
  350. //系统的aidl工具会将ILedService.aidl文件ILedService.java文件,实现了ILedService  </pre><br>  
  351. <p></p>  
  352. <h4 style="margin-top:6pt; margin-right:0cm; margin-bottom:6pt; margin-left:0cm; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left"><a name="t14"></a>  
  353. <span style="font-size:13px"><span style="font-family:宋体"><br>  
  354. (<span lang="EN-US">2</span>)<span lang="EN-US">SystemServer </span>(</span><span style="font-family:宋体">属于</span><span lang="EN-US" style="font-family:宋体">APP</span><span style="font-family:宋体">层</span><span style="font-family:宋体">)</span></span></h4>  
  355. <p></p>  
  356. <p class="PreformattedText" style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left; margin-top:0cm; margin-right:0cm; margin-bottom:0pt; margin-left:0cm">  
  357. <span style="font-size:10.5pt; font-family:宋体">文件:<span lang="EN-US">mokoid-read-only/apps/LedTest/src/com/mokoid/LedTest/LedSystemServer.java</span></span></p>  
  358. <p class="PreformattedText" style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left; margin-top:0cm; margin-right:0cm; margin-bottom:0pt; margin-left:0cm">  
  359. <span style="font-size:10.5pt; font-family:宋体"><span lang="EN-US"></span></span></p>  
  360. <pre name="code" class="cpp">package com.mokoid.LedTest;    
  361. import com.mokoid.server.LedService;    
  362. import android.os.IBinder;    
  363. import android.os.ServiceManager;    
  364. import android.util.Log;    
  365. import android.app.Service;    
  366. import android.content.Context;    
  367. import android.content.Intent;    
  368.     
  369. public class LedSystemServer extends Service {    
  370. //注意这里的Service是APP中的概念,代表一个后台进程。注意区别和Framework中的service的概念。    
  371.     @Override    
  372.     public IBinder onBind(Intent intent) {    
  373.         return null;    
  374.     public void onStart(Intent intent, int startId) {    
  375.         Log.i("LedSystemServer""Start LedService...");    
  376.     
  377.     /* Please also see SystemServer.java for your interests. */    
  378.     LedService ls = new LedService();    
  379.         try {    
  380.             ServiceManager.addService("led", ls);  //将LedService添加到ServiceManager中    
  381.         } catch (RuntimeException e) {    
  382.             Log.e("LedSystemServer""Start LedService failed.");    
  383.         }    
  384.     }    
  385. }  </pre>  
  386. <p></p>  
  387. <h4 style="margin-top:6pt; margin-right:0cm; margin-bottom:6pt; margin-left:0cm; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left"><a name="t15"></a>  
  388. <span style="font-size:13px"><span style="font-family:宋体">(<span lang="EN-US">3</span>)<span lang="EN-US">APP </span></span><span style="font-family:宋体">测试程序</span><span style="font-family:宋体">(</span><span style="font-family:宋体">属于</span><span lang="EN-US" style="font-family:宋体">APP</span><span style="font-family:宋体">层</span><span style="font-family:宋体">)</span></span></h4>  
  389. <p></p>  
  390. <p class="PreformattedText" style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left; background-color:white; margin-top:0cm; margin-right:0cm; margin-bottom:0pt; margin-left:0cm">  
  391. <span style="font-size:10.5pt; font-family:宋体">文件:<span lang="EN-US">mokoid-read-only/apps/LedTest/src/com/mokoid/LedTest/LedTest.java</span></span></p>  
  392. <p class="PreformattedText" style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left; margin-top:0cm; margin-right:0cm; margin-bottom:0pt; margin-left:0cm">  
  393. <span style="font-size:10.5pt; font-family:宋体"><span lang="EN-US"></span></span></p>  
  394. <pre name="code" class="cpp">package com.mokoid.LedTest;    
  395. import mokoid.hardware.LedManager;    
  396. import com.mokoid.server.LedService;    
  397. import android.app.Activity;    
  398. import android.os.Bundle;    
  399. import android.util.Log;    
  400. import android.widget.TextView;    
  401. import android.widget.Button;    
  402. import android.content.Intent;    
  403. import android.view.View;    
  404.     
  405. public class LedTest extends Activity implements View.OnClickListener {    
  406.     private LedManager mLedManager = null;    
  407.     @Override    
  408.     public void onCreate(Bundle savedInstanceState) {    
  409.         super.onCreate(savedInstanceState);    
  410.         // Start LedService in a seperated process.    
  411.         startService(new Intent("com.mokoid.systemserver"));//开启后台进程    
  412.         Button btn = new Button(this);    
  413.         btn.setText("Click to turn LED 1 On");    
  414.      btn.setOnClickListener(this);    
  415.         setContentView(btn);    
  416.     }    
  417.     public void onClick(View v) {    
  418.         // Get LedManager.    
  419.         if (mLedManager == null) {    
  420.         Log.i("LedTest""Creat a new LedManager object.");    
  421.         mLedManager = new LedManager();  //实例化Framework层中的Manager    
  422.         }        
  423.         if (mLedManager != null) {    
  424.         Log.i("LedTest""Got LedManager object.");    
  425.      }    
  426.         /** Call methods in LedService via proxy object   
  427.          * which is provided by LedManager.   
  428.          */    
  429.         mLedManager.LedOn(1);    
  430.         TextView tv = new TextView(this);    
  431.         tv.setText("LED 1 is On.");    
  432.         setContentView(tv);    
  433.     }    
  434. }  </pre><br>  
  435. <p></p>  
  436. <h2><a name="t16"></a>五、实验中需要注意的问题</h2>  
  437. <p></p>  
  438. <p>将下载后的源码放到你的android源码目录下,然后编译系统。本实验用的android版本为2.1。实验的过程中大致出现过以下几个问题:</p>  
  439. <h3><a name="t17"></a>1、目标系统中没有生成LedClient.apk或LedTest.apk应用程序</h3>  
  440. <p>编译完成后,没有在目标系统的system/app/目录下找到LedClient.apk或LedTest应用程序。只有通过单独编译LedClient或LedTest才能在目标目录中生成。方法如下:</p>  
  441. <p>#mmm  mokoid-read-only/apps/LedTest/ </p>  
  442. <p>检查原因后发现mokoid-read-only/apps/LedTest/Android.mk </p>  
  443. <p>LOCAL_MODULES_TAGS :=user</p>  
  444. <p>而我们的s5pc100系统在配置时tapas时选择的是eng,所以没有装载到目标系统</p>  
  445. <p>所以修改LedTest和LedClient的Android.mk</p>  
  446. <p>LOCAL_MODULES_TAGS :=user  eng</p>  
  447. <p>再次编译即可自动装载到目标系统/system/app/目录下。</p>  
  448. <h3><a name="t18"></a>2、启动后没有图标,找不到应用程序</h3>  
  449. <p>    目标系统启动后找不到两个应用程序的图标。仔细阅读logcat输出的信息发现:</p>  
  450. <p>E/PackageManager( 2717): Package com.mokoid.LedClient requires unavailable shared library com.mokoid.server; failing!</p>  
  451. <p>原因是找不到 com.mokoid.server。检查mokoid-read-only/frameworks/base/Android.mk发现系统将LedManager和LedService编译成 mokoid.jar库文件。为了让应用程序可以访问到这个库,需要通过com.mokoid.server.xml 来设定其对应关系。解决方法:拷贝com.mokoid.server.xml到目标系统的system/etc/permissions/目录下</p>  
  452. <p>此时两个应用的程序的图标都正常出现了。</p>  
  453. <p></p>  
  454. <h3><a name="t19"></a>3、需要针对你的目标平台修改HAL的Makefile</h3>  
  455. <p></p>  
  456. <p>修改mokoid-read-only/hardware/modules/led/Android.mk</p>  
  457. <p>LOCAL_MODULE := led.default</p>  
  458. <h3><a name="t20"></a>4、在eclipse中编译不了LedSystemServer.java</h3>  
  459. <p>原因是程序中要用到ServiceManager.addService,这需要系统权限。</p>  
  460. <p>解决方法可以把应用程序放入Android源码中编译,并确保以下两点:</p>  
  461. <p>    (1)在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。</p>  
  462. <p>    (2)修改Android 加入LOCAL_CERTIFICATE := platform.</p>  
  463. <p>当然:mokoid工程源码中已经做了这些。</p>  
  464. <p><br>  
  465. </p>  
  466. <p>最后,附上<span style="color:rgb(51,51,51); font-family:宋体; font-size:14px; line-height:26px; text-align:left">Jollen的一些资料,<a href="http://www.slideshare.net/jollen/jollens-presentation-introducing-android-lowlevel">PPT</a>,<a href="http://www.jollen.org/blog/android_os/">blog</a>,<a href="http://www.jollen.org/Android/">androidmainpage</a>。</span></p>  
  467. <br>  
  468. <br>  
  469. <p class="PreformattedText" style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left; margin-top:0cm; margin-right:0cm; margin-bottom:0pt; margin-left:0cm">  
  470. <span style="font-size:10.5pt; font-family:宋体"><span lang="EN-US"><br>  
  471. </span></span></p>  
  472. <br>  
  473. <br>  
  474. <br>  
  475. <span style="color:rgb(51,51,51); font-family:宋体; line-height:26px; text-align:left; font-size:13px"></span>  
  476. <pre></pre>  

原创粉丝点击