一、代码讲解

1、 编写HAL层代码

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

下面结合代码说明这3个结构的用法


文件:weiyan/hardware/modules/include/weiyan/led.h

 


[c-sharp]  
   view plain 
   copy 
   
 
 
1. //HAL  规定不能直接使用hw_module_t结构
2. //因此需要做这么一个继承
3. struct
4. struct
5. };  
6. struct
7. //自定义一个针对led控制的结构
8. //包含hw_device_t和支持的API操作
9. struct
10. /* supporting control APIs go here */
11. intstruct
12. intstruct
13. };  
14. /*****************************************************************************/
15. struct
16. struct
17. };  
18. //定义一个MODULE_ID
19. //HAL层可以根据这个ID找到我们这个HAL Stub
20. #define LED_HARDWARE_MODULE_ID "led"

 

文件:weiyan/hardware/modules/led/led.c


[c-sharp]  
   view plain 
   copy 
   
 
 
1. intstruct
2. {  
3. structstruct
4. if
5.         free(ctx);  
6.     }  
7. return
8. }  
9. intstruct
10. {  
11. int
12. char"";  
13. int
14. if
15. "open leds fail");  
16. return
17.         }  
18. //memset(buff,'1',5);
19.     memset(buff,0,3);  
20. //灯开
21. char)led; //leds 灯号
22.       
23. sizeof(buff));  
24. "LED Stub: set %d on.", led);  
25.     close(fd);  
26. return
27. }  
28. intstruct
29. {  
30. int
31. char"";  
32. int
33. if
34. "open leds fail");  
35. return
36.         }  
37.     memset(buff,0,3);  
38. //灯关
39. char)led; //leds 灯号
40. sizeof(buff));  
41. "LED Stub: set %d off.", led);  
42.     close(fd);  
43. return
44. }  
45. staticint led_device_open(const struct hw_module_t* module, const char* name,  
46. struct
47. {  
48. struct
49. structsizeof(*dev));  
50. sizeof(*dev));  
51.     dev->common.tag =  HARDWARE_DEVICE_TAG;  
52.     dev->common.version = 0;  
53.     dev->common.module = module;  
54.     dev->common.close = led_device_close;  
55. //实例化支持的操作
56.     dev->set_off = led_off;  
57. //将实例化后的led_control_deivce_t地址返回给jni层
58. //这样jni层就可以直接调用led_on、led_off、led_device_close 方法
59.     *device = &dev->common;  
60. success:  
61. return
62. }  
63. staticstruct
64.     open: led_device_open  
65. };  
66. //向系统注册一个iD为LED_HARDWARE_MODULE_ID的stub
67. //注意这里的HAL_MODULE_INFO_SYM不能修改
68. conststruct
69.     common: {  
70.         tag: HARDWARE_MODULE_TAG,  
71.         version_major: 1,  
72.         version_minor: 0,  
73.         id: LED_HARDWARE_MODULE_ID,  
74. "Sample LED Stub",  
75. "The Mokoid Open Source Project",  
76.         methods: &led_module_methods,  
77.     }  
78. /* supporting APIs go here */
79. };

 

 

2.JNI层

 

文件:weiyan/frameworks/base/service/jni/com_mokoid_server_LedService.cpp


[c-sharp]  
   view plain 
   copy 
   
 
 
1. struct
2. static
3. "LedService JNI: weityan_setOn() is invoked.");  
4. if
5. "LedService JNI: sLedDevice was not fetched correctly.");  
6. return
7. else
8. return//调用HAL层的方法
9.     }  
10. }  
11. static
12. "LedService JNI: weiyan_setOff() is invoked.");  
13. if
14. "LedService JNI: sLedDevice was not fetched correctly.");  
15. return
16. else
17. return//调用HAL层的方法
18.     }  
19. }  
20. /** helper APIs */
21. staticint led_control_open(const struct
22. struct
23. //这个过程非常重要
24. //JNI通过LED_HARDWARE_MODULE_ID 找到对应的Stub
25. return
26. struct
27. }  
28. static
29. weiyan_init(JNIEnv *env, jclass clazz)  
30. {  
31.     led_module_t* module;  
32. //根据LED_HARDWARE_MODULE_ID找到对应的hw_module_t
33. ifconst
34. "LedService JNI: LED Stub found.");  
35. if
36. "LedService JNI: Got Stub operations.");  
37. return
38.         }  
39.     }  
40. "LedService JNI: Get Stub operations failed.");  
41. return
42. }  
43. // ----------------------------------------------------------------------------
44. /*
45.  *JNINativeMethod是JNI层注册的方法
46.  *Framework层可以使用这些方法
47.  * _init,_set_on,_set_off是Framework层调用的方法
48.  * ()Z 无参数返回值为bool型
49.  * (I)Z整形参数返回值为bool型
50.  */
51. staticconst
52. "_init",       "()Z",  
53. void*)weiyan_init},//framework层调用_init 时促发
54. "_set_on",          "(I)Z",  
55. void*)weityan_setOn },  
56. "_set_off",          "(I)Z",  
57. void*)weiyan_setOff },  
58. };  
59. staticint
60. staticconst char* const
61. "com/weiyan/server/LedService";//必须与Frameword层的service类名相同
62.     jclass clazz;  
63. /* look up the class */
64.     clazz = env->FindClass(kClassName);  
65. if
66. "Can't find class %s/n", kClassName);  
67. return
68.     }  
69. /* register all the methods */
70. if
71. sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)  
72.     {  
73. "Failed registering methods for %s/n", kClassName);  
74. return
75.     }  
76. /* fill out the rest of the ID cache */
77. return
78. }  
79. // ----------------------------------------------------------------------------
80. /*
81.  * Framework层加载JNI库时调用
82.  */
83. jint JNI_OnLoad(JavaVM* vm, void* reserved) {  
84.     JNIEnv* env = NULL;  
85.     jint result = -1;  
86. ifvoid**) &env, JNI_VERSION_1_4) != JNI_OK) {  
87. "ERROR: GetEnv failed/n");  
88. goto
89.     }  
90.     assert(env != NULL);  
91. //注册JNINavtiveMethod方法
92. if
93. "ERROR: PlatformLibrary native registration failed/n");  
94. goto
95.     }  
96. /* success -- return valid version number */
97.     result = JNI_VERSION_1_4;  
98. bail:  
99. return
100. }

 


 

 


