Now Hal development on Android is relatively random, and Android does not have a specific framework. I will make some changes according to jollen's mokoid project, we will introduce three implementation methods respectively.
This article first introduces the simplest implementation method-Java applications directly call the JNI library.
Due to the existence of JNI technology, Java programs can call the C/C ++ Library Well in Android. Here we design a simple Hal with only three layers: Hal stub <-> JNI library <-> JAVA application.
Now let's look at the Hal stub code:
1. int led_device_close (struct hw_device_t * Device) <br/> 2. {<br/> 3. struct led_control_device_t * CTX = (struct led_control_device_t *) device; <br/> 4. if (CTX) {<br/> 5. free (CTX); <br/> 6 .} <br/> 7. return 0; <br/> 8 .} <br/> 9. <br/> 10. int led_on (struct led_control_device_t * Dev, int32_t led) <br/> 11. {<br/> 12. logi ("led stub: Set % d on. ", LED); <br/> 13. return 0; <br/> 14 .} <br/> 15. <br/> 16. int led_off (struct led_control_device_t * Dev, int32_t led) <br/> 17. {<br/> 18. logi ("led stub: Set % d off. ", LED); <br/> 19. return 0; <br/> 20 .} <br/> 21. <br/> 22. static int led_device_open (const struct hw_module_t * module, const char * Name, <br/> 23. struct hw_device_t ** device) <br/> 24. {<br/> 25. struct led_control_device_t * dev; <br/> 26. <br/> 27. dev = (struct led_control_device_t *) malloc (sizeof (* Dev); <br/> 28. memset (Dev, 0, sizeof (* Dev); <br/> 29. <br/> 30. dev-> common. tag = hardware_device_tag; <br/> 31. dev-> common. version = 0; <br/> 32. dev-> common. module = module; <br/> 33. dev-> common. close = led_device_close; <br/> 34. <br/> 35. dev-> set_on = led_on; <br/> 36. dev-> set_off = led_off; <br/> 37. <br/> 38. * Device = & Dev-> common; <br/> 39. <br/> 40. success: <br/> 41. return 0; <br/> 42 .} <br/> 43. <br/> 44. static struct hw_module_methods_t led_module_methods ={< br/> 45. open: led_device_open <br/> 46 .}; <br/> 47. <br/> 48. const struct led_module_t hal_module_info_sym = {<br/> 49. common: {<br/> 50. tag: hardware_module_tag, <br/> 51. version_major: 1, <br/> 52. version_minor: 0, <br/> 53. ID: led_hardware_module_id, <br/> 54. name: "sample led stub", <br/> 55. author: "The mokoid open source project", <br/> 56. methods: & led_module_methods, <br/> 57 .} <br/> 58. /* supporting APIs go here */<br/> 59 .};
I have introduced how to write Hal stub in the previous article on Hal Technology. Note that only the data structures hw_module_t and hw_device_t are required. I will not repeat them here.
Let's take a look at the JNI Layer Code:
1. struct led_control_device_t * sleddevice = NULL; <br/> 2. <br/> 3. static jboolean mokoid_seton (jnienv * ENV, jobject thiz, jint led) <br/> 4. {<br/> 5. logi ("ledservice JNI: mokoid_seton () is invoked. "); <br/> 6. <br/> 7. if (sleddevice = NULL) {<br/> 8. logi ("ledservice JNI: sleddevice was not fetched correctly. "); <br/> 9. return-1; <br/> 10 .} else {<br/> 11. return sleddevice-> set_on (lupus Ddevice, LED); <br/> 12 .} <br/> 13 .} <br/> 14. <br/> 15. static jboolean mokoid_setoff (jnienv * ENV, jobject thiz, jint led) <br/> 16. {<br/> 17. logi ("ledservice JNI: mokoid_setoff () is invoked. "); <br/> 18. <br/> 19. <br/> 20. if (sleddevice = NULL) {<br/> 21. logi ("ledservice JNI: sleddevice was not fetched correctly. "); <br/> 22. return-1; <br/> 23 .} else {<br/> 24. return sleddevice-> S Et_off (sleddevice, LED); <br/> 25 .} <br/> 26 .} <br/> 27. <br/> 28. /** helper APIs */<br/> 29. static inline int led_control_open (const struct hw_module_t * module, <br/> 30. struct led_control_device_t ** device) {<br/> 31. return Module-> methods-> open (module, <br/> 32. led_hardware_module_id, (struct hw_device_t **) device); <br/> 33 .} <br/> 34. <br/> 35. static jboolean mokoid_init (jnienv * env, Jclass clazz) <br/> 36. {<br/> 37. led_module_t * module; <br/> 38. <br/> 39. if (hw_get_module (led_hardware_module_id, (const hw_module_t **) & module) = 0) {<br/> 40. logi ("ledservice JNI: LED stub found. "); <br/> 41. if (led_control_open (& module-> common, & sleddevice) = 0) {<br/> 42. logi ("ledservice JNI: Got stub operations. "); <br/> 43. return 0; <br/> 44 .} <br/> 45 .} <br/> 46. <br/> 47. LogE ("ledservice JNI: Get stub operations failed. "); <br/> 48. return-1; <br/> 49 .} <br/> 50. <br/> 51. static const jninativemethod gmethods [] ={< br/> 52. {"_ init", "() Z", (void *) mokoid_init}, <br/> 53. {"_ set_on", "(I) Z", (void *) mokoid_seton}, <br/> 54. {"_ set_off", "(I) Z", (void *) mokoid_setoff}, <br/> 55 .}; <br/> 56. <br/> 57. int register_mokoid_server_ledservice (jnienv * env) {<B R/> 58. static const char * const kclassname = <br/> 59. "com/mokoid/ledclient"; <br/> 60. jclass clazz; <br/> 61. <br/> 62. /* look up the class */<br/> 63. clazz = env-> findclass (kclassname); <br/> 64. if (clazz = NULL) {<br/> 65. logE ("can't find Class % s/n", kclassname); <br/> 66. return-1; <br/> 67 .} <br/> 68. <br/> 69. /* register all the methods */<br/> 70. if (env-> Register Natives (clazz, gmethods, <br/> 71. sizeof (gmethods)/sizeof (gmethods [0])! = Jni_ OK) <br/> 72. {<br/> 73. logE ("failed registering methods for % s/n", kclassname); <br/> 74. return-1; <br/> 75 .} <br/> 76. <br/> 77. /* fill out the rest of the ID cache */<br/> 78. return 0; <br/> 79 .} <br/> 80. <br/> 81. extern "C" jint jni_onload (JavaVM * Vm, void * Reserved) <br/> 82. {<br/> 83. jnienv * Env = NULL; <br/> 84. jint result =-1; <br/> 85. <br/> 86. if (Vm-> getenv (void **) & ENV, jni_version_1_4 )! = Jni_ OK) {<br/> 87. LogE ("getenv failed! "); <Br/> 88. Return result; <br/> 89.} <br/> 90. log_assert (ENV," cocould not retrieve the Env! "); <Br/> 91. <br/> 92. register_mokoid_server_ledservice (ENV); <br/> 93. <br/> 94. return jni_version_1_4; <br/> 95 .}
The preceding JNI code first obtains Hal stub through hw_get_module. After opening, you can directly use Hal.
The interface defined in stub. Pay attention to the jni_onload function. When the JNI library is
This function will be automatically called during load, so we have registered
Service operation, that is, to map the C/C ++ interface to Java, so that
This interface can be used in the app. In register_mokoid_server_ledservice, note thatKclassname
Specifies the Java app class-Com. mokoid. ledclient. ledclient that needs to call the JNI library. That is to say, the JNI library can only be provided to the Java program.
Finally, the application code is as follows:
1. public class ledclient extends activity {<br/> 2. <br/> 3. static {<br/> 4. system. load ("/system/lib/libmokoid_runtime.so"); <br/> 5 .} <br/> 6. <br/> 7. @ override <br/> 8. public void oncreate (bundle savedinstancestate) {<br/> 9. super. oncreate (savedinstancestate); <br/> 10. <br/> 11. // call an API on the library. <br/> 12. _ Init (); <br/> 13. _ set_on (1); <br/> 14. _ set_off (2); <br/> 15. <br/> 16. textview TV = new textview (this); <br/> 17. TV. settext ("led 1 is on. led 2 is off. "); <br/> 18. setcontentview (TV); <br/> 19 .} <br/> 20. private Static native Boolean _ Init (); <br/> 21. private Static native Boolean _ set_on (INT led); <br/> 22. private Static native Boolean _ set_off (INT led); <br/> 23 .}
The above uses system. Load to load the JNI library. Of course, we can also use system. loadlibrary for loading. The only difference between them is that the former needs to specify the complete
Path
, The latter will be in the systemPath
(Such as/system/lib. After loading the JNI library, you can use the ing interface (_ init, _ set_on, _ set_off ).
The above Hal implementation method is relatively simple, but there is also a big problem, that is, the JNI library can only be provided to a specific Java, how to overcome this problem? We can
A Java service is added between the app and JNI, which is provided to Java
Service, and all apps use the Service to use the interfaces provided by JNI. In this way, the application layer does not need to care about how JNI is implemented. Next article I
We will introduce this method.