本文轉載自:https://blog.csdn.net/gh201030460222/article/details/80551897
Android O HIDL的實現對接
1. HIDL的定義
1.1. 關於Android更新
2. HIDL處於系統哪個部位及怎么通信的
2.1. Android 系統架構包含以下組件
2.2. HAL的類型
3. HIDL的實現
4. HIDL版本維護
5. 實例對接HIDL完整過程
5.1. 新功能接口的添加
5.2. 修改HIDL及HAL層文件
5.2.1. HIDL文件修改
5.2.2. HAL文件生成
5.2.2. HAL層與HIDL的實現對接
5.3. HAL層與framework層對接
5.4. 應用層接口的添加
5.5. 驗證功能
Android O HIDL的實現對接
Google對於HIDL的詳細說明,以及語法解析鏈接如下(ps: 需要翻牆才可以打開)
https://source.android.com/devices/architecture/hidl/
以下是個人學習整理的資料,以及實做的一個例子
1. HIDL的定義
HIDL 讀作 hide-l,全稱是 Hardware Interface Definition Language。它在 Android Project Treble 中被起草,在 Android 8.0 中被全面使用。其誕生目的是,框架可以在無需重新構建 HAL 的情況下進行替換。HAL將由供應商或SOC 制造商構建,放置在設備的 /vendor 分區中,這樣一來,框架就可以在其自己的分區中通過 OTA 進行替換,而無需重新編譯 HAL
1.1. 關於Android更新
利用新的供應商接口,Project Treble 將供應商實現(由芯片制造商編寫的設備專屬底層軟件)與 Android 操作系統框架分離開來。Android 7.x 及更早版本中沒有正式的供應商接口,因此設備制造商必須更新大量 Android 代碼才能將設備更新到新版 Android 系統。
圖 1. Treble 推出前的 Android 更新環境
Treble 提供了一個穩定的新供應商接口,供設備制造商訪問 Android 代碼中特定於硬件的部分,這樣一來,設備制造商只需更新 Android 操作系統框架,即可跳過芯片制造商直接提供新的 Android 版本:
圖 2. Treble 推出后的 Android 更新環境
2. HIDL處於系統哪個部位及怎么通信的
2.1. Android 系統架構包含以下組件
2.2. HAL的類型
為了更好地實現模塊化,Android 8.0 對 Android 操作系統底層進行了重新架構。作為此變化的一部分,運行 Android 8.0 的設備必須支持綁定式或直通式 HAL:
• 綁定式 HAL。以 HAL 接口定義語言 (HIDL) 表示的 HAL。這些 HAL 取代了早期 Android 版本中使用的傳統 HAL 和舊版 HAL。在綁定式 HAL 中,Android 框架和 HAL 之間通過 Binder 進程間通信 (IPC) 調用進行通信。所有在推出時即搭載了 Android 8.0 或后續版本的設備都必須只支持綁定式 HAL。
• 直通式 HAL。以 HIDL 封裝的傳統 HAL 或舊版 HAL。這些 HAL 封裝了現有的 HAL,可在綁定模式和 Same-Process(直通)模式下使用。升級到 Android 8.0 的設備可以使用直通式 HAL。
3. HIDL的實現
Android O 對 Android 操作系統的架構重新進行了設計,以在獨立於設備的 Android 平台與特定於設備和供應商的代碼之間定義清晰的接口。Android 已經以 HAL 接口的形式(在 hardware/libhardware 中定義為 C 標頭)定義了許多此類接口。HIDL 將這些 HAL 接口替換為穩定的帶版本接口,它們可以是采用 C++(如下所述)或 Java 的客戶端和服務器端 HIDL 接口。
HIDL 接口具有客戶端和服務器實現:
• HIDL 接口的客戶端實現是指通過在該接口上調用方法來使用該接口的代碼
• 服務器實現是指 HIDL 接口的實現,它可接收來自客戶端的調用並返回結果(如有必要)
在從 libhardware HAL 轉換為 HIDL HAL 的過程中,HAL 實現成為服務器,而調用 HAL 的進程則成為客戶端。默認實現可提供直通和綁定式 HAL,並可能會隨着時間而發生變化,如下所示:
4. HIDL版本維護
HIDL 要求每個使用 HIDL 編寫的接口均必須帶有版本編號。HAL 接口一經發布便會被凍結,如果要做任何進一步的更改,都只能在接口的新版本中進行。雖然無法對指定的已發布接口進行修改,但可通過其他接口對其進行擴展。
5. 實例對接HIDL完整過程
因為要google規定,已經發的hal版本是不能再更改的,除非再update成新的版本,而在porting的平台上,幾乎都沒有遵守這個規定,只是在原先的基礎版本上去update而已,把要修改的文件進行重新繼承整理,沒更新版本。但這樣卻也可以過google的測試。。。
而對於新加的可以修改p2p group密碼的接口,這個是一個新的接口,所以,也沒有重新生成新的版本去update。下面讓我們一起來看下這個hidl新接口的添加過程
5.1. 新功能接口的添加
因為這個是添加了一個新的接口功能,所以在wpa_supplicant中添加了可以修改p2p group密碼的接口,新加接口記為
p2p_set_passphrase()
# wpa_cli -ip2p0 -p /data/misc/wifi/sockets/
> SET p2p_pwd “12345678”
<3>P2P-GROUP-STARTED p2p-p2p0-1 GO ssid="DIRECT-ac-Android_e8q7" freq=2472 passphrase="12345678" go_dev_addr=01:bc:43:cf:04:44 [PERSISTENT]
<3>AP-STA-CONNECTED 4a:d5:dd:5a:74:14 p2p_dev_addr=4a:d5:dd:5a:74:14”
1
2
3
4
5.2. 修改HIDL及HAL層文件
5.2.1. HIDL文件修改
wpa_supplicant_8/wpa_supplicant/hidl/1.0
1
因為修改的是p2p相關部分,所以,可以直接查看p2p_iface.cpp,按其中的接口setSsidPostfix()進行類似添加即可,修改密碼接口名為setPasswdPostfix()
5.2.2. HAL文件生成
hardware/interfaces/wifi/supplicant/1.0
1
如果此時把HIDL中的接口setPasswdPostfix()添加到HAL中的ISupplicantP2pIface.hal中,當build code時,系統會提示frozen的相關錯誤,說明這個文件的接口是不能添加,以及修改的。如果要修改,只能第三方廠家自己重新實現一套HAL接口。
而第三方Icecream,可以在vendor/Icecream/hardware/interfaces下面去創建自己對應的目錄實現HAL層的對接。
所以,對於第三方來說,我們得重新創建目錄了,如
vendor/Icecream/hardware/interfaces/wifi/supplicant/1.0
1
同時把要修改的HAL文件進行修改,因為我們只用到了ISupplicantP2pIface.hal文件,而我們還是要用到之前hardware/interfaces/wifi/supplicant/1.0目錄中的其他文件,如此,我們不用直接使用ISupplicantP2pIface.hal,而是要對這個文件進行繼承的方式進行,創建對應的IIcecreamSupplicantP2pIface.hal來繼承ISupplicantP2pIface.hal,如下:
package Icecream.hardware.wifi.supplicant@1.0;
import android.hardware.wifi.supplicant@1.0::ISupplicantP2pIface;
/**
* Interface exposed by the supplicant for each P2P mode network
* interface (e.g p2p0) it controls.
*/
interface IIcecreamSupplicantP2pIface
extends android.hardware.wifi.supplicant@1.0::ISupplicantP2pIface {
/**
* Set the postfix to be used for P2P Passwd's.
*
* @param postfix String to be appended to Passwd.
* @return status Status of the operation.
* Possible status codes:
* |SupplicantStatusCode.SUCCESS|,
* |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
* |SupplicantStatusCode.FAILURE_UNKNOWN|,
* |SupplicantStatusCode.FAILURE_IFACE_INVALID|
*/
setPasswdPostfix(vec<uint8_t> postfix) generates (SupplicantStatus status);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
如上,我們已經把Hal文件創建好了,那接下來就得創建Android.mk跟Android.db文件了。
而此時,我們只要先source、lunch一下后,再執行一下
vendor/Icecream/hardware/interfaces/update-makefiles.sh即可以在生成對應的Android.mk跟Android.db了。
update-makefiles.sh內容如下:
#!/bin/bash
source system/tools/hidl/update-makefiles-helper.sh
do_makefiles_update \
"Icecream.hardware:vendor/Icecream/hardware/interfaces/" \
"android.hardware:hardware/interfaces" \
"android.hidl:system/libhidl/transport"
1
2
3
4
5
6
7
8
update-makefiles.sh內容的寫法,可以參考hardware/interfaces/update-makefiles.sh,再添加自己平台對應的hal目錄路徑即可
在執行了update-makefiles.sh后,你可以看到自己的目錄會多出了Android.bp、Android.mk
vendor/Icecream/hardware/interfaces$ tree wifi
wifi
├── Android.bp
└── supplicant
└── 1.0
├── Android.bp
├── Android.mk
└── IIcecreamSupplicantP2pIface.hal
1
2
3
4
5
6
7
8
9
對於以上的Android.mk中,這個要對應其父類
hardware/interfaces/wifi/supplicant/1.0/Android.mk的寫法,注意把父類中的對應LIBRARIES在這個子類中都加上去,避免后面要build code error,要再重新檢查一下,還會有讓你莫名其妙的錯誤,讓你無從下手,這點要注意了。
所以,在Android.mk中,還要在LOCAL_JAVA_LIBRARIES與LOCAL_STATIC_JAVA_LIBRARIES中添加父類依賴的
android.hidl.base-V1.0-java這個lib進去
這時,HAL目前就已經生成了,我們可以直接在這個目錄mm,讓其在out目錄下生成對應的java跟cpp文件,以借framework中的java調用,以及hidl層中cpp調用
5.2.2. HAL層與HIDL的實現對接
以上第二步已經把HAL層生成,以及對應文件也生成了,接下來就得進行把hal層跟hidl層對接起來了。
這時在hidl層中,原生在使用ISupplicantP2pIface這個類的以及其對應命名空間的,得全部改成IIcecreamSupplicantP2pIface的來繼承了,這時會出現很多error,所以,接下來,得針對這些error一個一個解決,最后讓hidl可以build過
5.3. HAL層與framework層對接
經過上面5.1、5.2,已經把HIDL的實現跟hal層對接起來了,接下來把hal層跟framework對接起來,並向上層應用提供接口調用
frameworks/opt/net/wifi/service/java/com/android/server/wifi/p2p
frameworks/base/wifi/java/android/net/wifi/p2p
1
2
同5.2中的(3)一樣,把SupplicantP2pIfaceHal.java中原先對應的ISupplicantP2pIface類全部改成IIcecreamSupplicantP2pIface,再仿照setSsidPostfix()接口實現對應要添加的接口setPasswdPostfix(),然后一層一層往上加
SupplicantP2pIfaceHal.java-->WifiP2pNative.java-->WifiP2pServiceImpl.java-->WifiP2pManager.aidl-->WifiP2pManager.java
1
5.4. 應用層接口的添加
在TvSetting中去添加對應的接口,對於這個問題,目前是加在點擊wifi direct中的搜索時,就會去設置group的密碼,這樣,當連接時,group就可以直接使用設置過的密碼進行連接了
diff --git a/Settings/src/com/android/tv/settings/connectivity/p2p/WifiP2pSettings.java b/Settings/src/com/android/tv/settings/connectivity/p2p/WifiP2pSettings.java
index 2488272..91d486d 100644
--- a/Settings/src/com/android/tv/settings/connectivity/p2p/WifiP2pSettings.java
+++ b/Settings/src/com/android/tv/settings/connectivity/p2p/WifiP2pSettings.java
@@ -620,6 +620,9 @@ public class WifiP2pSettings extends SettingsPreferenceFragment
}
});
}
+
+ Log.d(TAG, "startSearch set p2p passwd");
+ mWifiP2pManager.setP2pPasswd("12348765");
}
private void updateDevicePref() {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
5.5. 驗證功能
1)wifi打開后
2)在命令行執行以下操作,用於觀察建立group時的passwd是否是正確的
# wpa_cli -ip2p0 -p /data/misc/wifi/sockets/
3)進入wifi Direct中,點擊搜索
4)用手機進行Wifi Direct直連,或者手機進行Miracast連接。
5)觀察剛剛串口中的打印信息passphrase,是否跟你自己設定的正確
<3>P2P-GROUP-STARTED p2p-p2p0-2 GO ssid=”DIRECT-ac-Android_e8q7” freq=2472 passphrase=”12348765” go_dev_addr=01:bc:43:cf:04:44 [PERSISTENT]
<3>AP-STA-CONNECTED 4a:d5:dd:5a:74:14 p2p_dev_addr=4a:d5:dd:5a:74:14”
以上的passphrase=”12348765”,跟在TvSetting中添加的代碼是一樣,說明已經設定成功了
以上的HIDL對接流程,對以后再進行相關方面的接口添加,減少以后相關porting新接口的操作,或要再重新從1.0 –>1.1當參考用