在Ubuntu為Android硬體抽象層(HAL)模組編寫JNI方法提供Java訪問硬體服務介面(老羅學習筆記4),androidjni

來源:互聯網
上載者:User

在Ubuntu為Android硬體抽象層(HAL)模組編寫JNI方法提供Java訪問硬體服務介面(老羅學習筆記4),androidjni

在上兩篇文章中,我們介紹了如何為Android系統的硬體編寫驅動程式,包括如何在Linux核心空間實現核心驅動程式和在使用者空間實現硬體抽象層介面。實現這兩者的目的是為了向更上一層提供硬體提供者,即為Android的Application Frameworks層提供硬體服務。我們知道,Android系統的應用程式是用Java語言編寫的,而硬體驅動程式是用C語言來實現的,那麼,Java介面如何去訪問C介面呢?眾所周知,Java提供了JNI方法調用,同樣,在Android系統中,Java應用程式通過JNI來調用硬體抽象層介面。在這一篇文章中,我們將介紹如何為Android硬體抽象層介面編寫JNI方法,以便使得上層的Java應用程式能夠使用下層提供的硬體服務。

      一. 參照在Ubuntu上為Android增加硬體抽象層(HAL)模組訪問Linux核心驅動程式一文,準備好硬體抽象層模組,確保Android系統鏡像檔案system.img已經包含hello.default模組。

      二. 進入到frameworks/base/services/jni目錄,建立com_android_server_HelloService.cpp檔案:

      USER-NAME@MACHINE-NAME:~/Android$ cd frameworks/base/services/jni

      USER-NAME@MACHINE-NAME:~/Android/frameworks/base/services/jni$ vi com_android_server_HelloService.cpp

      在com_android_server_HelloService.cpp檔案中,實現JNI方法。注意檔案的命令方法,com_android_server首碼表示的是包名,表示硬體服務HelloService是放在frameworks/base/services/java目錄下的com/android/server目錄的,即存在一個命令為com.android.server.HelloService的類。這裡,我們暫時略去HelloService類的描述,在下一篇文章中,我們將回到HelloService類來。簡單地說,HelloService是一個提供Java介面的硬體訪問服務類

      首先是包含相應的標頭檔:

#define LOG_TAG "HelloService"          //#include "jni.h"      //jni層使用的一些函數定義 聲明#include "JNIHelp.h"   //??各個標頭檔作用,,求高人指點???????????? 謝謝#include "android_runtime/AndroidRuntime.h"  //?#include <utils/misc.h>     //?#include <utils/Log.h>  //?#include <hardware/hardware.h>    //需調用底層介面 如:hello_device
#include <hardware/hello.h> #include <stdio.h>

 

接著定義hello_init、hello_getVal和hello_setVal三個JNI方法:

