看板 AndroidDev 關於我們 聯絡資訊
※ 引述《mshockwave (夏克維夫)》之銘言: : 首先我也非常感動有人研究 AOSP HAL : 我當初掉進 AOSP 的坑也是從 HAL 開始 : ※ 引述《gn00618777 (非常念舊)》之銘言: : : 在asop內 : : mydroid/hardware/libhardware/hardware.c 內的 hw_get_module function : : 原型是 : : hw_get_module(const *id, hw_module_t **) : : 但在許多 android service 中會呼叫,並帶入參數(如: : : camera_module_t、sensor_module_t) : : 在 service 內宣告一個 sensor_module_t 的變數 mSensorModule : : 呼叫 hw_get_module( * , (hw_module_t**)&mSensorModule); : : mSensorModule 結構裡有包含 hw_module_t 的型態,mSensorModule : : 被強制作 hw_module_t 型態轉換有甚麼用意嗎? : 從結論來說 你可以見識到 google 工程師 c/c++ 的怪物等級: : 你可以觀察一下 像 sensors_module_t, camera_module_t 這些 struct : 他們有個共同特徵:第一個 struct field 一定是 hw_module_t 型態 : 例如 sensors_module_t 他第一個 struct field 就是 "struct hw_module_t common;" : 而假如 sensors_module_t 和 hw_module_t 長這樣: : struct hw_module_t { : int id; : const char* name; : } : struct sensors_module_t{ : struct hw_module_t common; : int foo; : int bar; : } : 那其實在記憶體中你可以把它想成他會"攤開"成這樣: : struct sensors_module_t { : int id; : const char* name; : int foo; : int bar : } : 所以假如你有一個 sensors_module_t 型態的變數 sensorMod : 那你依然可以呼叫 ((hw_module_t*)&sensorMod)->name : 沒錯 老師說 struct 的 memory layout 不一定會一個 field 接著一個 : 可能會因 alignment 而有所調整 但因為 hw_module_t 必定是在第一個 field : (這是類似約定的規定 google沒寫出來是因為這件事只要給硬體廠知道就好) : 所以不用擔心 alignment 問題 : 這種手法看起來是不是很熟悉? 沒錯 他們就是用 C 來模擬 C++ 的繼承 : 為什麼不直接用 C++? 痾...因為很多硬體工程師只會寫C (X) : 因為 C 許多性質都比較適合寫底層的 code (O) : : 最後 mSensorModule 可以拿來呼叫mSensorModule->get_sensor_list() function : : mSensorModule不是已經被轉換成 hw_module_t型態了? 他為啥可以呼叫 : : sensors_module_t型態裡面的 get_sensor_list fucntion? : : 謝謝指教.. : 其實 hw_get_module 的流程挺簡單的: : 丟給他你想要的硬體後 他會解析名稱然後用 dlopen 載入適當的 .so file : 也就是該硬體的實作 share library : 而每個實作的硬體 shared library : 禮面一定會有個變數 HAL_MODULE_INFO_SYM (這也是約定的) : 像 sensor 的就在這邊: http://goo.gl/186qAC : 那個變數其實就是 XXX_module_t 的實作 在前面 dlopen 後會用 dlsym 去得到它 : 所以雖然你在 hw_get_module 那邊已經把 mSensorModule 轉型成 hw_module_t** : 但重點就在這邊:hw_module_t** 是指標的指標 也就是 dereference 第一次後 : 會是個 pointer, 在 C 語言中這種"輸出型變數"很常見 所以顯而易見的 : 這邊就是輸出個 hw_module_t* 這樣的話因為是個指標 你就可以做一大堆奇怪的事了 : 說得更明確一點:sensors_module_t 的"實體" 在 share library 裡面 : 所以就算你轉成 hw_module_t* 但 sensors_module_t 的實體位址不會變啊 : 你依然存取得到他 以及呼叫他的函式 感謝m大的解說 dlsym 回傳 symble 為 HMI 的位址,而這個位址是 struct AL_MODULE_INFO_SYM 的位址 他把他做一個強制轉換為 hw_module_t 型態的指標,對傳進來的 *pHmi 做賦值 *pHmi 當然就是傳進來的 hw_module_t 位址,現在被賦值後,就指向 struct HAL_MODULE_INFO_SYM 的 common filed 位址了,也就是 hw_module_t 而 hw_module_t 的位址就是 struct AL_MODULE_INFO_SYM 的第一個,當然最後 最上面就可以呼叫 struct HAL_MODULE_INFO_SYM 內 get_sensor_list function 這有點像是一個陣列,它的陣列名稱是第一個元素的位址,也是這個陣列起始位址的概 念。 我的理解是這樣 @@" 有錯請指教囉,謝謝。 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 58.115.110.28 ※ 文章網址: https://www.ptt.cc/bbs/AndroidDev/M.1467979025.A.D31.html ※ 編輯: gn00618777 (58.115.110.28), 07/08/2016 19:59:19