Re: [問題] AOSP 的 source code

作者: gn00618777 (非常念舊)   2016-07-08 19:56:59
※ 引述《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
這有點像是一個陣列,它的陣列名稱是第一個元素的位址,也是這個陣列起始位址的概
念。
我的理解是這樣 @@"
有錯請指教囉,謝謝。

Links booklink

Contact Us: admin [ a t ] ucptt.com