namespace android  {      /*在硬體抽象層中定義的硬體訪問結構體,參考<hardware/hello.h>*/          struct hello_device_t* hello_device = NULL;      /*通過硬體抽象層定義的硬體提供者設定硬體寄存器val的值*/  
   /* 寫入 */ static void hello_setVal(JNIEnv* env, jobject clazz, jint value) { //JNIEnv*,jobject,jint類型 int val = value; LOGI("Hello JNI: set value %d to device.", val); if(!hello_device) { LOGI("Hello JNI: device is not open."); return; } hello_device->set_val(hello_device, val); //執行底層:set_val } /*通過硬體抽象層定義的硬體提供者讀取硬體寄存器val的值*/
     /*--讀取--*/   static jint hello_getVal(JNIEnv* env, jobject clazz) { int val = 0; if(!hello_device) { LOGI("Hello JNI: device is not open."); return val; } hello_device->get_val(hello_device, &val); //執行底層:get_val(就是簡單的運行一下) LOGI("Hello JNI: get value %d from device.", val); return val; } /*通過硬體抽象層定義的硬體模組開啟介面開啟硬體裝置*/ static inline int hello_device_open(const hw_module_t* module, struct hello_device_t** device) { //inline:內建函數 return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device); } /*通過硬體模組ID來載入指定的硬體抽象層模組並開啟硬體*/
     /*--bool為C中變數類型,jboolean 為JNI中變數類型,boolean為Java中變數類型;
     jboolean在C語言的定義為:
     typedef unsigned char jboolean;--*/ static jboolean hello_init(JNIEnv* env, jclass clazz) { hello_module_t* module; LOGI("Hello JNI: initializing......"); if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) { LOGI("Hello JNI: hello Stub found."); if(hello_device_open(&(module->common), &hello_device) == 0) { //調用hello_device_open()函數 LOGI("Hello JNI: hello device is open."); return 0; } LOGE("Hello JNI: failed to open hello device."); return -1; } LOGE("Hello JNI: failed to get hello stub module."); return -1; } /*JNI方法表*/ static const JNINativeMethod method_table[] = { //頂層只用 {"init_native", "()Z", (void*)hello_init}, {"setVal_native", "(I)V", (void*)hello_setVal}, {"getVal_native", "()I", (void*)hello_getVal}, }; /*註冊JNI方法*/ int register_android_server_HelloService(JNIEnv *env) { //http://blog.csdn.net/horkychen/article/details/10952249 return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table)); } };

 

 

      注意,在hello_init函數中,通過Android硬體抽象層提供的hw_get_module方法來載入模組ID為HELLO_HARDWARE_MODULE_ID的硬體抽象層模組,其中,HELLO_HARDWARE_MODULE_ID是在<hardware/hello.h>中定義的。Android硬體抽象層會根據HELLO_HARDWARE_MODULE_ID的值在Android系統的/system/lib/hw目錄中找到相應的模組,然後載入起來,並且返回hw_module_t介面給調用者使用。在jniRegisterNativeMethods函數中,第二個參數的值必須對應HelloService所在的包的路徑,即com.android.server.HelloService

      三. 修改同目錄下的onload.cpp檔案,首先在namespace android增加register_android_server_HelloService函式宣告:

      namespace android {

      ..............................................................................................

      int register_android_server_HelloService(JNIEnv *env);

      };

      在JNI_onLoad增加register_android_server_HelloService函數調用:      extern "C" jint JNI_onLoad(JavaVM* vm, void* reserved)      {       .................................................................................................        register_android_server_HelloService(env);        .................................................................................................      }      這樣,在Android系統初始化時,就會自動載入該JNI方法調用表。      四. 修改同目錄下的Android.mk檔案,在LOCAL_SRC_FILES變數中增加一行:      LOCAL_SRC_FILES:= \      com_android_server_AlarmManagerService.cpp \      com_android_server_BatteryService.cpp \      com_android_server_InputManager.cpp \      com_android_server_LightsService.cpp \      com_android_server_PowerManagerService.cpp \      com_android_server_SystemServer.cpp \      com_android_server_UsbService.cpp \      com_android_server_VibratorService.cpp \      com_android_server_location_GpsLocationProvider.cpp \       com_android_server_HelloService.cpp /      onload.cpp      五. 編譯和重新找億system.img:       USER-NAME@MACHINE-NAME:~/Android$ mmm frameworks/base/services/jni       USER-NAME@MACHINE-NAME:~/Android$ make snod       這樣,重新打包的system.img鏡像檔案就包含我們剛才編寫的JNI方法了,也就是我們可以通過Android系統的Application Frameworks層提供的硬體服務HelloService來調用這些JNI方法,進而調用低層的硬體抽象層介面去訪問硬體了。前面提到,在這篇文章中,我們暫時忽略了HelloService類的實現,在下一篇文章中,我們將描述如何?硬體服務HelloService,敬請關注。   

1.

make:進入目錄'/opt/FriendlyARM/tiny4412/android/android-4.1.2'
make: *** 沒有規則可以建立“out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/import_includes”需要的目標“out/target/product/generic/obj/SHARED_LIBRARIES/libc_intermediates/export_includes”。 停止。
make:離開目錄“/opt/FriendlyARM/tiny4412/android/android-4.1.2”
root@phone-desktop:/opt/FriendlyARM/tiny4412/android/android-4.1.2#

 

解決方案:

. setenv

輸出:

out/target/product/tiny4412/system/lib/libandroid_servers.so

3

make: *** [out/target/common/obj/APPS/CMParts_intermediates/classes-full-debug.jar] 錯誤 41 這個錯誤,解決方案,知道的話就很簡單了,
只需打如下命令 即可:make update-api;             //$ make clobber       $ make   
 局部程式修改:http://blog.csdn.net/oldmtn/article/details/9214143 原文:http://blog.csdn.net/luoshengyang/article/details/6575988   

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.