3.Framework层的service

文件:weiyan/frameworks/base/service/java/com/weiyan/server


[c-sharp]  
1. publicclass
2. static
3. "/system/lib/libmokoid_runtime.so");//加载JNI动态 库
4.     }  
5. public
6. "LedService", "Go to get LED Stub...");  
7.     _init();  
8.     }  
9. /*
10.      * Mokoid LED native methods.
11.      */
12. publicint
13. "MokoidPlatform", "LED On");  
14. return
15.     }  
16. publicint
17. "MokoidPlatform", "LED Off");  
18. return
19.     }  
20. //声明jni可以使用的方法
21. privatestatic
22. privatestatic native boolean _set_on(int
23. privatestatic native boolean _set_off(int
24. }

 

 

4.APP 测试程序 (属于APP层)

    APP层两种调用模式

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

(2)经过Manager调用service

Manager (属于Framework层)


[c-sharp] 
1. publicclass
2. {  
3. privatestatic final String TAG = "LedManager";  
4. private
5. public
6. //利用ServiceManager获取LedService,从而调用它
7. //提供的方法,这要求LedService必须已经增加
8. //到ServiceManager中,这个过程将在App的一个
9. //Service进程中完成
10. 
11.         mLedService = ILedService.Stub.asInterface(  
12. "led"));  
13. ifnull) {  
14. "The LedManager object is ready.");  
15.     }  
16.     }  
17. publicint
18. false;  
19. try
20.             result = mLedService.setOn(n);  
21. catch
22. "RemoteException in LedManager.LedOn:", e);  
23.         }  
24. return
25.     }  
26. publicint
27. false;  
28. try
29.             result = mLedService.setOff(n);  
30. catch
31. "RemoteException in LedManager.LedOff:", e);  
32.         }  
33. return
34.     }  
35. }


 

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


文件:weiyan/frameworks/base/core/java/weiyan/hardware/ILedService.aidl

package mokoid.hardware;

interface ILedService
{
    boolean setOn(int led);
    boolean setOff(int led);
}

  系统的aidl工具会将ILedService.aidl生成ILedService.java文件,实现IledService

SystemServer (属于APP层)


 

文件: weiyan/apps/LedTest/src/com/weiyan/LedTest/LedSystemServer.java


[c-sharp]  
1. publicclass
2.     @Override  
3. public
4. returnnull;  
5.     }  
6. publicvoid onStart(Intent intent, int
7. "LedSystemServer", "Start LedService...");  
8. /* Please also see SystemServer.java for your interests. */
9. new
10. try
11. //将LedService添加到ServiceManager
12. "led", ls);  
13. catch
14. "LedSystemServer", "Start LedService failed.");  
15.         }  
16.     }  
17. }

 


 

 

二、 加载方法

1、把weiyan.tar.gz解压到/opt/ android_froyo_smdk

  $ cd   /opt/ android_froyo_smdk

  $ tar  -jxvf weiyan.tar.bz2

2、         修改build/core/config.mk文件防止编译找不到led.h头文件

$cd  /opt/ android_froyo_smdk
  $gedit build/core/config.mk

  找到SRC_HEADERS := /
        $(TOPDIR)system/core/include /

   在后面加入

$(TOPDIR)weiyan/hardware/modules/include

 

3、编译工程

$ source  /opt/android_froyo_smdk/build/envsetup.sh
$ export   TARGET_PRODUCT=sec_smdkv210
$mmm   /opt/android_froyo_smdk/weiyan

编译成功后会如下路径生成apk文件,库文件,jar包等

/opt/android_froyo_smdk/out/target/product/smdkv210/system/app/LedClient.apk
/opt/android_froyo_smdk/out/target/product/smdkv210/system/app/LedTest.apk
/opt/android_froyo_smdk/out/target/product/smdkv210/system/framework/ledctl.jar
/opt/android_froyo_smdk/out/target/product/smdkv210/system/lib/hw/led.smdkv210.so
/opt/android_froyo_smdk/out/target/product/smdkv210/system/lib/libled.so
/opt/android_froyo_smdk/out/target/product/smdkv210/system/lib/libmokoid_runtime.so

把LedClient.apk, LedTest.apk放到android的system/app目录,把ledctl.jar放到system/framework目录,把led.smdkv210.so放到system/lib/hw目录,把ibled.so,

libmokoid_runtime.so放到system/lib目录下

 

4、为了android桌面能显示我们的LedClient.apk, LedTest.apk程序,把weiyan/frameworks/base/service/com.weiyan.server.xml放到android的

system/etc/permissions目录下

5、加载led驱动模块

   把leds.ko复制到android 的system目录下,执行

   #insmod leds.ko

   #chmod 666 /dev/leds

 

6、运行LedClient.apk, LedTest.apk