Android HAL实例分析

本文深入剖析了Android HAL(硬件抽象层)的工作原理及其在Android系统中的应用。通过具体实例,详细介绍了HAL的架构设计、模块开发流程以及与上层应用的交互方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

华清远见讲师   刘洪涛

一、概述

    本文 希望通 分析台湾的Jollen的mokoid 工程代 ,和在s5pc100平台上 实现过 程种遇到的问题,解析Andorid HAL的 开发 方法。     

二、 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架构”。两 框架如下 所示。

                   3.1   旧HAL 架构                              3.2  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、结构分析

|-- Android.mk  

|-- apps      //两种应用测试方法

|   |-- Android.mk

|   |-- LedClient    //直接调用service来调用jni

|   |   |-- AndroidManifest.xml

|   |   |-- Android.mk

|   |   `-- src

|   |       `-- com

|   |           `-- mokoid

|   |               `-- LedClient

|   |                   `-- LedClient.java      // 第1种方式应用程序实现代码

|   `-- LedTest        //通过manager来调用jni

|       |-- AndroidManifest.xml

|       |-- Android.mk

|       `-- src

|           `-- com

|               `-- mokoid

|                   `-- LedTest

|                       |-- LedSystemServer.java  //开启了一个后台service,下文会有解释

|                       `-- LedTest.java    //第2种方式应用程序实现代码

|-- dma6410xp   //这个目录可以 不要

|   |-- AndroidBoard.mk

|   |-- AndroidProducts.mk

|   |-- BoardConfig.mk

|   |-- dma6410xp.mk

|   |-- init.dma6410xp.rc

|   |-- init.goldfish.sh

|   `-- init.rc

|-- frameworks     //框架代 码

|   |-- Android.mk

|   `-- base

|       |-- Android.mk

|       |-- core

|       |   `-- java

|       |       `-- mokoid

|       |           `-- hardware

|       |               |-- ILedService.aidl

|       |               `-- LedManager.java     //实现了Manager,给第2种方 法用

|       `-- service  

|           |-- Android.mk

|           |-- com.mokoid.server.xml

|           |-- java

|           |   `-- com

|           |       `-- mokoid

|           |           `-- server

|           |               `-- LedService.java    //Framework service代码

|           `-- jni

|               |-- Android.mk

|               `-- com_mokoid_server_LedService.cpp  //jni 代码

|-- hardware

|   |-- Android.mk

|   |-- libled

|   |   |-- Android.mk

|   |   `-- libled.c

|   `-- modules

|       |-- Android.mk

|       |-- include

|       |   `-- mokoid

|       |       `-- led.h

|       `-- led

|           |-- Android.mk

|           `-- led.c       //led stub 硬件控制代码

