一、本文源自刘洪涛,实际上源自台湾的Jollen的mokoid工程代码。
二、HAL介绍
现有HAL架构由Patrick Brady (Google) 在2008 Google I/O演讲中提出的,如下图。
![Android HAL实例解析_第1张图片](http://img.e-com-net.com/image/info5/bb8f0f997dec411b9c1a22f69c514a23.jpg)
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等。
目前存在两种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、结构分析
- |-- 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种方式应用程序实现代码
- |-- 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
- | `-- modules
- | |-- Android.mk
- | |-- include
- | | `-- mokoid
- | | `-- led.h
- | `-- led
- | |-- Android.mk
- | `-- led.c //led stub 硬件控制代码
- |-- driver
- | `-- led
- | |-- Makefile
- | `-- led_drv.c //led driver
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 HAL实例解析_第4张图片](http://img.e-com-net.com/image/info5/a699438bc52c45739200f7bb3ea592b4.jpg)
上面两种方法应该说是各有优缺点,第一种方法简单高效,但不正规。第二种方法实现起来比较复杂,但更符合目前的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
- <pre name="code" class="cpp"> struct led_module_t {
- struct hw_module_t common;
- };
-
- struct led_control_device_t {
-
- struct hw_device_t common;
-
- int fd;
-
- int (*set_on)(struct led_control_device_t *dev, int32_t led);
- int (*set_off)(struct led_control_device_t *dev, int32_t led);
- };
- #define LED_HARDWARE_MODULE_ID "led"
-
- <pre></pre>
- <p></p>
- <pre></pre>
- <p></p>
- <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>
- <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>
- <pre name="code" class="cpp" style="font-family: 宋体; font-size: 10.5pt; ">#define LOG_TAG "MokoidLedStub"
- #include <hardware/hardware.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <cutils/log.h>
- #include <cutils/atomic.h>
-
- #include "../include/mokoid/led.h"
-
- int fd;
- #define GPG3DAT2_ON 0x4800 //ioctl控制命令
- #define GPG3DAT2_OFF 0x4801
- int led_device_close(struct hw_device_t* device)
- {
- struct led_control_device_t* ctx = (struct led_control_device_t*)device;
- if (ctx) {
- free(ctx);
- }
- close(fd);
- return 0;
- }
- int led_on(struct led_control_device_t *dev, int32_t led)
- {
- LOGI("LED Stub: set %d on.", led);
- ioctl(fd,GPG3DAT2_ON,NULL);
- return 0;
- }
- int led_off(struct led_control_device_t *dev, int32_t led)
- {
- LOGI("LED Stub: set %d off.", led);
- return 0;
- }
- static int led_device_open(const struct hw_module_t* module, const char* name,
- struct hw_device_t** device)
- {
- struct led_control_device_t *dev;
- dev = (struct led_control_device_t *)malloc(sizeof(*dev));
- memset(dev, 0, sizeof(*dev));
- dev->common.tag = HARDWARE_DEVICE_TAG;
- dev->common.version = 0;
- dev->common.module = module;
- dev->common.close = led_device_close;
- dev->set_on = led_on;
- dev->set_off = led_off;
- *device = &dev->common;
-
- if((fd=open("/dev/led",O_RDWR))==-1)
- {
- LOGE("LED open error");
- }
- else
- LOGI("open ok");
- success:
- return 0;
- }
- static struct hw_module_methods_t led_module_methods = {
- open: led_device_open
- };
- const struct led_module_t HAL_MODULE_INFO_SYM = {
-
- common: {
- tag: HARDWARE_MODULE_TAG,
- version_major: 1,
- version_minor: 0,
- id: LED_HARDWARE_MODULE_ID,
- name: "Sample LED Stub",
- author: "The Mokoid Open Source Project",
- methods: &led_module_methods,
-
- }
-
- };
- </pre><br>
- <br>
- <p></p>
- <h4 style="font-family:宋体; font-size:10.5pt"><a name="t9"></a>(2)JNI层</h4>
- <p></p>
- <p style="font-family:宋体; font-size:10.5pt">文件:mokoid-read-only/frameworks/base/service/jni/com_mokoid_server_LedService.cpp</p>
- <p></p>
- <pre name="code" class="cpp" style="font-family: 宋体; font-size: 10.5pt; ">struct led_control_device_t *sLedDevice = NULL;
-
- static jboolean mokoid_setOn(JNIEnv* env, jobject thiz, jint led)
- {
- LOGI("LedService JNI: mokoid_setOn() is invoked.");
-
- if (sLedDevice == NULL) {
- LOGI("LedService JNI: sLedDevice was not fetched correctly.");
- return -1;
- } else {
- return sLedDevice->set_on(sLedDevice, led);
- }
- }
-
- static jboolean mokoid_setOff(JNIEnv* env, jobject thiz, jint led)
- {
- LOGI("LedService JNI: mokoid_setOff() is invoked.");
-
-
- if (sLedDevice == NULL) {
- LOGI("LedService JNI: sLedDevice was not fetched correctly.");
- return -1;
- } else {
- return sLedDevice->set_off(sLedDevice, led);
- }
- }
-
-
- static inline int led_control_open(const struct hw_module_t* module,
- struct led_control_device_t** device) {
- return module->methods->open(module,
- LED_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
-
- }
-
- static jboolean mokoid_init(JNIEnv *env, jclass clazz)
- {
- led_module_t* module;
- LOGI("jni init-----------------------.");
- if (hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) {
-
- LOGI("LedService JNI: LED Stub found.");
- if (led_control_open(&module->common, &sLedDevice) == 0) {
-
- LOGI("LedService JNI: Got Stub operations.");
- return 0;
- }
- }
-
- LOGE("LedService JNI: Get Stub operations failed.");
- return -1;
- }
-
-
-
-
-
-
- static const JNINativeMethod gMethods[] = {
- { "_init", "()Z", (void *)mokoid_init },
- { "_set_on", "(I)Z", (void *)mokoid_setOn },
- { "_set_off", "(I)Z", (void *)mokoid_setOff },
- };
-
-
-
-
-
-
- static int registerMethods(JNIEnv* env) {
- static const char* const kClassName =
- "com/mokoid/server/LedService";
- jclass clazz;
-
- clazz = env->FindClass(kClassName);
- if (clazz == NULL) {
- LOGE("Can't find class %s/n", kClassName);
- return -1;
- }
-
- if (env->RegisterNatives(clazz, gMethods,
- sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)
- {
- LOGE("Failed registering methods for %s/n", kClassName);
- return -1;
- }
-
- return 0;
- }
- jint JNI_OnLoad(JavaVM* vm, void* reserved) {
- JNIEnv* env = NULL;
- jint result = -1;
- LOGI("JNI_OnLoad LED");
- if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
- LOGE("ERROR: GetEnv failed/n");
- goto fail;
- }
- assert(env != NULL);
- if (registerMethods(env) != 0) {
- LOGE("ERROR: PlatformLibrary native registration failed/n");
- goto fail;
- }
-
- result = JNI_VERSION_1_4;
- fail:
- return result;
- } </pre>
- <p></p>
- <h4 style="font-family:宋体; font-size:10.5pt"><a name="t10"></a>3)service (属于Framework层)</h4>
- <p></p>
- <p style="font-family:宋体; font-size:10.5pt">文件:frameworks/base/service/java/com/mokoid/server/LedService.java</p>
- <pre name="code" class="cpp" style="font-family: 宋体; font-size: 10.5pt; ">package com.mokoid.server;
- import android.util.Config;
- import android.util.Log;
- import android.content.Context;
- import android.os.Binder;
- import android.os.Bundle;
- import android.os.RemoteException;
- import android.os.IBinder;
- import mokoid.hardware.ILedService;
- public final class LedService extends ILedService.Stub {
-
- static {
- System.load("/system/lib/libmokoid_runtime.so");
- }
- public LedService() {
- Log.i("LedService", "Go to get LED Stub...");
- _init();
- }
-
-
-
- public boolean setOn(int led) {
- Log.i("MokoidPlatform", "LED On");
- return _set_on(led);
- }
- public boolean setOff(int led) {
- Log.i("MokoidPlatform", "LED Off");
- return _set_off(led);
- }
- private static native boolean _init();
- private static native boolean _set_on(int led);
- private static native boolean _set_off(int led);
- } </pre><br>
- <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>
- <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>
- <p style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left">
- <span style="font-size:10.5pt; font-family:宋体">文件:<span lang="EN-US">apps/LedClient/src/com/mokoid/LedClient/LedClient.java</span></span></p>
- <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">
- </p>
- <pre name="code" class="cpp">package com.mokoid.LedClient;
- import com.mokoid.server.LedService;
- import android.app.Activity;
- import android.os.Bundle;
- import android.widget.TextView;
-
- public class LedClient extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- LedService ls = new LedService();
- ls.setOn(1);
- ls.setOff(2);
-
- TextView tv = new TextView(this);
- tv.setText("LED 1 is on. LED 2 is off.");
- setContentView(tv);
- }
- } </pre>
- <p></p>
- <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>
- <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>
- <p></p>
- <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">
- <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>
- <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>
- <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>
- <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">
- <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>
- <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">
- <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>
- <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">
- </p>
- <pre name="code" class="cpp">package mokoid.hardware;
- import android.content.Context;
- import android.os.Binder;
- import android.os.Bundle;
- import android.os.Parcelable;
- import android.os.ParcelFileDescriptor;
- import android.os.Process;
- import android.os.RemoteException;
- import android.os.Handler;
- import android.os.Message;
- import android.os.ServiceManager;
- import android.util.Log;
- import mokoid.hardware.ILedService;
-
-
-
-
- public class LedManager
- {
- private static final String TAG = "LedManager";
- private ILedService mLedService;
- public LedManager() {
- mLedService = ILedService.Stub.asInterface(ServiceManager.getService("led"));
-
-
-
-
- if (mLedService != null) {
- Log.i(TAG, "The LedManager object is ready.");
- }
- }
- public boolean LedOn(int n) {
- boolean result = false;
- try {
- result = mLedService.setOn(n);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in LedManager.LedOn:", e);
- }
- return result;
- }
- public boolean LedOff(int n) {
- boolean result = false;
- try {
- result = mLedService.setOff(n);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in LedManager.LedOff:", e);
- }
- return result;
- }
- } </pre>
- <p></p>
- <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">
- <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>
- <p style="color:rgb(51,51,51); font-family:Arial; font-size:15px; line-height:26px; text-align:left">
- <span style="font-size:10.5pt; font-family:宋体"></span></p>
- <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">
- <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>
- <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">
- <span lang="EN-US"></span></p>
- <pre name="code" class="cpp" style="font-family: 宋体; font-size: 10.5pt; ">package mokoid.hardware;
- interface ILedService
- {
- boolean setOn(int led);
- boolean setOff(int led);
- }
-
- <p></p>
- <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>
- <span style="font-size:13px"><span style="font-family:宋体"><br>
- (<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>
- <p></p>
- <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">
- <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>
- <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">
- <span style="font-size:10.5pt; font-family:宋体"><span lang="EN-US"></span></span></p>
- <pre name="code" class="cpp">package com.mokoid.LedTest;
- import com.mokoid.server.LedService;
- import android.os.IBinder;
- import android.os.ServiceManager;
- import android.util.Log;
- import android.app.Service;
- import android.content.Context;
- import android.content.Intent;
-
- public class LedSystemServer extends Service {
-
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- public void onStart(Intent intent, int startId) {
- Log.i("LedSystemServer", "Start LedService...");
-
-
- LedService ls = new LedService();
- try {
- ServiceManager.addService("led", ls);
- } catch (RuntimeException e) {
- Log.e("LedSystemServer", "Start LedService failed.");
- }
- }
- } </pre>
- <p></p>
- <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>
- <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>
- <p></p>
- <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">
- <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>
- <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">
- <span style="font-size:10.5pt; font-family:宋体"><span lang="EN-US"></span></span></p>
- <pre name="code" class="cpp">package com.mokoid.LedTest;
- import mokoid.hardware.LedManager;
- import com.mokoid.server.LedService;
- import android.app.Activity;
- import android.os.Bundle;
- import android.util.Log;
- import android.widget.TextView;
- import android.widget.Button;
- import android.content.Intent;
- import android.view.View;
-
- public class LedTest extends Activity implements View.OnClickListener {
- private LedManager mLedManager = null;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- startService(new Intent("com.mokoid.systemserver"));
- Button btn = new Button(this);
- btn.setText("Click to turn LED 1 On");
- btn.setOnClickListener(this);
- setContentView(btn);
- }
- public void onClick(View v) {
-
- if (mLedManager == null) {
- Log.i("LedTest", "Creat a new LedManager object.");
- mLedManager = new LedManager();
- }
- if (mLedManager != null) {
- Log.i("LedTest", "Got LedManager object.");
- }
-
-
-
- mLedManager.LedOn(1);
- TextView tv = new TextView(this);
- tv.setText("LED 1 is On.");
- setContentView(tv);
- }
- } </pre><br>
- <p></p>
- <h2><a name="t16"></a>五、实验中需要注意的问题</h2>
- <p></p>
- <p>将下载后的源码放到你的android源码目录下,然后编译系统。本实验用的android版本为2.1。实验的过程中大致出现过以下几个问题:</p>
- <h3><a name="t17"></a>1、目标系统中没有生成LedClient.apk或LedTest.apk应用程序</h3>
- <p>编译完成后,没有在目标系统的system/app/目录下找到LedClient.apk或LedTest应用程序。只有通过单独编译LedClient或LedTest才能在目标目录中生成。方法如下:</p>
- <p>#mmm mokoid-read-only/apps/LedTest/ </p>
- <p>检查原因后发现mokoid-read-only/apps/LedTest/Android.mk </p>
- <p>LOCAL_MODULES_TAGS :=user</p>
- <p>而我们的s5pc100系统在配置时tapas时选择的是eng,所以没有装载到目标系统</p>
- <p>所以修改LedTest和LedClient的Android.mk</p>
- <p>LOCAL_MODULES_TAGS :=user eng</p>
- <p>再次编译即可自动装载到目标系统/system/app/目录下。</p>
- <h3><a name="t18"></a>2、启动后没有图标,找不到应用程序</h3>
- <p> 目标系统启动后找不到两个应用程序的图标。仔细阅读logcat输出的信息发现:</p>
- <p>E/PackageManager( 2717): Package com.mokoid.LedClient requires unavailable shared library com.mokoid.server; failing!</p>
- <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>
- <p>此时两个应用的程序的图标都正常出现了。</p>
- <p></p>
- <h3><a name="t19"></a>3、需要针对你的目标平台修改HAL的Makefile</h3>
- <p></p>
- <p>修改mokoid-read-only/hardware/modules/led/Android.mk</p>
- <p>LOCAL_MODULE := led.default</p>
- <h3><a name="t20"></a>4、在eclipse中编译不了LedSystemServer.java</h3>
- <p>原因是程序中要用到ServiceManager.addService,这需要系统权限。</p>
- <p>解决方法可以把应用程序放入Android源码中编译,并确保以下两点:</p>
- <p> (1)在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。</p>
- <p> (2)修改Android 加入LOCAL_CERTIFICATE := platform.</p>
- <p>当然:mokoid工程源码中已经做了这些。</p>
- <p><br>
- </p>
- <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>
- <br>
- <br>
- <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">
- <span style="font-size:10.5pt; font-family:宋体"><span lang="EN-US"><br>
- </span></span></p>
- <br>
- <br>
- <br>
- <span style="color:rgb(51,51,51); font-family:宋体; line-height:26px; text-align:left; font-size:13px"></span>
- <pre></pre>