转载.Android HAL实现的三种方式(1) - 基于JNI的简单HAL设计

现在在Android上的HAL开发总的来说还是随意性比较大,Android也并没有规范好一个具体的框架,下面我将根据Jollen的Mokoid工程,自己做了一些改动,分别给大家介绍一下三种实现方式。

这篇先介绍最简单的一种实现方式 - Java应用程序直接调用JNI库。

由于JNI技术的存在,在Android中,java程序能够很好的调用C/C++库。我们这里设计一个简单的HAL,一共只有三层: HAL stub <-> JNI 库 <-> JAVA应用程序。

我们现看看HAL stub的代码:

  1. int led_device_close(struct hw_device_t* device) 
  2.     struct led_control_device_t* ctx = (struct led_control_device_t*)device; 
  3.     if (ctx) { 
  4.         free(ctx); 
  5.     } 
  6.     return 0; 
  7.  
  8. int led_on(struct led_control_device_t *dev, int32_t led) 
  9.     LOGI("LED Stub: set %d on.", led); 
  10.     return 0; 
  11.  
  12. int led_off(struct led_control_device_t *dev, int32_t led) 
  13.     LOGI("LED Stub: set %d off.", led); 
  14.     return 0; 
  15.  
  16. static int led_device_open(const struct hw_module_t* module, const char* name, 
  17.         struct hw_device_t** device)  
  18.     struct led_control_device_t *dev; 
  19.  
  20.     dev = (struct led_control_device_t *)malloc(sizeof(*dev)); 
  21.     memset(dev, 0, sizeof(*dev)); 
  22.  
  23.     dev->common.tag =  HARDWARE_DEVICE_TAG; 
  24.     dev->common.version = 0; 
  25.     dev->common.module = module; 
  26.     dev->common.close = led_device_close; 
  27.  
  28.     dev->set_on = led_on; 
  29.     dev->set_off = led_off; 
  30.  
  31.     *device = &dev->common; 
  32.  
  33. success: 
  34.     return 0; 
  35.  
  36. static struct hw_module_methods_t led_module_methods = { 
  37.     open: led_device_open 
  38. }; 
  39.  
  40. const struct led_module_t HAL_MODULE_INFO_SYM = { 
  41.     common: { 
  42.         tag: HARDWARE_MODULE_TAG, 
  43.         version_major: 1, 
  44.         version_minor: 0, 
  45.         id: LED_HARDWARE_MODULE_ID, 
  46.         name: "Sample LED Stub"
  47.         author: "The Mokoid Open Source Project"
  48.         methods: &led_module_methods, 
  49.     } 
  50.     /* supporting APIs go here */ 
  51. }; 

我在前面关于HAL技术的文章中已经介绍了如何写HAL stub,需要注意的只有hw_module_t和hw_device_t这两个数据结构,这里就不复述了。