`-- 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需要涉及的是三个关键结构体:

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. };  

2 JNI

文 件: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. }  

 
3 service  属于 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. }  

 
4 APP 测试程序 (属于 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. }  

5 、第二种方法 经过 Manager 调用 service

    HAL JNI 两层和第一种方法一样 所以后面只分析其他的层次。

1Manager 属于 Framework

    APP 通过这个 Manager service 通讯。

文件:mokoid-read-only /frameworks/base/core/java/mokoid/hardware/LedManager.java

 

  1. package mokoid.hardware;  
  2. import android.content.Context;  
  3. import android.os.Binder;  
  4. import android.os.Bundle;  
  5. import android.os.Parcelable;  
  6. import android.os.ParcelFileDescriptor;  
  7. import android.os.Process;  
  8. import android.os.RemoteException;  
  9. import android.os.Handler;  
  10. import android.os.Message;  
  11. import android.os.ServiceManager;  
  12. import android.util.Log;  
  13. import mokoid.hardware.ILedService;  
  14.   
  15. /*  
  16.  * Class that lets you access the Mokoid LedService.  
  17.  */   
  18. public   class  LedManager  
  19. {  
  20.     private   static  final String TAG =  "LedManager" ;  
  21.     private  ILedService mLedService;  
  22.     public  LedManager() {  
  23.         mLedService = ILedService.Stub.asInterface(ServiceManager.getService("led" ));  
  24. /*  
  25. *这一步是关键,利用ServiceManager获取到LedService,从而调用它提供的方法。这要求 LedService必  
  26. * 须已经添加到了ServiceManager中,这个过程将在App中的一个service进程中完成。  
  27. */   
  28.     if  (mLedService !=  null ) {  
  29.             Log.i(TAG, "The LedManager object is ready." );  
  30.     }  
  31.     }  
  32.     public  boolean LedOn( int  n) {  
  33.         boolean result = false ;  
  34.         try  {  
  35.             result = mLedService.setOn(n);  
  36.         } catch  (RemoteException e) {  
  37.             Log.e(TAG, "RemoteException in LedManager.LedOn:" , e);  
  38.         }  
  39.         return  result;  
  40.     }  
  41.     public  boolean LedOff( int  n) {  
  42.         boolean result = false ;  
  43.         try  {  
  44.             result = mLedService.setOff(n);  
  45.         } catch  (RemoteException e) {  
  46.             Log.e(TAG, "RemoteException in LedManager.LedOff:" , e);  
  47.         }  
  48.         return  result;  
  49.     }  
  50. }  

  

因为LedServiceLedManager 在不同的进 程,所以要考虑到进程通讯的问题。Manager 通过增加一个aidl 文件来描述通讯接口。

文件 mokoid-read-only/frameworks/base/core/java/mokoid/hardware/ILedService.aidl

  1. package mokoid.hardware;  
  2. interface  ILedService  
  3. {  
  4.     boolean setOn(int  led);  
  5.     boolean setOff(int  led);  
  6. }  
  7. //系统的aidl工具会将ILedService.aidl文件ILedService.java文件,实现了 ILedService   

  
2SystemServer 属于 APP

文件:mokoid-read-only/apps/LedTest/src/com/mokoid/LedTest/LedSystemServer.java

  1. package com.mokoid.LedTest;  
  2. import com.mokoid.server.LedService;  
  3. import android.os.IBinder;  
  4. import android.os.ServiceManager;  
  5. import android.util.Log;  
  6. import android.app.Service;  
  7. import android.content.Context;  
  8. import android.content.Intent;  
  9.   
  10. public   class  LedSystemServer extends Service {  
  11. //注意这里的Service是APP中的概念,代表一个后台进 程。注意区别和Framework中的service的概念。   
  12.     @Override  
  13.     public  IBinder onBind(Intent intent) {  
  14.         return   null ;  
  15.     public   void  onStart(Intent intent,  int  startId) {  
  16.         Log.i("LedSystemServer""Start LedService..." );  
  17.   
  18.     /* Please also see SystemServer.java for your interests. */   
  19.     LedService ls = new  LedService();  
  20.         try  {  
  21.             ServiceManager.addService("led" , ls);   // 将LedService添加到ServiceManager中   
  22.         } catch  (RuntimeException e) {  
  23.             Log.e("LedSystemServer""Start LedService failed." );  
  24.         }  
  25.     }  
  26. }  

3APP 测试程序 属于 APP

文件:mokoid-read-only/apps/LedTest/src/com/mokoid/LedTest/LedTest.java

  1. package com.mokoid.LedTest;  
  2. import mokoid.hardware.LedManager;  
  3. import com.mokoid.server.LedService;  
  4. import android.app.Activity;  
  5. import android.os.Bundle;  
  6. import android.util.Log;  
  7. import android.widget.TextView;  
  8. import android.widget.Button;  
  9. import android.content.Intent;  
  10. import android.view.View;  
  11.   
  12. public   class  LedTest extends Activity implements View.OnClickListener {  
  13.     private  LedManager mLedManager =  null ;  
  14.     @Override  
  15.     public   void  onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         // Start LedService in a seperated process.   
  18.         startService(new  Intent( "com.mokoid.systemserver" )); //开启后台进程   
  19.         Button btn = new  Button( this );  
  20.         btn.setText("Click to turn LED 1 On" );  
  21.      btn.setOnClickListener(this );  
  22.         setContentView(btn);  
  23.     }  
  24.     public   void  onClick(View v) {  
  25.         // Get LedManager.   
  26.         if  (mLedManager ==  null ) {  
  27.         Log.i("LedTest""Creat a new LedManager object." );  
  28.         mLedManager = new  LedManager();   //实例化Framework层中的Manager   
  29.         }      
  30.         if  (mLedManager !=  null ) {  
  31.         Log.i("LedTest""Got LedManager object." );  
  32.      }  
  33.         /** Call methods in LedService via proxy object   
  34.          * which is provided by LedManager.   
  35.          */   
  36.         mLedManager.LedOn(1);  
  37.         TextView tv = new  TextView( this );  
  38.         tv.setText("LED 1 is On." );  
  39.         setContentView(tv);  
  40.     }  
  41. }  

五、实验中需要注意的问题

将下载后的源码放到你的 android 源码目录下 然后编译系统。本实验用的android版本为2.1。实验 的过程中大致出现过以下几个问题:

1、 中没有生成 LedClient.apk或LedTest.apk 用程序

编 译完成后,没有在目标系统的system/app/目录下找到LedClient.apk或LedTest应用程序。只有通过单独编译LedClient 或LedTest才能在目标目录中生成。方法如下:

#mmm  mokoid-read-only/apps/LedTest/ 

检 查原因后发现mokoid-read-only/apps/LedTest/Android.mk 

LOCAL_MODULES_TAGS :=user

而 我们的s5pc100系统在配置时tapas时选择的是eng,所以没有装载到目标系统

所 以修改LedTest和LedClient的Android.mk

LOCAL_MODULES_TAGS :=user  eng

再次编译即可自动装载到目标系统/system/app /目录下。

2、 后没有 图标 ,找不到 应用 程序

    目标 系统启动后找不到两个应用程序的图标。 细阅读 logcat 出的信息 发现

E/PackageManager( 2717): Package com.mokoid.LedClient requires unavailable shared library com.mokoid.server; failing!

原因是 找不到 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/ 目 录下

此 时两个应用的程序的图标都正常出现了。

3 提示找不到 JNI_OnLoad

按照以前的实验加入下列代码:

  1. static   int  registerMethods(JNIEnv* env) {  
  2.     static   const   charconst  kClassName = "com/mokoid/server/LedService" ;  
  3.     jclass clazz;   
  4.         /* look up the class */   
  5.         clazz = env->FindClass(kClassName);  
  6.         if  (clazz == NULL) {  
  7.             LOGE("Can't find class %s/n" , kClassName);  
  8.             return  -1;  
  9.         }  
  10.             /* register all the methods */   
  11.         if  (env->RegisterNatives(clazz, gMethods,  
  12.                     sizeof (gMethods) /  sizeof (gMethods[0])) != JNI_OK)  
  13.         {  
  14.             LOGE("Failed registering methods for %s/n" , kClassName);  
  15.             return  -1;  
  16.         }  
  17.     /* fill out the rest of the ID cache */   
  18.         return  0;  
  19. }   
  20. /*  
  21.  * This is called by the VM when the shared library is first loaded.  
  22.  */    
  23. jint JNI_OnLoad(JavaVM* vm, void * reserved) {  
  24.         JNIEnv* env = NULL;  
  25.         jint result = -1;  
  26.         LOGI("JNI_OnLoad LED" );  
  27.         if  (vm->GetEnv(( void **) &env, JNI_VERSION_1_4) != JNI_OK) {  
  28.             LOGE("ERROR: GetEnv failed/n" );  
  29.             goto  fail;  
  30.         }  
  31.         assert(env != NULL);  
  32.         if  (registerMethods(env) != 0) {  
  33.             LOGE("ERROR: PlatformLibrary native registration failed/n" );  
  34.             goto  fail;  
  35.         }  
  36.         /* success -- return valid version number */       
  37.         result = JNI_VERSION_1_4;  
  38. fail:  
  39.         return  result;  
  40. }   

4 需要 针对 你的目 平台修改HAL的Makefile

修 改mokoid-read-only/hardware/modules/led/Android.mk

LOCAL_MODULE := led.default

5 、在 eclipse 编译 不了 LedSystemServer.java

原因是程序中要用到 ServiceManager.addService,这需要系统权限。

解决方法可以把应用程序放入Android 源码中编译,并确保以下两点:

    1 在应用程序的 AndroidManifest.xml 中的 manifest 节点中加入 android:sharedUserId="android.uid.system" 这个属性。

    2 修改 Android 加入 LOCAL_CERTIFICATE := platform.

当 然: mokoid工程源码中已经 做了这些。

 

 

  (2) 经过 Manager调用service

 

此贴是对刘洪涛老师大作的转载,如有冒犯,敬请原谅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值