安卓驅動、HAL、JNI與java
最近看了安卓驅動層到應用層的實現,總結一下所學,新手學習,不足之處請指正(以LED為例):
網址:http://blog.csdn.net/liruicom/article/details/8517948
由驅動層到應用層的流程Linux驅動->HAL->JNI->APK
首先是驅動層:
1)建立cdev與實現file_operations 。
2)module_init與module_exit的實現:在module_init中實現cdev_init()、register_chrdev_region()或alloc_chrdev_region()與cdev_add(),同時實現class_create()、device_class()。在module_exit中實現device_destroy()、class_destroy()與unregister_chrdev_region()。
3)open與release函式的實現,open函式中實現gpio_request()、s3c_gpio_cfgpin()、gpio_direction_output()函式。release函式中實現gpio_free()。
4)ioctl函式實現
5)MODULE_LICENSE("GPL")
6)對Makefile與Kconfig函式修改。
其次HAL層實現:
HAL層的入口函式為HAL_MODULE_INFO_SYM,呼叫過程為HAL_MODULE_INFO_SYM-> hw_module_methods_t->open,在open中對包含hw_device_t的結構體進行一系列初始化,並開啟LED驅動裝置。具體實現過程如下:
1)定義結構體和巨集
hw_module_t,hw_device_t及IO,HAL規定不可直接使用hw_module_t結構體,因此,需要在hw_module_t外再套一層結構體。hw_module_t及hw_device_t自定義結構體內的第一個成員變數資料結構必須為hw_module_t與hw_device_t。在hw_device_t自定義的結構體內可定義函式指標,函式指標的數量與引數可自己定義,但必須與上層呼叫形式儲存一致。
2)編寫HAL模組的open函式
(1)初始化hw_device_t子結構體、必要操作、硬體操作函式指標。
(2)開啟裝置檔案。
(3)初始化暫存器
3)定義hw_module_methods_t結構體變數
4)定義HAL_MODULE_INFO_SYM變數,一般為hw_module_t或子結構體,並對其初始化。
5)編寫HAL模組close函式
6)編寫控制函式
7)編寫Android.mk
再次編寫JNI函式
1)編寫JNI_Onload函式,系統在成功裝載JNI共享庫後自動呼叫,一般用於初始化JNI,函式如下:主要實現功能:告訴JavaVm使用虛擬機器那一個版本:初值設定獲取JavaVm介面
/*沒有理解JNI_OnLoad函式與register_android_server_LedService函式,若您理解了之後可以留言教我一下嗎*/
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_android_server_LedService( env );//將JNI程式庫與Java類繫結
return JNI_VERSION_1_4;
}
int register_android_server_LedService(JNIEnv *env)
{
static const char* const kClassName = " android /server/LedService"; /*kclassname 指定了需要呼叫該Jni庫的Java APP類*/
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, method_table,
sizeof(method_table) / sizeof(method_table[0])) != JNI_OK)
{
LOGE("Failed registering methods for %s/n", kClassName);
return -1;
}
/* fill out the rest of the ID cache */
return 0;
}
/*JNI與JAVA對應對映表,格式:要註冊到java類中的方法名;方法引數與返回值的型別;要註冊到JNI的指標函式*/
static JNINativeMethod method_table[] = {
{ "led_init", "()Z", (void*)Java_com_embedsky_led_LedActivity_ledInit },
{ "led_setOn", "(I)Z", (void*)Java_com_embedsky_led_LedActivity_ledSetOn },
{ "led_setOff", "(I)Z", (void*)Java_com_embedsky_led_LedActivity_ledSetOff },
{ "led_close", "()Z", (void*)Java_com_embedsky_led_LedActivity_ledClose },
2)實現method_table[] 中JNI的指標函式,在init中呼叫hw_get_module函式,實現通過呼叫hw_get_module函式找到HAL中定義標頭檔案的ID來查詢HAL模組,並獲得hw_module_t的子結構,來呼叫hw_module_methods_t中的open函式來初始化hw_device_t的子結構體。
最後實現JAVA函式
1)package xxx/*宣告原始檔中的類屬於哪個具體包,包的名字是有層次的,各層之間以點分割,必須與檔案系統結構相同*/
2)import xxx /*將其他包中的類引入當前名字空間中*/
3)public class LedActivity extends Activity {
static {
System.loadLibrary("led");??作用是什麼,不太理解?
}
/*在C++中實現native函式,需要特定格式,可以用javah來幫助宣告用javac編譯我們的java類,獲得class檔案,然後javah xxx.class 生成.h檔案JNI格式按.h檔案書寫*/
public static native boolean ledInit();/*要將JNI呼叫的方法做本地宣告,關鍵詞native*/
public static native boolean ledClose();
private static native boolean ledSetOn(int number);
private static native boolean ledSetOff(int number);
CheckBox[] cb = new CheckBox[8];
CheckBox cbAll;// 全選
Button btnQuit;// 退出按鈕
@Override/*重寫父類,加 @Override系統可以幫你檢查方法的正確性*/
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 獲取 xml 中對應的控制元件
cb[0] = (CheckBox) findViewById(R.id.cbLed1);
cb[1] = (CheckBox) findViewById(R.id.cbLed2);
cb[2] = (CheckBox) findViewById(R.id.cbLed3);
cb[3] = (CheckBox) findViewById(R.id.cbLed4);
cb[4] = (CheckBox) findViewById(R.id.cbLed5);
cb[5] = (CheckBox) findViewById(R.id.cbLed6);
cb[6] = (CheckBox) findViewById(R.id.cbLed7);
cb[7] = (CheckBox) findViewById(R.id.cbLed8);
cbAll = (CheckBox) findViewById(R.id.cbLedAll);
btnQuit = (Button) findViewById(R.id.btnQuit);
// 初始化點選事件物件
// 初始化點選事件物件
MyClickListener myClickListern = new MyClickListener();
// LED1-LED8 選中 / 取消事件
for (int i = 0; i < 8; i++) {
cb[i].setOnClickListener(myClickListern);
}
// 全選選中 / 取消事件
cbAll.setOnClickListener(myClickListern);
// 退出按鈕點選事件處理
btnQuit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
}
// led 初始化
if (!ledInit()) {
new AlertDialog.Builder(this).setTitle("init led fail").show();
//led 初始化失敗,則使控制元件不可點選
for (int i = 0; i < 8; i++)
cb[i].setEnabled(false);
cbAll.setEnabled(false);
}
}
// 自定義的事件監聽器類,用來處理 CheckBox 選中和取消事件
public class MyClickListener implements OnClickListener {
@Override
public void onClick(View v) {
// 遍歷陣列,判斷是哪個 led 控制元件被選中
for (int i = 0; i < 8; i++) {
if (v == cb[i]) {
// 根據選中 / 取消狀態來控制 led 燈的亮 / 滅
controlLed(i + 1, cb[i].isChecked());
return;
}
}
// 全選按鈕,遍歷陣列,對所有 led 燈做控制
if (v == cbAll) {
for (int i = 0; i < 8; i++) {
controlLed(i + 1, cbAll.isChecked());
cb[i].setChecked(cbAll.isChecked());
}
}
}
/*******************************************/
// 功能: LED 亮 / 滅處理
// 引數:
// number : 燈編號
// on :true ,亮 ;fase, 滅
/*******************************************/
private void controlLed(int number, boolean on) {
if (on) {
ledSetOn(number);
} else {
ledSetOff(number);
}
}
}
相關文章
- Android音訊驅動學習(一) Audio HALAndroid音訊
- 安卓除錯 .so 斷到 JNI_OnLoad 或者 .init段安卓除錯
- 安卓部署Java專案安卓Java
- 安卓動畫(一)安卓動畫
- java JNI簡介Java
- java呼叫c++動態庫之jni呼叫JavaC++
- H5與安卓/IOS進行原生互動H5安卓iOS
- 【Camera專題】Qcom-Camera驅動框架淺析(Hal層->Driver層)框架
- Android JNI開發系列之Java與C相互呼叫AndroidJava
- 如何安裝印表機驅動 印表機驅動安裝步驟
- 舵機驅動——STM32F407ZGT6探索者——HAL庫
- STM32 HAL 庫硬體 I2C 驅動 MPU6050
- MySQL的驅動表與被驅動表MySql
- 360驅動大師怎麼安裝印表機驅動 360驅動安裝印表機的步驟
- Java JNI 學習筆記Java筆記
- 【Camera專題】你應該熟悉的Camera驅動框架一(Hal層->kernel層)框架
- 驅動精靈是幹嘛的 驅動精靈怎麼安裝驅動
- 惠普印表機驅動怎麼安裝 惠普印表機驅動安裝教程
- Java的Panama專案與JNI以及外部函式介面FFIJava函式
- 安卓啟動時間獲取安卓
- 星雲精準測試對安卓底層驅動程式碼的測試案例分析安卓
- Android:JNI與NDK(二)交叉編譯與動態庫,靜態庫Android編譯
- 安卓安卓
- 【詳解】JNI (Java Native Interface) (二)Java
- 【詳解】JNI (Java Native Interface) (三)Java
- 【詳解】JNI (Java Native Interface) (四)Java
- 【詳解】JNI(Java Native Interface)(一)Java
- Java安全之JNI繞過RASPJava
- Ubuntu 16.04 安裝Nvidia驅動Ubuntu
- [vmware to openstack] 安裝virtio驅動
- 群控與安卓底層開發安卓
- win10 inf驅動怎麼安裝_win10 inf驅動如何安裝Win10
- 【Android】書客編輯器安卓Java版Android安卓Java
- 安卓自動化打包環境搭建安卓
- 安卓-自動切換APP圖示安卓APP
- Mysql java JDBC驅動jar包MySqlJavaJDBCJAR
- 安卓應用優化:使用反射測試安卓裝置是否使用“動態桌布”安卓優化反射
- MySQL8.0.11 Community Server 與 驅動 mysql-connector-java-8.0.11.jarMySqlUnityServerJavaJAR