Treble框架
Android 8.0 重新設(shè)計了 Android 操作系統(tǒng)框架(在一個名為“Treble”的項目中),以便讓制造商能夠以更低的成本更輕松、更快速地將設(shè)備更新到新版 Android 系統(tǒng)。在這種新架構(gòu)中,HAL 接口定義語言(HIDL,發(fā)音為“hide-l”)指定了 HAL 和其用戶之間的接口,讓用戶無需重新構(gòu)建 HAL,就能替換 Android 框架。在 Android 10 中,HIDL 功能已整合到 AIDL 中。此后,HIDL 就被廢棄了,并且僅供尚未轉(zhuǎn)換為 AIDL 的子系統(tǒng)使用。
利用新的供應(yīng)商接口,Treble 將供應(yīng)商實現(xiàn)(由芯片制造商編寫的設(shè)備專屬底層軟件)與 Android 操作系統(tǒng)框架分離開來。供應(yīng)商或 SOC 制造商構(gòu)建一次 HAL,并將其放置在設(shè)備的 /vendor 分區(qū)中;框架可以在自己的分區(qū)中通過無線下載 (OTA) 更新進(jìn)行替換,而無需重新編譯 HAL。
舊版 Android 架構(gòu)與當(dāng)前基于 HIDL 的架構(gòu)之間的區(qū)別在于對供應(yīng)商接口的使用:
-
Android 7.x 及更低版本中沒有正式的供應(yīng)商接口,因此設(shè)備制造商必須更新大量 Android 代碼才能將設(shè)備更新到新版 Android 系統(tǒng)
- Android 8.0 及更高版本提供了一個穩(wěn)定的新供應(yīng)商接口,因此設(shè)備制造商可以訪問 Android 代碼中特定于硬件的部分,這樣一來,設(shè)備制造商只需更新 Android 操作系統(tǒng)框架,即可跳過芯片制造商直接提供新的 Android 版本:
所有搭載 Android 8.0 及更高版本的新設(shè)備都可以利用這種新架構(gòu)。為了確保供應(yīng)商實現(xiàn)的向前兼容性,供應(yīng)商接口會由供應(yīng)商測試套 (VTS) 進(jìn)行驗證,該套件類似于兼容性測試套件 (CTS)。您可以使用 VTS 在舊版 Android 架構(gòu)和當(dāng)前 Android 架構(gòu)中自動執(zhí)行 HAL 和操作系統(tǒng)內(nèi)核測試。
Android官網(wǎng)資料
Android 開發(fā)者網(wǎng)站,面向應(yīng)用開發(fā)者,
https://developer.android.google.cn/
Android 開源操作系統(tǒng)網(wǎng)站,面向系統(tǒng)開發(fā)者,系統(tǒng)架構(gòu),安全,Treble方案,VNDK這里都有詳細(xì)的說明,官網(wǎng)資料都是晦澀難懂,多看幾遍就好。
https://source.android.google.cn/devices/architecture

Treble之后系統(tǒng)變化
按 Treble 架構(gòu)要求,System 分區(qū)拆分成 System 和 Vendor 分區(qū)。System 鏡像包含Android 原生倉及 Vendor/ODM 開發(fā)的 app 和 framework/JNI。Vendor 主要提供芯片/硬件相關(guān)接口實現(xiàn)。Android 版本中與 Treble 相關(guān)的新特性:
- HIDL binderized,framework 與 HAL 實現(xiàn)運行在不同進(jìn)程,通過 hwbinder 通信
- System、Vendor 獨立分區(qū)
- Vendor 包含獨立 SELinux 策略、Property 屬性
- Kernel 要求 linux4.4 以上版本,推薦 4.9
- 新增 VTS 測試,保證兼容性
- 新增 PureAndroidTest,由 Google 提供鏡像,覆蓋廠商 system 分區(qū)后執(zhí)行 VTS 測試;
| IPC 域 | 說明 |
|---|---|
| /dev/binder | 框架/應(yīng)用進(jìn)程之間的 IPC,使用 AIDL 接口 |
| /dev/hwbinder | 框架/供應(yīng)商進(jìn)程之間的 IPC,使用 HIDL 接口 供應(yīng)商進(jìn)程之間的 IPC,使用 HIDL 接口 |
| /dev/vndbinder | 供應(yīng)商/供應(yīng)商進(jìn)程之間的 IPC,使用 AIDL 接口 |
binder,hwbinder,vndbinder之間的關(guān)系
Android O 獨立 System、Vendor 分區(qū)后,增加了相應(yīng) Selinux 規(guī)則,System 進(jìn)程不能按原有方式綁定 Vendor 服務(wù)。因為在 Android O 中,/dev/binder 設(shè)備節(jié)點成為了框架進(jìn)程的專屬節(jié)點,這意味著 Vendor 進(jìn)程將無法再訪問該節(jié)點,而要使用 kernel 新增的 hwbinder和 vndbinder。

