本頁描述了對Android 8中的活頁夾驅動程序的更改,提供了有關使用活頁夾IPC的詳細信息,並列出了所需的SELinux策略。
對活頁夾驅動程序的更改
從Android 8開始,Android框架和HAL現在使用活頁夾彼此通信。由於這種通信方式大大增加了活頁夾流量,因此Android 8包括多項旨在保持活頁夾IPC快速運行的改進。 SoC供應商和OEM應該直接從android / 4.4,android-4.9及更高版本的內核/通用項目的相關分支中合併。
多個活頁夾域(上下文)
通用4.4及更高版本,包括上游為了在框架代碼(獨立於設備)和供應商代碼(特定於設備)之間明確劃分綁定程序流量,Android 8引入了綁定程序上下文的概念。每個綁定器上下文都有其自己的設備節點和其上下文(服務)管理器。您只能通過上下文管理器所屬的設備節點來訪問上下文管理器,並且在將綁定程序節點通過某個上下文傳遞時,只能通過另一個進程從同一上下文訪問上下文管理器,從而將域彼此完全隔離。有關使用的詳細信息,請參見vndbinder和vndservicemanager 。
散佈聚集
通用4.4及更高版本,包括上游在以前的Android版本中,活頁夾調用中的每個數據都被複製了3次:
- 一次在調用過程中將其序列化為
Parcel
- 一旦在內核驅動程序中將
Parcel
複製到目標進程 - 一次在目標流程中反序列化
Parcel
Android 8使用分散收集優化功能將副本數量從3減少到1。 Parcel
先在Parcel
中序列化數據,數據保持其原始結構和內存佈局,並且驅動程序立即將其複製到目標進程。數據進入目標過程後,其結構和內存佈局相同,並且可以讀取數據而無需其他副本。
細粒度鎖定
通用4.4及更高版本,包括上游在以前的Android版本中,綁定程序驅動程序使用全局鎖來防止對關鍵數據結構的並發訪問。儘管鎖的爭用最少,但是主要問題是,如果低優先級線程獲得了鎖然後被搶占,則可能嚴重延遲需要獲得同一鎖的高優先級線程。這在平台中造成了麻煩。
解決此問題的最初嘗試包括在持有全局鎖的同時禁用搶占。但是,這更多的不是真正的解決方案,而是最終被上游拒絕並丟棄。隨後的嘗試著重於使鎖定更細粒度,自2017年1月以來,該版本已在Pixel設備上運行。儘管大多數更改已公開,但後續版本進行了重大改進。
在確定細粒度的鎖定實現中的小問題之後,我們設計了一種具有不同鎖定架構的改進解決方案,並在所有通用內核分支中提交了更改。我們將繼續在大量不同的設備上測試該實現;由於我們不知道有任何未解決的問題,因此這是Android 8隨附設備的推薦實現。
實時優先級繼承
Common-4.4和Common-4.9(即將推出上游)綁定程序驅動程序始終支持良好的優先級繼承。隨著越來越多的Android進程以實時優先級運行,在某些情況下,現在有意義的是,如果實時線程進行綁定程序調用,則處理該調用的進程中的線程也將以實時優先級運行。為了支持這些用例,Android 8現在在活頁夾驅動程序中實現了實時優先級繼承。
除了事務級優先級繼承外,節點優先級繼承還允許節點(活頁夾服務對象)指定執行該節點調用的最低優先級。早期版本的Android已經支持具有良好值的節點優先級繼承,但是Android 8增加了對實時調度策略節點繼承的支持。
用戶空間變更
Android 8包含了與公共內核中的當前活頁夾驅動程序一起使用所需的所有用戶空間更改,但有一個例外:禁用/dev/binder
實時優先級繼承的原始實現使用了ioctl 。隨後的開發將優先級繼承的控制切換為每個綁定器模式(而不是每個上下文)的更細粒度的方法。因此,ioctl不在Android通用分支中,而是在我們的通用內核中提交。
此更改的結果是,默認情況下每個節點都禁用實時優先級繼承。 Android性能團隊發現,為hwbinder
域中的所有節點啟用實時優先級繼承是hwbinder
。為了達到相同的效果,請在用戶空間中選擇此更改。
通用內核的SHA
要對綁定程序驅動程序進行必要的更改,請同步至適當的SHA:
- 普通3.18
cc8b90c121de ANDROID:活頁夾:不檢查還原時的prio權限。 - 通用4.4
76b376eac7a2 ANDROID:活頁夾:不檢查恢復時的prio權限。 - 普通4.9
ecd972d4f9b5 ANDROID:活頁夾:不檢查還原時的prio權限。
使用活頁夾IPC
從歷史上看,供應商流程曾使用活頁夾進程間通信(IPC)進行通信。在Android 8中, /dev/binder
設備節點變為框架進程專有的,這意味著供應商進程不再有權訪問它。供應商進程可以訪問/dev/hwbinder
,但是必須將其AIDL接口轉換為使用HIDL。對於希望繼續在供應商流程之間使用AIDL接口的供應商,Android支持如下所述的活頁夾IPC。
vndbinder
Android 8支持供供應商服務使用的新的綁定器域,可使用/dev/vndbinder
而不是/dev/binder
。通過添加/dev/vndbinder
,Android現在具有以下三個IPC域:
IPC域 | 描述 |
---|---|
/dev/binder | 具有AIDL接口的框架/應用程序流程之間的IPC |
/dev/hwbinder | 具有HIDL接口的框架/供應商流程之間的IPC 具有HIDL接口的供應商流程之間的IPC |
/dev/vndbinder | 使用AIDL接口的供應商/供應商流程之間的IPC |
對於/dev/vndbinder
出現,確保內核配置項CONFIG_ANDROID_BINDER_DEVICES
設置為"binder,hwbinder,vndbinder"
這是Android的通用內核樹默認值)。
通常,供應商進程不會直接打開活頁夾驅動程序,而是鏈接到libbinder
用戶空間庫,後者會打開活頁夾驅動程序。為::android::ProcessState()
添加方法為libbinder
選擇活頁夾驅動程序。供應商進程應在調用ProcessState,
IPCThreadState
或進行任何綁定程序調用之前先調用此方法。若要使用,請將以下調用放在供應商進程(客戶端和服務器)的main()
之後:
ProcessState::initWithDriver("/dev/vndbinder");
vndservicemanager
以前,綁定程序服務已在servicemanager
中註冊,可以在其他進程中檢索它們。在Android 8中, servicemanager
現在僅由框架和應用程序進程使用,並且供應商進程無法再訪問它。
但是,供應商服務現在可以使用vndservicemanager
,這是servicemanager
的新實例,它使用/dev/vndbinder
而不是/dev/binder
,並且與框架servicemanager
具有相同的來源。供應商流程無需進行更改即可與vndservicemanager
;當供應商進程打開/ dev/vndbinder
,服務查找將自動轉到vndservicemanager
。
vndservicemanager
二進製文件包含在Android的默認設備makefile中。
SELinux政策
想要使用活頁夾功能相互通信的供應商流程需要以下條件:
- 訪問
/dev/vndbinder
。 - 活頁夾
{transfer, call}
掛接到vndservicemanager
。 - 要通過供應商資料夾接口調用供應商域B的任何供應商域A的
binder_call(A, B)
。 - 對
vndservicemanager
{add, find}
服務的vndservicemanager
。
要滿足要求1和2,請使用vndbinder_use()
宏:
vndbinder_use(some_vendor_process_domain);
為了滿足要求3,需要通過綁定器進行對話的供應商進程A和B的binder_call(A, B)
可以保留在原位,並且不需要重命名。
為了滿足要求4,您必須更改服務名稱,服務標籤和規則的處理方式。
有關SELinux的詳細信息,請參見Android中的安全性增強的Linux 。有關Android 8.0中的SELinux的詳細信息,請參見適用於Android 8.0的SELinux 。
服務名稱
以前,供應商在service_contexts
文件中處理註冊的服務名稱,並添加了訪問該文件的相應規則。來自device/google/marlin/sepolicy
示例service_contexts
文件:
AtCmdFwd u:object_r:atfwd_service:s0 cneservice u:object_r:cne_service:s0 qti.ims.connectionmanagerservice u:object_r:imscm_service:s0 rcs u:object_r:radio_service:s0 uce u:object_r:uce_service:s0 vendor.qcom.PeripheralManager u:object_r:per_mgr_service:s0
在Android 8中, vndservicemanager
會改為加載vndservice_contexts
文件。遷移到vndservicemanager
供應商服務(已經在舊的service_contexts
文件中)應該添加到新的vndservice_contexts
文件中。
服務標籤
以前,在service.te
文件中定義了諸如u:object_r:atfwd_service:s0
類的服務標籤。例:
type atfwd_service, service_manager_type;
在Android 8中,您必須將類型更改為vndservice_manager_type
並將規則移至vndservice.te
文件。例:
type atfwd_service, vndservice_manager_type;
服務經理規則
以前,規則授予域訪問權限以從servicemanager
添加或查找服務。例:
allow atfwd atfwd_service:service_manager find; allow some_vendor_app atfwd_service:service_manager add;
在Android 8中,此類規則可以保留並使用相同的類。例:
allow atfwd atfwd_service:service_manager find; allow some_vendor_app atfwd_service:service_manager add;