九鼎创展论坛中文版English
登录 | 立即注册 设为首页收藏本站 切换到宽版
查看: 2213|回复: 0

Android HAL实例解析

[复制链接]
发表于 2013-2-28 11:24:53 | 显示全部楼层 |阅读模式

一、概述    本文希望通过分析台湾的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 Layerl  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、结构分析

  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. |-- dma6410xp   //这个目录可以不要
  22. |   |-- AndroidBoard.mk
  23. |   |-- AndroidProducts.mk
  24. |   |-- BoardConfig.mk
  25. |   |-- dma6410xp.mk
  26. |   |-- init.dma6410xp.rc
  27. |   |-- init.goldfish.sh
  28. |   `-- init.rc
  29. |-- frameworks     //框架代码
  30. |   |-- Android.mk
  31. |   `-- base
  32. |       |-- Android.mk
  33. |       |-- core
  34. |       |   `-- java
  35. |       |       `-- mokoid
  36. |       |           `-- hardware
  37. |       |               |-- ILedService.aidl
  38. |       |               `-- LedManager.java     //实现了Manager,给第2种方法用
  39. |       `-- service  
  40. |           |-- Android.mk
  41. |           |-- com.mokoid.server.xml
  42. |           |-- java
  43. |           |   `-- com
  44. |           |       `-- mokoid
  45. |           |           `-- server
  46. |           |               `-- LedService.java    //Framework service代码
  47. |           `-- jni
  48. |               |-- Android.mk
  49. |               `-- com_mokoid_server_LedService.cpp  //jni代码
  50. |-- hardware
  51. |   |-- Android.mk
  52. |   |-- libled
  53. |   |   |-- Android.mk
  54. |   |   `-- libled.c
  55. |   `-- modules
  56. |       |-- Android.mk
  57. |       |-- include
  58. |       |   `-- mokoid
  59. |       |       `-- led.h
  60. |       `-- led
  61. |           |-- Android.mk
  62. |           `-- led.c       //led stub 硬件控制代码
  63. `-- 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. <font color="#333333"><font face="Arial">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
  16. </font></font>
