日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

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

發布時間:2023/12/4 Android 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 转载.Android HAL实现的三种方式(1) - 基于JNI的简单HAL设计 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

現在在Android上的HAL開發總的來說還是隨意性比較大,Android也并沒有規范好一個具體的框架,下面我將根據Jollen的Mokoid工程,自己做了一些改動,分別給大家介紹一下三種實現方式。

這篇先介紹最簡單的一種實現方式 - Java應用程序直接調用JNI庫。

由于JNI技術的存在,在Android中,java程序能夠很好的調用C/C++庫。我們這里設計一個簡單的HAL,一共只有三層: HAL stub <-> JNI 庫 <-> JAVA應用程序。

我們現看看HAL stub的代碼:

  • 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);?
  • ????}?
  • ????return?0;?
  • }?
  • ?
  • int?led_on(struct?led_control_device_t?*dev,?int32_t?led)?
  • {?
  • ????LOGI("LED?Stub:?set?%d?on.",?led);?
  • ????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;?
  • ?
  • 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,?
  • ????}?
  • ????/*?supporting?APIs?go?here?*/?
  • };?
  • 我在前面關于HAL技術的文章中已經介紹了如何寫HAL stub,需要注意的只有hw_module_t和hw_device_t這兩個數據結構,這里就不復述了。

    下面看看JNI層代碼:

  • 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);?
  • ????}?
  • }?
  • ?
  • /**?helper?APIs?*/?
  • 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;?
  • ?
  • ????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?},?
  • };?
  • ?
  • int?register_mokoid_server_LedService(JNIEnv*?env)?{?
  • ????static?const?char*?const?kClassName?=?
  • ????????"com/mokoid/LedClient/LedClient";?
  • ????jclass?clazz;?
  • ?
  • ????/*?look?up?the?class?*/?
  • ????clazz?=?env->FindClass(kClassName);?
  • ????if?(clazz?==?NULL)?{?
  • ????????LOGE("Can't?find?class?%s\n",?kClassName);?
  • ????????return?-1;?
  • ????}?
  • ?
  • ????/*?register?all?the?methods?*/?
  • ????if?(env->RegisterNatives(clazz,?gMethods,?
  • ????????????sizeof(gMethods)?/?sizeof(gMethods[0]))?!=?JNI_OK)?
  • ????{?
  • ????????LOGE("Failed?registering?methods?for?%s\n",?kClassName);?
  • ????????return?-1;?
  • ????}?
  • ?
  • ????/*?fill?out?the?rest?of?the?ID?cache?*/?
  • ????return?0;?
  • }?
  • ?
  • extern?"C"?jint?JNI_OnLoad(JavaVM*?vm,?void*?reserved)?
  • {?
  • ????JNIEnv*?env?=?NULL;?
  • ????jint?result?=?-1;?
  • ?
  • ????if?(vm->GetEnv((void**)?&env,?JNI_VERSION_1_4)?!=?JNI_OK)?{?
  • ????????LOGE("GetEnv?failed!");?
  • ????????return?result;?
  • ????}?
  • ????LOG_ASSERT(env,?"Could?not?retrieve?the?env!");?
  • ?
  • ????register_mokoid_server_LedService(env);?
  • ?
  • ????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程序使用。

    最后是應用程序代碼:

  • public?class?LedClient?extends?Activity?{?
  • ?
  • ????static?{?
  • ????????System.load("/system/lib/libmokoid_runtime.so");?
  • ????}?
  • ?
  • ????@Override?
  • ????public?void?onCreate(Bundle?savedInstanceState)?{?
  • ????????super.onCreate(savedInstanceState);?
  • ?
  • ????????//?Call?an?API?on?the?library.?
  • ????????_init();?
  • ????????_set_on(1);?
  • ????????_set_off(2);?
  • ?????????
  • ????????TextView?tv?=?new?TextView(this);?
  • ????????tv.setText("LED?1?is?on.?LED?2?is?off.");?
  • ????????setContentView(tv);?
  • ????}?
  • ????private?static?native?boolean?_init();?
  • ????private?static?native?boolean?_set_on(int?led);?
  • ????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

    總結

    以上是生活随笔為你收集整理的转载.Android HAL实现的三种方式(1) - 基于JNI的简单HAL设计的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。