Trang này mô tả các thay đổi đối với trình điều khiển liên kết trong Android 8, cung cấp chi tiết về việc sử dụng IPC liên kết và liệt kê chính sách SELinux bắt buộc.
Các thay đổi đối với trình điều khiển liên kết
Kể từ Android 8, khung Android và HAL (Lớp trừu tượng phần cứng) hiện giao tiếp với với nhau bằng liên kết. Vì hoạt động giao tiếp này làm tăng đáng kể tính liên kết lưu lượng truy cập, Android 8 có một số điểm cải tiến được thiết kế để duy trì IPC liên kết một cách nhanh chóng. Nhà cung cấp hệ thống SoC (SoC) và OEM (Nhà sản xuất thiết bị gốc) nên hợp nhất trực tiếp từ các nhánh có liên quan của android-4.4, android-4.9 trở lên của kernel/common (hạt nhân/phổ biến).
Nhiều miền liên kết (ngữ cảnh)
Common-4.4 trở lên, bao gồm cả thượng nguồnĐể phân chia rõ ràng lưu lượng truy cập liên kết giữa khung (độc lập với thiết bị) và mã của nhà cung cấp (dành riêng cho thiết bị), Android 8 đưa ra khái niệm trình liên kết ngữ cảnh. Mỗi ngữ cảnh liên kết đều có nút thiết bị riêng và ngữ cảnh riêng (dịch vụ). Bạn chỉ có thể truy cập vào trình quản lý bối cảnh thông qua thiết bị này nút mà nó thuộc về và khi chuyển nút liên kết qua một nút nhất định ngữ cảnh đó, nó chỉ có thể truy cập được từ cùng một ngữ cảnh đó bởi một quy trình khác, do đó tách biệt hoàn toàn các miền với nhau. Để biết chi tiết về cách sử dụng, hãy xem vndbinder và vndservicemanager.
Tán xạ
Common-4.4 trở lên, bao gồm cả thượng nguồnTrong các bản phát hành Android trước đây, mọi phần dữ liệu trong lệnh gọi liên kết đều được sao chép ba lần:
- Để chuyển đổi tuần tự thành một
Parcel
trong quá trình gọi - Sau khi truy cập vào trình điều khiển nhân hệ điều hành, hãy sao chép
Parcel
vào mục tiêu quy trình - Một lần để huỷ chuyển đổi tuần tự
Parcel
trong quy trình mục tiêu
Cách sử dụng Android 8
thu thập phân tán
tối ưu hoá để giảm số lượng bản sao từ 3 xuống còn 1. Thay vì
chuyển đổi tuần tự dữ liệu trong Parcel
trước, dữ liệu vẫn ở trạng thái ban đầu
cấu trúc và bố cục bộ nhớ, đồng thời trình điều khiển ngay lập tức sao chép cấu trúc đó vào mục tiêu
của chúng tôi. Sau khi dữ liệu ở trong quá trình xử lý mục tiêu, cấu trúc và bộ nhớ
bố cục giống nhau và dữ liệu có thể được đọc mà không cần bản sao khác.
Khoá chi tiết nhỏ
Common-4.4 trở lên, bao gồm cả thượng nguồnTrong các bản phát hành Android trước đây, trình điều khiển liên kết đã sử dụng một phương thức khoá chung để bảo vệ chống lại quyền truy cập đồng thời vào các cấu trúc dữ liệu quan trọng. Mặc dù có rất ít tranh chấp khoá, vấn đề chính là nếu một luồng có mức độ ưu tiên thấp lấy được khoá rồi bị giành quyền, nó có thể trì hoãn rất nghiêm trọng các luồng có mức độ ưu tiên cao hơn cần có được cùng một khoá. Điều này gây ra hiện tượng giật trong chủ.
Nỗ lực ban đầu để giải quyết sự cố này liên quan đến việc vô hiệu hoá quyền giành quyền trong khi giữ khoá chung. Tuy nhiên, đây là một giải pháp xâm nhập nhiều hơn là một giải pháp thực sự, và cuối cùng đã bị từ chối bởi thượng nguồn và bị loại bỏ. Các lần thử tiếp theo tập trung vào việc làm cho việc khoá chi tiết hơn, một phiên bản của tính năng này đang hoạt động trên thiết bị Pixel kể từ tháng 1 năm 2017. Mặc dù phần lớn những thay đổi đó được công khai, nhưng đã được cải tiến đáng kể trong các phiên bản tiếp theo.
Sau khi xác định các vấn đề nhỏ trong việc triển khai khoá chi tiết, chúng tôi đã nghĩ ra một giải pháp cải tiến với một cấu trúc khoá khác và cho rằng các thay đổi trong tất cả các nhánh hạt nhân phổ biến. Chúng tôi sẽ tiếp tục thử nghiệm triển khai trên một số lượng lớn các thiết bị khác nhau; vì chúng ta không biết về vấn đề còn tồn đọng, đây là cách triển khai được đề xuất cho việc vận chuyển thiết bị trên Android 8.
Kế thừa mức độ ưu tiên theo thời gian thực
Common-4.4 và phổ biến-4.9 (sắp ra mắt)Trình điều khiển liên kết luôn hỗ trợ tính kế thừa mức độ ưu tiên tốt. Là một số lượng quy trình trong Android chạy ở mức độ ưu tiên theo thời gian thực tăng lên, trong một số Trong các trường hợp khác, giờ đây sẽ trở nên hợp lý khi một luồng thời gian thực thực hiện lệnh gọi liên kết, luồng trong quy trình xử lý lệnh gọi đó cũng chạy ở mức độ ưu tiên theo thời gian thực. Người nhận hỗ trợ các trường hợp sử dụng này, Android 8 nay triển khai tính năng kế thừa ưu tiên theo thời gian thực trong trình điều khiển liên kết.
Ngoài cơ chế kế thừa mức độ ưu tiên ở cấp giao dịch, mức độ ưu tiên của nút tính kế thừa cho phép một nút (đối tượng dịch vụ liên kết) chỉ định một giá trị tối thiểu mức độ ưu tiên mà tại đó các lệnh gọi đến nút này sẽ được thực thi. Các phiên bản trước của Android vốn đã hỗ trợ tính năng kế thừa mức độ ưu tiên của nút với các giá trị đẹp, nhưng Android 8 bổ sung tính năng hỗ trợ kế thừa nút của chính sách lên lịch theo thời gian thực.
Thay đổi về không gian người dùng
Android 8 bao gồm tất cả các thay đổi cần thiết đối với không gian người dùng để tương thích với
trình điều khiển liên kết trong nhân hệ điều hành chung với một ngoại lệ: Chương trình gốc
để vô hiệu hoá tính năng kế thừa ưu tiên theo thời gian thực cho
/dev/binder
đã dùng một
ioctl. Quá trình phát triển tiếp theo chuyển đổi điều khiển mức độ ưu tiên
sang một phương thức chi tiết hơn theo chế độ liên kết (không theo
ngữ cảnh). Do đó, ioctl không nằm trong nhánh chung của Android mà thay vào đó
được gửi trong kernel thông thường của chúng tôi.
Ảnh hưởng của thay đổi này là tính kế thừa mức độ ưu tiên theo thời gian thực bị vô hiệu hoá
mặc định cho mọi nút. Nhóm hiệu suất Android đã tìm thấy
sẽ hữu ích khi bật tính năng kế thừa mức độ ưu tiên theo thời gian thực cho tất cả các nút trong phương thức
hwbinder
. Để đạt được hiệu quả tương tự, hãy chọn quả anh đào
thay đổi này trong không gian người dùng.
SHA cho các nhân phổ biến
Để có được các thay đổi cần thiết đối với trình điều khiển liên kết, hãy đồng bộ hoá với SHA thích hợp:
- Phổ biến-3,18
cc8b90c121de ANDROID: binder: không kiểm tra quyền prio khi khôi phục. - Phổ biến-4,4
76b376eac7a2 ANDROID: liên kết: không kiểm tra quyền prio khi khôi phục. - Phổ biến-4,9
ecd972d4f9b5 ANDROID: binder: không kiểm tra quyền prio khi khôi phục.
Thao tác với IPC liên kết
Trước đây, các quy trình của nhà cung cấp sử dụng giao tiếp liên quy trình liên kết
(IPC) để giao tiếp. Trong Android 8, nút thiết bị /dev/binder
chỉ áp dụng cho các quy trình khung, nghĩa là quy trình của nhà cung cấp không còn
sẽ có quyền truy cập vào thiết bị đó. Quy trình của nhà cung cấp có thể truy cập vào /dev/hwbinder
, nhưng
phải chuyển đổi giao diện AIDL để sử dụng HIDL. Dành cho những nhà cung cấp muốn tiếp tục
bằng cách sử dụng giao diện AIDL giữa các quy trình của nhà cung cấp, Android hỗ trợ IPC liên kết dưới dạng
được mô tả bên dưới. Trong Android 10, AIDL ổn định cho phép tất cả
các quy trình để sử dụng /dev/binder
, đồng thời giải quyết vấn đề ổn định
đảm bảo đã giải quyết HIDL và /dev/hwbinder
. Để biết cách sử dụng Kênh chính thức
AIDL, xem
AIDL cho HAL.
vndbinder
Android 8 hỗ trợ một miền liên kết mới để các dịch vụ của nhà cung cấp sử dụng, được truy cập vào
sử dụng /dev/vndbinder
thay vì /dev/binder
. Với
Ngoài /dev/vndbinder
, Android hiện có 3 tính năng
Miền IPC:
Miền IPC | Mô tả |
---|---|
/dev/binder |
IPC giữa các quy trình khung/ứng dụng có giao diện AIDL |
/dev/hwbinder |
IPC giữa các quy trình khung/nhà cung cấp với giao diện HIDL
IPC giữa các quy trình của nhà cung cấp có giao diện HIDL |
/dev/vndbinder |
IPC giữa các quy trình của nhà cung cấp/nhà cung cấp bằng giao diện AIDL |
Để /dev/vndbinder
xuất hiện, hãy đảm bảo cấu hình nhân hệ điều hành
mục CONFIG_ANDROID_BINDER_DEVICES
được đặt thành
"binder,hwbinder,vndbinder"
(đây là tuỳ chọn mặc định trong
cây nhân hệ điều hành chung).
Thường thì quy trình của nhà cung cấp không trực tiếp mở trình điều khiển liên kết mà thay vào đó
liên kết với thư viện không gian người dùng libbinder
, điều này sẽ mở ra
trình điều khiển liên kết. Thêm một phương thức cho ::android::ProcessState()
hãy chọn trình điều khiển liên kết cho libbinder
. Quy trình của nhà cung cấp phải
gọi phương thức này trước khi gọi vào ProcessState,
IPCThreadState
hoặc trước khi thực hiện bất kỳ lệnh gọi liên kết nào nói chung. Người nhận
sử dụng, thực hiện lệnh gọi sau đây sau main()
trong quy trình của nhà cung cấp
(máy khách và máy chủ):
ProcessState::initWithDriver("/dev/vndbinder");
vndservicemanager
Trước đây, dịch vụ liên kết được đăng ký bằng servicemanager
,
nơi chúng có thể được truy xuất bởi các quy trình khác. Trong Android 8,
servicemanager
hiện được dùng riêng cho khung và ứng dụng
các quy trình và quy trình của nhà cung cấp không thể truy cập vào dữ liệu đó nữa.
Tuy nhiên, các dịch vụ của nhà cung cấp hiện có thể sử dụng vndservicemanager
, một
thực thể của servicemanager
sử dụng /dev/vndbinder
thay vì /dev/binder
và được tạo từ cùng các nguồn với
khung servicemanager
. Quy trình của nhà cung cấp không cần phải thực hiện
các thay đổi để trò chuyện với vndservicemanager
; khi một quy trình của nhà cung cấp mở
/dev/vndbinder
, tra cứu dịch vụ sẽ tự động chuyển đến
vndservicemanager
.
Tệp nhị phân vndservicemanager
có trong mặc định của Android
tệp makefile của thiết bị.
Chính sách SELinux
Những quy trình của nhà cung cấp muốn sử dụng chức năng liên kết để giao tiếp với nhau cần những thứ sau:
- Quyền truy cập vào
/dev/vndbinder
. - Nối
{transfer, call}
móc vàovndservicemanager
binder_call(A, B)
cho bất kỳ miền của nhà cung cấp A nào muốn gọi vào miền B của nhà cung cấp qua giao diện liên kết của nhà cung cấp.- Quyền đối với các dịch vụ của
{add, find}
trongvndservicemanager
Để đáp ứng yêu cầu 1 và 2, hãy sử dụng vndbinder_use()
macro:
vndbinder_use(some_vendor_process_domain);
Để đáp ứng yêu cầu 3, binder_call(A, B)
dành cho nhà cung cấp
các quy trình A và B cần trao đổi qua liên kết có thể giữ nguyên mà không
cần đổi tên.
Để đáp ứng yêu cầu 4, bạn phải thay đổi cách tên dịch vụ, nhãn dịch vụ và quy tắc đều được xử lý.
Để biết chi tiết về SELinux, hãy xem phần Bảo mật được tăng cường Linux trong Android. Để biết chi tiết về SELinux trong Android 8.0, hãy xem SELinux cho Android 8.0.
Tên dịch vụ
Trước đây, nhà cung cấp sẽ xử lý tên dịch vụ đã đăng ký trong một
service_contexts
và đã thêm các quy tắc tương ứng để truy cập
tệp đó. Tệp service_contexts
mẫu từ
device/google/marlin/sepolicy
:
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
Trong Android 8, vndservicemanager
sẽ tải
Thay vào đó, tệp vndservice_contexts
. Chuyển dịch vụ của nhà cung cấp sang
vndservicemanager
(và những giá trị này đã thuộc phiên bản cũ
service_contexts
) vào tệp mới
vndservice_contexts
.
Nhãn dịch vụ
Trước đây, các nhãn dịch vụ như u:object_r:atfwd_service:s0
được xác định trong tệp service.te
. Ví dụ:
type atfwd_service, service_manager_type;
Trong Android 8, bạn phải thay đổi loại thành
vndservice_manager_type
rồi di chuyển quy tắc này sang
vndservice.te
. Ví dụ:
type atfwd_service, vndservice_manager_type;
quy tắc về người quản lý dịch vụ
Trước đây, các quy tắc cấp cho miền quyền truy cập để thêm hoặc tìm dịch vụ từ
servicemanager
. Ví dụ:
allow atfwd atfwd_service:service_manager find; allow some_vendor_app atfwd_service:service_manager add;
Trong Android 8, các quy tắc như vậy có thể giữ nguyên và sử dụng cùng một lớp. Ví dụ:
allow atfwd atfwd_service:service_manager find; allow some_vendor_app atfwd_service:service_manager add;