复制代码
文件: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. static jboolean mokoid_setOn(JNIEnv* env, jobject thiz, jint led)
  3. {
  4.     LOGI("LedService JNI: mokoid_setOn() is invoked.");

  5.     if (sLedDevice == NULL) {
  6.         LOGI("LedService JNI: sLedDevice was not fetched correctly.");
  7.         return -1;
  8.     } else {
  9.         return sLedDevice->set_on(sLedDevice, led);//调用hal层的注册的方法
  10.     }
  11. }

  12. static jboolean mokoid_setOff(JNIEnv* env, jobject thiz, jint led)
  13. {
  14.     LOGI("LedService JNI: mokoid_setOff() is invoked.");


  15.     if (sLedDevice == NULL) {
  16.         LOGI("LedService JNI: sLedDevice was not fetched correctly.");
  17.         return -1;
  18.     } else {
  19.         return sLedDevice->set_off(sLedDevice, led); //调用hal层的注册的方法
  20.     }
  21. }

  22. /** helper APIs */
  23. static inline int led_control_open(const struct hw_module_t* module,
  24.         struct led_control_device_t** device) {
  25.     return module->methods->open(module,
  26.             LED_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
  27. //这个过程非常重要,jni通过LED_HARDWARE_MODULE_ID找到对应的stub
  28. }

  29. static jboolean mokoid_init(JNIEnv *env, jclass clazz)
  30. {
  31.     led_module_t* module;
  32.      LOGI("jni init-----------------------.");
  33. if (hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) {
  34. //根据LED_HARDWARE_MODULE_ID找到hw_module_t,参考hal层的实现
  35.         LOGI("LedService JNI: LED Stub found.");
  36.         if (led_control_open(&module->common, &sLedDevice) == 0) {  
  37.     //通过hw_module_t找到led_control_device_t
  38.                 LOGI("LedService JNI: Got Stub operations.");
  39.             return 0;
  40.         }
  41.     }

  42.     LOGE("LedService JNI: Get Stub operations failed.");
  43.     return -1;
  44. }

  45. /*
  46. * Array of methods.
  47. * Each entry has three fields: the name of the method, the method
  48. * signature, and a pointer to the native implementation.
  49. */
  50. static const JNINativeMethod gMethods[] = {
  51.     { "_init",                  "()Z",        (void *)mokoid_init },//Framework层调用_init时促发
  52.     { "_set_on",        "(I)Z", (void *)mokoid_setOn },
  53.     { "_set_off",       "(I)Z", (void *)mokoid_setOff },
  54. };
  55. /*
  56. *JNINativeMethod是jni层注册的方法,Framework层可以使用这些方法
  57. *_init 、_set_on、_set_off是在Framework中调用的方法名称,函数的类型及返回值如下:
  58. *()Z   无参数    返回值为bool型
  59. * (I)Z   整型参数  返回值为bool型
  60. */
  61. static int registerMethods(JNIEnv* env) {
  62.                 static const char* const kClassName =
  63.                 "com/mokoid/server/LedService";//注意:必须和你Framework层的service类名相同
  64.                 jclass clazz;
  65.       /* look up the class */
  66.                 clazz = env->FindClass(kClassName);
  67.                 if (clazz == NULL) {
  68.                                         LOGE("Can't find class %s/n", kClassName);
  69.                                         return -1;
  70.                 }
  71.         /* register all the methods */
  72.                 if (env->RegisterNatives(clazz, gMethods,
  73.                                                 sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)
  74.                 {
  75.                         LOGE("Failed registering methods for %s/n", kClassName);
  76.                         return -1;
  77.                 }
  78.         /* fill out the rest of the ID cache */
  79.                 return 0;
  80. }
  81. jint JNI_OnLoad(JavaVM* vm, void* reserved) {//Framework层加载jni库时调用
  82.                 JNIEnv* env = NULL;
  83.                 jint result = -1;
  84.                 LOGI("JNI_OnLoad LED");
  85.                      if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
  86.                         LOGE("ERROR: GetEnv failed/n");
  87.                         goto fail;
  88.                 }
  89.                     assert(env != NULL);
  90.                 if (registerMethods(env) != 0) { //注册你的JNINativeMethod
  91.                         LOGE("ERROR: PlatformLibrary native registration failed/n");
  92.                         goto fail;
  93.                 }
  94.                 /* success -- return valid version number */        
  95.                 result = JNI_VERSION_1_4;
  96. fail:
  97.                 return result;
  98. }
复制代码
(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. public class LedClient extends Activity {
  7.     @Override
  8.     public void onCreate(Bundle savedInstanceState) {
  9.         super.onCreate(savedInstanceState);
  10.         // Call an API on the library.
  11.         LedService ls = new LedService();  //实例化LedService
  12.         ls.setOn(1);                       //通过LedService提供的方法,控制底层硬件
  13.         ls.setOff(2);
  14.         
  15.         TextView tv = new TextView(this);
  16.         tv.setText("LED 1 is on. LED 2 is off.");
  17.         setContentView(tv);
  18.     }
  19. }
复制代码
5、第二种方法:经过Manager调用service

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

(1)Manager (属于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. * Class that lets you access the Mokoid LedService.
  16. */
  17. public class LedManager
  18. {
  19.     private static final String TAG = "LedManager";
  20.     private ILedService mLedService;
  21.     public LedManager() {
  22.         mLedService = ILedService.Stub.asInterface(ServiceManager.getService("led"));
  23. /*
  24. *这一步是关键,利用ServiceManager获取到LedService,从而调用它提供的方法。这要求LedService必
  25. *须已经添加到了ServiceManager中,这个过程将在App中的一个service进程中完成。
  26. */
  27.         if (mLedService != null) {
  28.             Log.i(TAG, "The LedManager object is ready.");
  29.         }
  30.     }
  31.     public boolean LedOn(int n) {
  32.         boolean result = false;
  33.         try {
  34.             result = mLedService.setOn(n);
  35.         } catch (RemoteException e) {
  36.             Log.e(TAG, "RemoteException in LedManager.LedOn:", e);
  37.         }
  38.         return result;
  39.     }
  40.     public boolean LedOff(int n) {
  41.         boolean result = false;
  42.         try {
  43.             result = mLedService.setOff(n);
  44.         } catch (RemoteException e) {
  45.             Log.e(TAG, "RemoteException in LedManager.LedOff:", e);
  46.         }
  47.         return result;
  48.     }
  49. }
复制代码

因为LedService和LedManager在不同的进程,所以要考虑到进程通讯的问题。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
复制代码
(2)SystemServer (属于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. public class LedSystemServer extends Service {
  10. //注意这里的Service是APP中的概念,代表一个后台进程。注意区别和Framework中的service的概念。
  11.     @Override
  12.     public IBinder onBind(Intent intent) {
  13.         return null;
  14.     public void onStart(Intent intent, int startId) {
  15.         Log.i("LedSystemServer", "Start LedService...");

  16.         /* Please also see SystemServer.java for your interests. */
  17.         LedService ls = new LedService();
  18.         try {
  19.             ServiceManager.addService("led", ls);  //将LedService添加到ServiceManager中
  20.         } catch (RuntimeException e) {
  21.             Log.e("LedSystemServer", "Start LedService failed.");
  22.         }
  23.     }
  24. }
复制代码
(3)APP 测试程序(属于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. public class LedTest extends Activity implements View.OnClickListener {
  12.     private LedManager mLedManager = null;
  13.     @Override
  14.     public void onCreate(Bundle savedInstanceState) {
  15.         super.onCreate(savedInstanceState);
  16.         // Start LedService in a seperated process.
  17.         startService(new Intent("com.mokoid.systemserver"));//开启后台进程
  18.         Button btn = new Button(this);
  19.         btn.setText("Click to turn LED 1 On");
  20.          btn.setOnClickListener(this);
  21.         setContentView(btn);
  22.     }
  23.     public void onClick(View v) {
  24.         // Get LedManager.
  25.         if (mLedManager == null) {
  26.             Log.i("LedTest", "Creat a new LedManager object.");
  27.             mLedManager = new LedManager();  //实例化Framework层中的Manager
  28.         }   
  29.         if (mLedManager != null) {
  30.             Log.i("LedTest", "Got LedManager object.");
  31.          }
  32.         /** Call methods in LedService via proxy object
  33.          * which is provided by LedManager.
  34.          */
  35.         mLedManager.LedOn(1);
  36.         TextView tv = new TextView(this);
  37.         tv.setText("LED 1 is On.");
  38.         setContentView(tv);
  39.     }
  40. }
复制代码
五、实验中需要注意的问题

将下载后的源码放到你的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 char* const 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


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳市九鼎创展科技官方论坛 ( 粤ICP备11028681号-2  

GMT+8, 2020-2-17 11:30 , Processed in 0.033630 second(s), 32 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表