Android 8 tái cấu trúc hệ điều hành Android để xác định các giao diện rõ ràng giữa các
nền tảng Android độc lập với thiết bị và mã dành riêng cho thiết bị và nhà cung cấp.
Android đã định nghĩa nhiều giao diện như vậy ở dạng giao diện HAL,
được xác định là tiêu đề C trong hardware/libhardware
. HIDL thay thế các tham số này
Giao diện HAL có giao diện ổn định, được lập phiên bản, có thể là
giao diện HIDL phía máy chủ trong C++ (mô tả dưới đây) hoặc
Java.
Các trang trong phần này mô tả cách triển khai C++ của giao diện HIDL,
bao gồm cả thông tin chi tiết về các tệp được tạo tự động từ .hal
của HIDL
các tệp của trình biên dịch hidl-gen
, cách đóng gói các tệp này và
cách tích hợp các tệp này với mã C++ có sử dụng chúng.
Triển khai ứng dụng và máy chủ
Giao diện HIDL có cách triển khai ứng dụng và máy chủ:
- Ứng dụng của giao diện HIDL là mã sử dụng bằng cách gọi các phương thức trên giao diện đó.
- Máy chủ là cách triển khai giao diện HIDL nhận cuộc gọi từ khách hàng và trả về kết quả (nếu cần).
Khi chuyển đổi từ HAL libhardware
sang HAL HIDL, HAL
Quá trình triển khai sẽ trở thành máy chủ và quy trình gọi vào HAL trở thành
khách hàng. Các cách triển khai mặc định có thể phân phát cả truyền qua và liên kết
HAL và có thể thay đổi theo thời gian:
Hình 1. Tiến trình phát triển HAL (Lớp trừu tượng phần cứng) cũ.
Tạo ứng dụng HAL
Bắt đầu bằng cách đưa các thư viện HAL vào tệp makefile:
- Nhãn hiệu:
LOCAL_SHARED_LIBRARIES += android.hardware.nfc@1.0
- Sắp phát hành:
shared_libs: [ …, android.hardware.nfc@1.0 ]
Tiếp theo, hãy thêm các tệp tiêu đề HAL:
#include <android/hardware/nfc/1.0/IFoo.h> … // in code: sp<IFoo> client = IFoo::getService(); client->doThing();
Tạo máy chủ HAL
Để tạo quy trình triển khai HAL, bạn phải có các tệp .hal
đại diện cho HAL và đã tạo tệp makefile cho HAL của bạn bằng cách sử dụng
-Lmakefile
hoặc -Landroidbp
trên hidl-gen
(./hardware/interfaces/update-makefiles.sh
thực hiện việc này đối với
HAL và là tài liệu tham khảo tốt). Khi chuyển qua HAL từ
libhardware
, bạn có thể dễ dàng thực hiện nhiều việc này bằng c2hal.
Cách tạo các tệp cần thiết để triển khai HAL:
PACKAGE=android.hardware.nfc@1.0 LOC=hardware/interfaces/nfc/1.0/default/ m -j hidl-gen hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport $PACKAGE hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport $PACKAGE
Để HAL hoạt động ở chế độ thông qua, bạn phải
hàm HIDL_FETCH_IModuleName
cư trú trong
/(system|vendor|...)/lib(64)?/hw/android.hardware.package@3.0-impl(OPTIONAL_IDENTIFIER).so
trong đó OPTIONAL_IDENTIFIER là một chuỗi xác định tín hiệu truyền qua
trong quá trình triển khai. Các yêu cầu về chế độ truyền qua được tự động đáp ứng bởi
các lệnh bên trên. Các lệnh này cũng tạo ra android.hardware.nfc@1.0-impl
nhưng có thể sử dụng bất kỳ tiện ích nào. Ví dụ:
android.hardware.nfc@1.0-impl-foo
sử dụng -foo
để
sự khác biệt.
Nếu HAL là phiên bản nhỏ hoặc phần mở rộng của một phiên bản khác
HAL, HAL cơ sở nên được sử dụng để đặt tên cho tệp nhị phân này. Ví dụ:
Quá trình triển khai android.hardware.graphics.mapper@2.1
nên
vẫn ở trong tệp nhị phân được gọi là
android.hardware.graphics.mapper@2.0-impl(OPTIONAL_IDENTIFIER)
Thường thì OPTIONAL_IDENTIFIER ở đây sẽ bao gồm HAL thực tế
. Bằng cách đặt tên tệp nhị phân như thế này, các ứng dụng khách 2.0 có thể truy xuất tệp đó trực tiếp,
và phiên bản 2.1 có thể bỏ qua việc triển khai.
Tiếp theo, điền chức năng vào các stub và thiết lập một trình nền. Ví dụ: mã trình nền (hỗ trợ truyền qua):
#include <hidl/LegacySupport.h> int main(int /* argc */, char* /* argv */ []) { return defaultPassthroughServiceImplementation<INfc>("nfc"); }
defaultPassthroughServiceImplementation
cuộc gọi
dlopen()
cho thư viện -impl
được cung cấp và cung cấp dưới dạng
dịch vụ liên kết. Ví dụ về mã trình nền (dành cho dịch vụ liên kết thuần tuý):
int main(int /* argc */, char* /* argv */ []) { // This function must be called before you join to ensure the proper // number of threads are created. The threadpool never exceeds // size one because of this call. ::android::hardware::configureRpcThreadpool(1 /*threads*/, true /*willJoin*/); sp<INfc> nfc = new Nfc(); const status_t status = nfc->registerAsService(); if (status != ::android::OK) { return 1; // or handle error } // Adds this thread to the threadpool, resulting in one total // thread in the threadpool. We could also do other things, but // would have to specify 'false' to willJoin in configureRpcThreadpool. ::android::hardware::joinRpcThreadpool(); return 1; // joinRpcThreadpool should never return }
Daemon này thường sống trong $PACKAGE + "-service-suffix"
(cho
ví dụ: android.hardware.nfc@1.0-service
), nhưng có thể ở bất cứ đâu.
Chính sách dành cho một phiên bản cụ thể
lớp HAL là thuộc tính hal_<module>
(ví dụ:
hal_nfc)
. Thuộc tính này phải được áp dụng cho trình nền chạy
HAL cụ thể (nếu cùng một quy trình cung cấp nhiều HAL thì nhiều thuộc tính
có thể áp dụng cho cảnh báo đó).