About VNDK
Treble工程的目標(biāo)是system/vendor進(jìn)程解耦,讓Android系統(tǒng)更新不依賴芯片方案商適配,要實現(xiàn)這一框架,需要先解耦system/vendor依賴(VNDK),并提供穩(wěn)定的API/ABI, 再打通system/vendor直接溝通(HIDL),這玩意,要學(xué)習(xí)參考官網(wǎng)資料吧.
https://source.android.google.cn/devices/architecture/vndk
HIDL簡介
Android O 引入 HIDL 語言,用于描述 O 中新增的跨進(jìn)程 HAL 接口。原生架構(gòu)下,F(xiàn)ramework 作為 Client 端,Vendor 作為 Service 端。Framework 框架由谷歌提供,原生 HIDL要求保持穩(wěn)定,適配工作主要在 Vendor Service。
Client 端:包含 Android 原生或海思擴(kuò)展服務(wù)。
Server 端:Android 原生或芯片廠擴(kuò)展 HAL 服務(wù)。
HIDL 文件(.hal)一般使用 Android.bp 編譯。Android.bp 通過 hidl-gen 工具將 HIDL 文
件轉(zhuǎn)換成.h/*.cpp,再編譯生成 android.hardware.xxxx@1.0.so 或 vendor.xxx.hardware.xxxx@1.0。

HIDL示例Demo
- 創(chuàng)建HIDL接口
hardware/interfaces/demo/1.0/IDemo.hal
package android.hardware.demo@1.0;
interface IDemo {
doDemo(float bar) generates(int32_t status);
};
- 生成接口的執(zhí)行代碼
這個命令會在hardware/interfaces/demo/1.0/default 下生成Demo.cpp 和 Demo.h兩個文件
hidl-gen -o hardware/interfaces/demo/1.0/default -Lc++-impl -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport android.hardware.demo@1.0
- 生成makefile
根目錄執(zhí)行腳本,自動生成*.hal 對應(yīng)的 Android.bp 和 Android.mk 文件
./hardware/interfaces/update-makefiles.sh
- 添加接口聲明
擴(kuò)展接口需要在 vendor/manifest.xml 中聲明, 或device/hisilicon/Hi37XXVXXX/manifest.xml
<hal format="hidl">
<name>android.hardware.demo</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IDemo</name>
<instance>default</instance>
</interface>
</hal>
- 增加 hash 值
HIDL 接口層是 Treble 架構(gòu)的基礎(chǔ),原則上發(fā)布后不能變動,新接口應(yīng)升級版本號。系統(tǒng)編譯時會檢查已發(fā)布接口 hash 值,防止篡改。已有接口對應(yīng) hash 值詳見hardware/interfaces/current.txt。新增擴(kuò)展接口,可在 Android 根目錄執(zhí)行命令生成 hash 值:
hidl-gen -L hash -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport android.hardware.demo@1.0 >> hardware/interfaces/current.txt
- 服務(wù)端實現(xiàn)
代碼目錄結(jié)構(gòu)如下,default目錄下面Android.mk, service.cpp, android.hardware.demo@1.0-service.rc需要自
己創(chuàng)建,目錄結(jié)構(gòu)如下,
hardware/interfaces/demo/1.0
├── Android.bp
├── Android.mk
├── default
│ ├── android.hardware.demo@1.0-service.rc
│ ├── Android.mk
│ ├── Demo.cpp
│ ├── Demo.h
│ └── service.cpp
└── IDemo.hal
Demo.cpp就添加一個打印
#include "Demo.h"
#include <log/log_main.h>
#define LOG_TAG "Demo"
namespace android {
namespace hardware {
namespace demo {
namespace V1_0 {
namespace implementation {
// Methods from ::android::hardware::demo::V1_0::IDemo follow.
Return<int32_t> Demo::doDemo(float bar) {
// Demo就簡單做個打印,
ALOGD(" Hello Hidl Demo Bar is %f \n", bar);
return int32_t {0};
}
// Methods from ::android::hidl::base::V1_0::IBase follow.
IDemo* HIDL_FETCH_IDemo(const char* /* name */) {
return new Demo();
}
} // namespace implementation
} // namespace V1_0
} // namespace demo
} // namespace hardware
} // namespace android
service.cpp將IDemo注冊到hwservicemanager:
#define LOG_TAG "android.hardware.demo@1.0-service"
#include "Demo.h"
#include <hidl/LegacySupport.h>
#include <android/log.h>
using android::hardware::demo::V1_0::IDemo;
using android::hardware::defaultPassthroughServiceImplementation;
int main() {
return defaultPassthroughServiceImplementation<IDemo>();
}
android.hardware.demo@1.0-service.rc啟動腳本
service demo_hal_service /vendor/bin/hw/android.hardware.demo@1.0-service
class hal
user root
group root
Android.mk參考其他hidl模塊寫
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.demo@1.0-impl
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := \
Demo.cpp
LOCAL_C_INCLUDES := \
LOCAL_SHARED_LIBRARIES := \
libutils \
libcutils \
liblog \
libbinder \
libhardware \
libhidlbase \
libhidltransport \
libhidlmemory \
android.hardware.demo@1.0 \
include $(BUILD_SHARED_LIBRARY)
############################################
include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.demo@1.0-service
LOCAL_INIT_RC := android.hardware.demo@1.0-service.rc
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true
LOCAL_SRC_FILES := service.cpp
LOCAL_SHARED_LIBRARIES := \
android.hardware.demo@1.0 \
libbase \
libcutils \
libhidlbase \
libhidltransport \
liblog \
libutils
include $(BUILD_EXECUTABLE)
- 實現(xiàn)客戶端
//Android.bp
frameworks/native/cmds/demo$ cat *
cc_binary {
name: "demo_client",
srcs: ["demo_client.cpp"],
shared_libs: [
"libhidlbase",
"libhidltransport",
"libutils",
"liblog",
"android.hardware.demo@1.0",
],
}
//demo_client.cpp
#include <android/hardware/demo/1.0/IDemo.h>
#include <hidl/Status.h>
#include <hidl/LegacySupport.h>
#include <hidl/HidlSupport.h>
#include <utils/misc.h>
#include <utils/Log.h>
#define LOG_TAG "demo_client"
using android::hardware::demo::V1_0::IDemo;
using android::sp;
int main(int argc, char* argv[])
{
android::sp<IDemo> service = IDemo::getService();
if(service == nullptr){
ALOGD("Failed to get service\n");
return -1;
}
float bar = 1.0;
service->doDemo(bar);
return 0;
}
- 添加SELinux策略
我這邊把自定義SELinux策略放到了獨立目錄,
//device/honeybee/system/sepolicy/vendor/hal_demo.te
type hal_demo, domain;
type hal_demo_exec, exec_type, file_type, vendor_file_type;
hwbinder_use(hal_demo);
init_daemon_domain(hal_demo)
add_hwservice(hal_demo, hal_demo_hwservice)
//device/honeybee/system/sepolicy/vendor/file_contexts
# Vendor files
/(vendor|system/vendor)/bin/DoraemonService u:object_r:DoraemonService_exec:s0
/(vendor|system/vendor)/bin/hw/android\.hardware\.demo@1\.0-service u:object_r:hal_demo_exec:s0
//device/honeybee/system/sepolicy/vendor/hwservice.te
type hal_demo_hwservice, hwservice_manager_type;
//device/honeybee/system/sepolicy/vendor/hwservice_contexts
android.hardware.demo::IDemo u:object_r:hal_demo_hwservice:s0
- 添加編譯聲明
如果不添加,系統(tǒng)編譯的時候不會編譯你的模塊,
PRODUCT_PACKAGES += \
android.hardware.demo@1.0 \
android.hardware.demo@1.0-impl \
android.hardware.demo@1.0-service
- 生成二進(jìn)制
新增 Demo HIDL示例生成的二進(jìn)制文件如下所示:
system/lib64/android.hardware.demo@1.0.so
system/lib/android.hardware.demo@1.0.so
vendor/etc/init/android.hardware.demo@1.0-service.rc
vendor/bin/hw/android.hardware.demo@1.0-service
vendor/lib64/hw/android.hardware.demo@1.0-impl.so
vendor/lib/hw/android.hardware.demo@1.0-impl.so
- Demo測試
把demo_client 編譯好push到/system/bin,
Hi3751V811:/system/bin # demo_client
Hi3751V811:/system/bin # logcat | grep Demo
01-01 16:00:11.529 1809 1809 D Demo : Hello Hidl Demo Bar is 1.000000
----Demo完畢。
HIDL平時需要參考系統(tǒng)模塊寫就好,如果要學(xué)習(xí)參考官網(wǎng)就好,或者下面博客
http://www.itdecent.cn/p/ca6823b897b5

