一、代码讲解
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