下面看看JNI层代码:

  1. struct led_control_device_t *sLedDevice = NULL; 
  2.  
  3. static jboolean mokoid_setOn(JNIEnv* env, jobject thiz, jint led)  
  4.     LOGI("LedService JNI: mokoid_setOn() is invoked."); 
  5.  
  6.     if (sLedDevice == NULL) { 
  7.         LOGI("LedService JNI: sLedDevice was not fetched correctly."); 
  8.         return -1; 
  9.     } else { 
  10.         return sLedDevice->set_on(sLedDevice, led); 
  11.     } 
  12.  
  13. static jboolean mokoid_setOff(JNIEnv* env, jobject thiz, jint led)  
  14.     LOGI("LedService JNI: mokoid_setOff() is invoked."); 
  15.  
  16.  
  17.     if (sLedDevice == NULL) { 
  18.         LOGI("LedService JNI: sLedDevice was not fetched correctly."); 
  19.         return -1; 
  20.     } else { 
  21.         return sLedDevice->set_off(sLedDevice, led); 
  22.     } 
  23.  
  24. /** helper APIs */ 
  25. static inline int led_control_open(const struct hw_module_t* module, 
  26.         struct led_control_device_t** device) { 
  27.     return module->methods->open(module, 
  28.             LED_HARDWARE_MODULE_ID, (struct hw_device_t**)device); 
  29.  
  30. static jboolean mokoid_init(JNIEnv *env, jclass clazz) 
  31.     led_module_t* module; 
  32.  
  33.     if (hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) { 
  34.         LOGI("LedService JNI: LED Stub found."); 
  35.         if (led_control_open(&module->common, &sLedDevice) == 0) { 
  36.             LOGI("LedService JNI: Got Stub operations."); 
  37.             return 0; 
  38.         } 
  39.     } 
  40.  
  41.     LOGE("LedService JNI: Get Stub operations failed."); 
  42.     return -1; 
  43.  
  44. static const JNINativeMethod gMethods[] = { 
  45.     { "_init",      "()Z",  (void *)mokoid_init }, 
  46.     { "_set_on",        "(I)Z", (void *)mokoid_setOn }, 
  47.     { "_set_off",       "(I)Z", (void *)mokoid_setOff }, 
  48. }; 
  49.  
  50. int register_mokoid_server_LedService(JNIEnv* env) { 
  51.     static const charconst kClassName = 
  52.         "com/mokoid/LedClient/LedClient"
  53.     jclass clazz; 
  54.  
  55.     /* look up the class */ 
  56.     clazz = env->FindClass(kClassName); 
  57.     if (clazz == NULL) { 
  58.         LOGE("Can't find class %s\n", kClassName); 
  59.         return -1; 
  60.     } 
  61.  
  62.     /* register all the methods */ 
  63.     if (env->RegisterNatives(clazz, gMethods, 
  64.             sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK) 
  65.     { 
  66.         LOGE("Failed registering methods for %s\n", kClassName); 
  67.         return -1; 
  68.     } 
  69.  
  70.     /* fill out the rest of the ID cache */ 
  71.     return 0; 
  72.  
  73. extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) 
  74.     JNIEnv* env = NULL; 
  75.     jint result = -1; 
  76.  
  77.     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { 
  78.         LOGE("GetEnv failed!"); 
  79.         return result; 
  80.     } 
  81.     LOG_ASSERT(env, "Could not retrieve the env!"); 
  82.  
  83.     register_mokoid_server_LedService(env); 
  84.  
  85.     return JNI_VERSION_1_4; 

上面的Jni代码首先通过hw_get_module得到HAL stub,open以后就可以直接使用HAL stub中定义的接口。这里还需要注意JNI_OnLoad这个函数,当Jni库被App load的时候,该函数将会自动被调用,所以我们在这里实现了注册Led Service的操作,也就是说把C/C++的接口映射到Java中去,这样在Java APP中就可以使用该接口了。在register_mokoid_server_LedService中,我们需要注意kclassname指定了需要调用该Jni库的Java APP类 - com.mokoid.LedClient.LedClient,也就是说该Jni库只能提供给该Java程序使用。

最后是应用程序代码:

  1. public class LedClient extends Activity { 
  2.  
  3.     static { 
  4.         System.load("/system/lib/libmokoid_runtime.so"); 
  5.     } 
  6.  
  7.     @Override 
  8.     public void onCreate(Bundle savedInstanceState) { 
  9.         super.onCreate(savedInstanceState); 
  10.  
  11.         // Call an API on the library. 
  12.         _init(); 
  13.         _set_on(1); 
  14.         _set_off(2); 
  15.          
  16.         TextView tv = new TextView(this); 
  17.         tv.setText("LED 1 is on. LED 2 is off."); 
  18.         setContentView(tv); 
  19.     } 
  20.     private static native boolean _init(); 
  21.     private static native boolean _set_on(int led); 
  22.     private static native boolean _set_off(int led); 

 上面使用System.load来装载Jni库,当然我们也可以使用System.loadLibrary来装载,他们的唯一区别就是前者需要指定完整的路径,后者会在系统路径上(比如/system/lib/) 查找库。装载完该Jni库后,就可以使用映射后的接口了(_init, _set_on, _set_off)。 

上面这种HAL的实现方式比较简单,但是也存在一个很大的问题,就是Jni库只能提供给某一个特定的Java使用,如何克服这个问题?我们可以在APP和Jni之间加一层Java service,该Jni提供给Java service使用,而所有的APP利用该service来使用Jni提供的接口。这样的话,在应用程序层,就不需要关心Jni是如何实现的了。下一篇我们会介绍这种方法。

本文出自 “Mobile and Linux Deve..” 博客,请务必保留此出处http://buaadallas.blog.51cto.com/399160/384622

转载于:https://www.cnblogs.com/gooogleman/archive/2012/07/06/2579431.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/302486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

21张GIF动图让你秒懂数学原理

全世界有3.14 % 的人已经关注了数据与算法之美数学是很难的科学&#xff0c;但因为它是科学家用数学来解释宇宙的语言&#xff0c;我们无可避免的要学习它。看看下面的这些GIF动图&#xff0c;它们提供了视觉的方式来帮助你理解各种数学技巧。推荐阅读《12堂魔力数学课》。1.椭…

表格过滤器_记录和管理零散信息,什么软件比 Excel 表格更方便

SeaTable 的目标是帮助大家更好的组织和管理各种零散的信息&#xff0c;团队的请假信息就属于这样一类零散的信息。下面我们来看一下 &#xff0c;SeaTable 相比于 Excel 是如何更好的帮助我们来组织和管理这样的信息的。用 Excel 记录的团队请假信息下面两张表是比较常见的请假…

使用 Source Generator 代替 T4 动态生成代码

使用 Source Generator 代替 T4 动态生成代码Intro在 Source Generator 出现之前有一些重复性的代码&#xff0c;我会使用 T4 去生成&#xff0c;这样就可以一定程度上避免复制粘贴和可维护性也会更好一些。在了解了一些 Source Generator 之后&#xff0c;就想尝试把现在项目里…

海量数据处理方法的分析

本文可以认为是http://blog.csdn.net/v_JULY_v/article/details/6279498的读后感&#xff0c;我是按照我理解的语言重新表述了一下而已。 海量数据处理的常用方法包括一下几种&#xff1a; 1.分而治之/hash映射 hash统计 堆/快速/归并排序&#xff1b;2.双层桶划分3.Bloom fi…

资料分享 | 数据挖掘实例资料分享来袭

小编从大学开始&#xff0c;便开启资料收集功能。随着大数据时代的来临&#xff0c;计算机发展进入新的阶段&#xff0c;再加上日常的深入研究&#xff0c;小编收集整理了丰富的数据挖掘资料&#xff0c;内容涵盖“程序”&#xff0c;“数据”、“文档”等。这次小编再次把所有…

修改图层的范围_【PS|第39期】数字绘画 使用填充图层

惟有悲观净化而成的乐观&#xff0c;才是真正的乐观。——尼采)填充图层是一种只承载纯色、渐变和图案的特殊图层&#xff0c;其特点是填充内容可以修改。另外&#xff0c;设置成不同的混合模式和不透明度后&#xff0c;可用于修改其他图层的颜色或生成图像混合效果。填充图层都…

我的注释那去了?

当我们用nuget引用三方库时&#xff0c;在类型&#xff0c;或类型成员上会有注释&#xff0c;如下图&#xff0c;是MySql官方包&#xff0c;command的ExecuteNonQuery的注释我们自己写一个类库项目CommentsLibrary&#xff0c;给类&#xff0c;构造函数&#xff0c;方法添加xml…

[原] jQuery EasyUI 1.2.6源码、Demo合集、离线API

下载地址&#xff1a; http://files.cnblogs.com/purediy/jquery-easyui-1.2.6.zip 兄弟版本&#xff1a; jQuery EasyUI 1.3.4 离线API、Demo jQuery EasyUI 1.3.2 离线API、Demo jQuery EasyUI 1.3.0 Demo合集、离线API、动态换肤 相信关注过jQuery UI 的大部分都查到过easyu…

ubuntu14安装python_ubuntu14.04 安装python3.7

下载源码&#xff1a;https://www.python.org/downloads/release/python-373/一、先安装需要的包zlib1g,libffisudo apt-get updatesudo apt-get install zlib1g-devsudo apt-get install libffi-dev二、在ubuntu上创建/usr/local/python3.7的目录&#xff0c;将压缩包放到该目…

CCNA第二章

第二章 交换机的基本概念和配置&#xff1a; Ethernet/802.3网络的关键要素&#xff1a; 载波侦听多路访问/冲突检测&#xff08;CSMA/CD&#xff09; CSMA/CD 仅用于集线器中常用的半双工通信。全双工交换机不使用 CSMA/CD。载波侦听&#xff1a;在 CSMA/CD 接入方法中&#x…

看书的一点小建议!

阅读本文大概需要6分钟。昨天看见小北写了一篇&#xff1a;「看书的一点小建议」&#xff0c;写的很不错&#xff0c;今天也分享一下自己看书的心得。其实不少读者问过我怎么看计算机经典大厚书、怎么看产品运营经典大厚书、怎么提高看书效率&#xff1a;电影教父里有台词&…

技巧:Excel用得好,天天没烦恼

全世界有3.14 % 的人已经关注了数据与算法之美Excel是Office三大神器当中最神秘、但也是最能提高你效率的工具了。而我们中的太多小伙伴&#xff0c;却一直把它当做是个“电子表格工具”。今天一起涨姿势&#xff0c;学会下面这些神技&#xff0c;你的Excel分分钟超过90%的同事…

操作数数据类型 char 对于 sum 运算符无效。_数据类型和运算符

数据类型和运算符1.进制1.1文件存储单位​ 任何数据在计算机中都是以二进制的形式存在的&#xff0c;二进制早期由电信号开关演变而来 。​ 一个电信号或者一个二进制位统称为Bit位&#xff0c;8个Bit位为一组组成一个字节Byte 。​ 一个bit位表示的数的范围&#xff1a;0和1​…

PHP excel文件导入至mysql中!

今天的项目需要一个导入excel文件到mysql的功能&#xff01;折腾了很久&#xff0c;去网上也找到一大堆的帖子&#xff01; 实现方式有几种: 1、使用扩展类库对excel文件进行操作&#xff01;如&#xff1a;PHPExcel类包、phpexcelreader类文件&#xff08;比较小巧&#xf…

我所理解的开源软件供应链安全

点击上方“开源社”关注我们| 作者&#xff1a;庄表伟| 编辑&#xff1a;钱英宇| 设计&#xff1a;谭嘉露| 责编&#xff1a;王玥敏1供应链与断供隐喻会帮助人&#xff0c;也会误导人。当我们谈到“供应链”时&#xff0c;会产生哪些联想&#xff1f;环环相扣&#xff1f;缺一不…

82 个代码案例实践,带你学好 Python 机器学习

全世界有3.14 % 的人已经关注了数据与算法之美如果村里通了网&#xff0c;那你一定知道【AI】人工智能。如果你会网上冲浪&#xff0c;那你一定看到过【ML】机器学习。小编在网上看到一个段子&#xff1a;ML派坐落美利坚合众山中&#xff0c;百年来武学奇才辈出&#xff0c;隐然…

Python进阶08 异常处理

作者&#xff1a;Vamei 出处&#xff1a;http://www.cnblogs.com/vamei 欢迎转载&#xff0c;也请保留这段声明。谢谢&#xff01; 本文特别感谢kylinfish的纠正&#xff0c;相关讨论见留言区。 异常处理 在项目开发中&#xff0c;异常处理是不可或缺的。异常处理帮助人们debug…

查询程序崩溃日志_PC 崩溃报告途径 amp; 临时解决方法

TC Sera (社区经理)&#xff1a;你好&#xff01;如果您在电脑游戏中遇到与 Nvidia 驱动程序相关的崩溃情况&#xff0c;请打开视频设置(Video Settings)中的诊断模式(Diagnostics Mode)并重新启动游戏。如果您遇到问题&#xff0c;请打包&#xff1a;%localappdata%\Gears5\Sa…

C# ConcurrentBag的实现原理

一、前言笔者最近在做一个项目&#xff0c;项目中为了提升吞吐量&#xff0c;使用了消息队列&#xff0c;中间实现了生产消费模式&#xff0c;在生产消费者模式中需要有一个集合&#xff0c;来存储生产者所生产的物品&#xff0c;笔者使用了最常见的List<T>集合类型。由于…

Linux里10个最危险的命令

全世界只有3.14 % 的人关注了数据与算法之美Linux命令行佷有用、很高效&#xff0c;也很有趣&#xff0c;但有时候也很危险&#xff0c;尤其是在你不确定你自己在正在做什么时候。推荐阅读Linux之父林纳斯自传《只是为了好玩》这篇文章将会向你介绍十条命令&#xff0c;但你最好…