- 對應的官方文檔地址:HIDL(General) - Using Binder IPC
This page describes changes to the binder driver in Android O, provides details on using binder IPC, and lists required SELinux policy.
這一章節描述了 Android O 中關於 Binder 的一些變化,提供了使用 Binder IPC 機制的細節,以及列出了一些所需要的 SELinux 相關策略。
1. Binder 驅動的改變
(Changes to binder driver)
Starting in Android O, the Android framework and HALs now communicate with each other using binder. As this communication dramatically increases binder traffic, Android O includes several improvements designed to keep binder IPC fast. SoC vendors and OEMs integrating the latest version of the driver should review the list of these improvements, relevant SHAs for the 3.18, 4.4, and 4.9 kernels, and required userspace changes.
從 Android O 開始,Android 框架層與 HAL 層之間就要通過 Binder 機制來進行通訊。這導致通過 Binder 傳輸的數據流量大大提升,爲了保持 Binder IPC 的高效,Android O 中對 Binder 進行了一些能可提升性能的修改。集成了最新版本驅動的 SoC 供應商 與 OEM 應查看所列出的相應的改進,關於用於 3.18
、4.4
與 4.9
內核的 SHA,以及所需求的用戶空間的修改。
1.1 多個 Binder 域(上下文)
(Multiple binder domains (contexts))
In common-3.10, common-3.18, common-4.4, common-4.9, and upstream
在 common-3.10
, common-3.18
, common-4.4
, common-4.9
以及更上游的版本中。
To cleanly split the binder traffic between framework (device-independent) and vendor (device-specific) code, Android O introduces the concept of a binder context. Each binder context has its own device node and its own context (service) manager. You can access the context manager only through the device node to which it belongs and, when passing a binder node through a certain context, it is accessible from that same context only by another process, thus completely isolating the domains from each other. For details on using, see vndbinder and vndservicemanager.
爲了明確劃分框架(獨立於設備)和供應商(特定於設備)代碼之間的 Binder 流量,Android O 介紹了一個 Binder 上下文的概念。每個 Binder 上下文都擁有自己的設備節點以及上下文(服務)管理者。當您通過某個上下文傳遞 Binder 節點時,您只能通過它所屬的設備節點來訪問對應的上下文管理器,它只能通過另一個進程來訪問,從而使得各個域完全隔離。更多詳細信息在 vndbinder 和 vndservicemanager 小節中有描述。
1.2 散集列表
(Scatter-gather)
In common-3.10, common-3.18, common-4.4, common-4.9, and upstream
在 common-3.10
, common-3.18
, common-4.4
, common-4.9
以及更上游的版本中。
In previous releases of Android, every piece of data in a binder call was copied three times:
- Once to serialize it into a
Parcel
in the calling process- Once in the kernel driver to copy the
Parcel
to the target process- Once to unserialize the
Parcel
in the target process
在以往的 Android 版本中,Binder 調用的每一個數據都會被複制三次:
- 一次是在調用的進程中將數據序列化爲一個
Parcel
。 - 一次是在內核驅動中將
Parcel
拷貝給目標進程。 - 一次是在目標進程中將
Parcel
反序列化。
Android O uses scatter-gather optimization to reduce the number of copies from 3 to 1. Instead of serializing data in a Parcel first, data remains in its original structure and memory layout and the driver immediately copies it to the target process. After the data is in the target process, the structure and memory layout is the same and the data can be read without requiring another copy.
Android O 採用散集優化的方式將拷貝次數從三次減少到一次。數據保持原本的結構與內存佈局,而驅動則立即將其複製到目標進程中,這樣第一次拷貝操作就省下了。當數據到達目標進程中,其結構與內存佈局是不變的,因此可以不需要另外的拷貝操作就讀取數據(將序列化與反序列化過程去掉了)。
1.3 更細化地加鎖
(Fine-grained locking)
In common-3.18, common-4.4, common-4.9, and upstream
在 common-3.18
, common-4.4
, common-4.9
以及更上游的版本中。
In previous Android releases, the binder driver used a global lock to protect against concurrent access to critical data structures. While there was minimal contention for the lock, the main problem was that if a low-priority thread obtained the lock and then got preempted, it could seriously delay higher-priority threads needing to obtain the same lock. This caused jank in the platform.
在以往的 Android 版本中, Binder 驅動會使用一個全局的鎖來防止對於關鍵數據結構的併發訪問。雖然對於鎖的搶奪情況很少,但主要的問題在於,如果一個低優先級線程獲得了鎖,隨後被搶佔,它就會使需要獲得相同鎖的高優先級線程嚴重地延遲。這在平臺中導致了 jank
(PS:我不知道是什麼東西) 這種情況。
Initial attempts to resolve this problem involved disabling preemption while holding the global lock. However, this was more of a hack than a true solution, and was eventually rejected by upstream and discarded. Subsequent attempts focused on making locking more fine-grained, a version of which has been running on Pixel devices since January 2017. While the majority of those changes were made public, substantial improvements were made in future versions.
最初,通過嘗試在持有全局鎖時禁用搶佔來解決這個問題。然而這更像是一種 “hack” 行爲,而非真正的解決方案,並且最終被更上游的版本所拒絕與棄用。隨後進行的嘗試專注於更細化地加鎖,自 2017 年 1 月開始,這一版本一直在 Pixel 設備上運行。目前主要的改動已經發布到公開版本中,在以後的版本中還會繼續有大量的改進加入其中。
After identifying small issues in the fine-grained locking implementation, we devised an improved solution with a different locking architecture and submitted the changes in the 3.18, 4.4, and 4.9 common branches. We continue to test this implementation on a large number of different devices; as we are unaware of any outstanding issues, this is the recommended implementation for devices shipping with Android O.
在解決了實現細粒度鎖中的一些問題之後,我們設計了一個改進的解決方案,它採用不同的鎖架構,這個更改方案已經提交到 3.18
,4.4
,4.9 common
分支中。我們繼續要大量不同的設備上測試了這一實現,沒有發現任何突出的問題,因此目前這是 Android O 的推薦實現方案。
Note: We strongly encourage budgeting sufficient testing hours for fine-grained locking.
注意:我們強烈建議爲細粒度鎖制定足夠的測試時間。
1.4 實時優先級繼承
(Real-time priority inheritance)
In common-3.18, common-4.4, common-4.9 (upstream coming soon)
在 common-3.18
, common-4.4
, common-4.9
(上游版本即將開放)
The binder driver has always supported nice priority inheritance. As an increasing number of processes in Android run at real-time priority, in some cases it now makes sense that if a real-time thread makes a binder call, the thread in the process that handles that call also runs at real-time priority. To support these use cases, Android O now implements real-time priority inheritance in the binder driver.
Binder 驅動一直很好地支持優先級繼承。隨着越來越多的 Android 進程在實時優先級運行,某些情況下,如果一個實時線程發出一個 Binder 調用,則處理該調用的進程中的線程也會在實時優先級中運行。爲了支持這些用例,Android O 在 Binder 驅動程序中實現了實時優先繼承。
In addition to transaction-level priority inheritance, node priority inheritance allows a node (binder service object) to specify a minimum priority at which calls into this node should be executed. Previous versions of Android already supported node priority inheritance with nice values, but Android O adds support for real-time scheduling policies node inheritance.
除了事務級的優先級繼承以外,節點優先級繼承允許節點(Binder 服務對象)指定一個最低優先級,該節點應執行調用該節點的請求。在以前的 Android 版本中,已經很好地支持了節點優先級繼承,而 Android O 則增加了對於實時調度策略節點繼承的支持。
Note: The Android performance team found that real-time priority inheritance caused unwanted side-effects in the framework binder domain (
/dev/binder
), so real-time priority inheritance is disabled for that domain.
注意: Android 性能團隊發現,實時優先級繼承在框架的 Binder 域(/dev/binder
)中造成了不必要的副作用,所以在該域中,實時優先級繼承是被禁用的。
1.5 用戶空間更改
(Userspace changes)
Android O includes all userspace changes required to work with the current binder driver in the common kernel with one exception: The original implementation to disable real-time priority inheritance for
/dev/binder
used an ioctl. Subsequent development switched control of priority inheritance to a more fine-grained method that is per binder mode (and not per context). Thus, the ioctl is not in the Android common branch and is instead submitted in our common kernels.
Android O 中包含了所有需要的用戶空間更改,這些變化需要與公共內核中的當前 Binder 驅動一起工作,但有一個例外:原始的實現中採用一個 ioctl
操作禁用 /dev/binder
的實時優先級繼承。隨後的開發會將優先級繼承轉換爲一種更具細粒度的方法,即每個 Binder 模式(而非每個上下文)。因此,ioctl
在我們的公共內核中,而不是在 Android 公共分支中提交。
The effect of this change is that real-time priority inheritance is disabled by default for every node. The Android performance team has found it beneficial to enable real-time priority inheritance for all nodes in the hwbinder domain. To achieve that same effect, cherry-pick this change in userspace.
這些關於實時優先級繼承的改變的效果,在默認情況下對於每個節點都是禁用的。Android 性能團隊發現,在 hwbinder
域中啓用實時優先級繼承是有好處的。爲實現同樣的效果,需要在用戶空間中選擇這個更改。
1.6 公共內核中的一些 SHA
(SHAs for common kernels)
To obtain necessary changes to the binder driver, sync to the SHAs below (or later):
- Common-3.18
cc8b90c121de ANDROID: binder: don’t check prio permissions on restore.- Common-4.4
76b376eac7a2 ANDROID: binder: don’t check prio permissions on restore.- Common-4.9
ecd972d4f9b5 ANDROID: binder: don’t check prio permissions on restore.
爲了獲得必要的關於 Binder 驅動的更改,需要同步下面這些 SHA:
- Common-3.18
cc8b90c121de ANDROID: binder: don’t check prio permissions on restore. - Common-4.4
76b376eac7a2 ANDROID: binder: don’t check prio permissions on restore. - Common-4.9
ecd972d4f9b5 ANDROID: binder: don’t check prio permissions on restore.
2. 使用 Binder IPC
(Using binder IPC)
Historically, vendor processes have used binder interprocess communication (IPC) to communicate. In Android O, the
/dev/binder
device node becomes exclusive to framework processes, meaning vendor processes no longer have access to it. Vendor processes can access/dev/hwbinder
, but must convert their AIDL interfaces to use HIDL. For vendors who want to continue using AIDL interfaces between vendor processes, Android supports binder IPC as described below.
從以往的情況來看,供應商進程使用 Binder 進程間通訊機制進行通信,在 Android O 中,/dev/binder
設備節點成爲了獨立於框架進程的存在,這就意味着供應商進程不能再訪問它。供應商進程可以訪問 /dev/hwbinder
,但必須將它們的 AIDL 接口轉換爲 HIDL 接口。對於需要繼續在供應商進程間使用 AILD 接口的供應商,Android 支持如下所述的 Binder IPC。
2.1 vndbinder
Android O supports a new binder domain for use by vendor services, accessed using
/dev/vndbinder
instead of/dev/binder
. With the addition of/dev/vndbinder
, Android now has the following three IPC domains:
IPC Domain Description /dev/binder
IPC between framework/app
processes with AIDL interfaces/dev/hwbinder
IPC between framework/vendor
processes with HIDL interfacesIPC between vendor processes with HIDL interfaces /dev/vndbinder
IPC between vendor/vendor
processes with AIDL Interfaces
Android O 支持由供應商服務所使用的一個新的域,使用 /dev/vndbinder
代替對 /dev/binder
的訪問。在添加 /dev/vndbinder
之後,目前 Binder IPC 共有以下三個域:
IPC 域 | 相關信息 |
---|---|
/dev/binder |
framework/app 進程與 AIDL 接口之間的 IPC |
/dev/hwbinder |
framework/vendor 進程與 HIDL 接口之間的 IPC |
vendor 進程與 HIDL 接口之間的 IPC |
|
/dev/vndbinder |
vendor/vendor 進程與 AIDL 接口之間的 IPC |
For
/dev/vndbinder
to appear, ensure the kernel configuration itemCONFIG_ANDROID_BINDER_DEVICES
is set to “binder,hwbinder,vndbinder” (this is the default in Android’s common kernel trees).
對於 /dev/vndbinder
的出現,確保 CONFIG_ANDROID_BINDER_DEVICES
這一內核配置項被設置爲 binder,hwbinder,vndbinder
(這在 Android 公共內核樹中是默認的)。
Normally, vendor processes don’t open the binder driver directly and instead link against the
libbinder
userspace library, which opens the binder driver. Adding a method for::android::ProcessState()
selects the binder driver forlibbinder
. Vendor processes should call this method before calling intoProcessState
,IPCThreadState
, or before making any binder calls in general. To use, place the following call after the main() of a vendor process (client and server):
通常供應商進程不會直接打開 Binder 驅動,而是連接到 libbinder
用戶空間庫去,這個庫打開了 Binder 驅動。加入一個方法爲 ::android::ProcessState()
選擇用於 libbinder
的 Binder 驅動程序。在供應商進程調用 ProcessState
, IPCThreadState
或對任何 Binder 的一般性調用之前,這一方法就應該被調用了。要使用它,則請在供應商進程(客戶端和服務端)的主函數之後進行如下調用:
ProcessState::initWithDriver("/dev/vndbinder");
2.2 vndservicemanager
Previously, binder services were registered with
servicemanager
, where they could be retrieved by other processes. In Android O,servicemanager
is now used exclusively by framework and app processes and vendor processes can no longer access it.
在以前,Binder 驅動會註冊到 servicemanager
中,這樣它可以被其它進程獲取。而在 Android O 中,servicemanager
目前已經完全只由框架與應用程序來使用,而供應商進程已經無法訪問它。
However, vendor services can now use
vndservicemanager
, a new instance ofservicemanager
that uses/dev/vndbinder
instead of/dev/binder
and which is built from the same sources as frameworkservicemanager
. Vendor processes do not need to make changes to talk tovndservicemanager
; when a vendor process opens/dev/vndbinder
, service lookups automatically go tovndservicemanager
.
供應商服務現在可以使用 vndservicemanager
,這是用 /dev/vndbinder
代替了 /dev/binder
而構成的新的 servicemanager
實例,它與框架層的 servicemanager
是用同一源碼所構建的。供應商進程不需要爲了與 vndservicemanager
進行通訊而做出更改,當供應商進程打開 /dev/vndbinder
後,服務就會自動查找到 vndservicemanager
。
The
vndservicemanager
binary is included in Android’s default device makefiles.
vndservicemanager
的二進制文件已經包含在 Android 默認的設備 makefile
中。
3. SELinux 策略
(SELinux policy)
Vendor processes that want to use binder functionality to communicate with each other need the following:
- Access to
/dev/vndbinder
.- Binder
{transfer, call}
hooks intovndservicemanager
.binder_call(A, B)
for any vendor domain A that wants to call into vendor domain B over the vendor binder interface.- Permission to
{add, find}
services invndservicemanager
.
需要使用 Binder 的功能以同其它進程通訊的供應商進程需要以下幾個條件:
- 訪問
/dev/vndbinder
。 - Binder 的鉤子函數
{transfer, call}
設置到vndservicemanager
中。 binder_call(A, B)
用於想要通過供應商 Binder 接口來調用到供應商域 B 的供應商域 A。- 在
vndservicemanager
中獲得{add, find}
的服務權限。
To fulfill requirements 1 and 2, use the
vndbinder_use()
macro:
爲完成第一第二個需求,則要使用到宏 vndbinder_use()
:
vndbinder_use(some_vendor_process_domain);
To fulfill requirement 3, the
binder_call(A, B)
for vendor processes A and B that need to talk over binder can stay in place, and doesn’t need renaming.
爲完成第三個需求,對供應商進程 A 和 B 的 binder_call(A, B)
可以保持在一個恰當的位置,並不需要重命名。
To fulfill requirement 4, you must make changes in the way service names, service labels, and rules are handled.
爲完成第四個需求,您必須對服務名稱,服務標籤與規則的方式進行更改。
For details on SELinux, see Security-Enhanced Linux in Android. For details on SELinux in Android 8.0, see SELinux for Android 8.0.
對於 SELinux 的更詳細的細節,可以閱讀 Android 中的安全增強型 Linux。對於 Android O 的 SELinux,可以參看 Android 8.0 的安全增強型 Linux。
3.1 服務名稱
(Service names)
Previously, vendor processes registered service names in aservice_contexts
file and added corresponding rules for accessing that file. Exampleservice_contexts
file fromdevice/google/marlin/sepolicy
:
在之前,供應商進程將服務名稱註冊到 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
In Android O,
vndservicemanager
loads thevndservice_contexts
file instead. Vendor services migrating tovndservicemanager
(and which are already in the oldservice_contexts
file) should be added to the newvndservice_contexts
file.
在 Android O 中,採用 vndservicemanager
來加載 vndservice_contexts
文件以替代上述過程。遷移到 vndservicemanager
中的供應商服務應該增加到相應的 vndservice_contexts
文件中。
3.2 服務標籤
(Service labels)
Previously, service labels such asu:object_r:atfwd_service:s0
were defined in aservice.te
file. Example:
以往的服務標籤,比如 u:object_r:atfwd_service:s0
會定義在一個 service.te
文件中,如下:
type atfwd_service, service_manager_type;
In Android O, you must change the type to
vndservice_manager_type
and move the rule to thevndservice.te
file. Example:
在 Android O 中,您必須將類型改變爲 vndservice_manager_type
,並且將規則移動到 vndservice.te
文件中,如下:
type atfwd_service, vndservice_manager_type;
3.3 服務管理者規則
(Servicemanager rules)
Previously, rules granted domains access to add or find services from
servicemanager
. Example:
以前,規則授權域訪問從 servicemanager
添加或查找服務,比如:
allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;
In Android O, such rules can stay in place and use the same class. Example:
在 Android O 中,這樣的設置可以不被更改,保持原位,比如:
allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;