Android HAL實例解析

轉自:

http://blog.csdn.net/hongtao_liu/article/details/6060734

華清遠見講師  劉洪濤

一、概述

    本文希望通分析臺灣的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

 

 

    AndroidHAL實現需要通JNI(Java Native Interface),JNI簡單就是java程序可以調C/C++寫的動態鏈這樣,HAL可以使用C/C++效率更高。在Android下訪問HAL大致有以下兩方式:

 

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

 

 

 

 

 

 

(2)經過Manager調用service

 

     上面兩種方法應該說是各有優缺點,第一種方法簡單高效,但不正規。第二種方法實現起來比較複雜,但更符合目前的Android框架。第二種方法中,LegManagerLedService(java)在兩個進程中,需要通過進程通訊的方式來通訊。

     mokoid工程中實現了上述兩方法。下面將詳細紹這方法的實現原理。


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

 

[c-sharp] view plaincopy

  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

[c-sharp] view plaincopy

  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

[c-sharp] view plaincopy

  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 char* const 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

[c-sharp] view plaincopy

  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

 

[c-sharp] view plaincopy

  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

    HALJNI兩層和第一種方法一樣所以後面只分析其他的層次。

(1)Manager 屬於Framework

    APP通過這個Managerservice通訊。

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

 

[c-sharp] view plaincopy

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

  

因爲LedService和LedManager在不同的進程,所以要考慮到進程通訊的問題。Manager通過增加一個aidl文件來描述通訊接口。


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

[c-sharp] view plaincopy

  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

[c-sharp] view plaincopy

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

(3)APP 測試程序屬於APP

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

[c-sharp] view plaincopy

  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

按照以前的實驗加入下列代碼:


[c-sharp] view plaincopy

  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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章