Bạn phải sử dụng HIDL để mô tả tất cả các cờ xây dựng được sử dụng để biên dịch khung có điều kiện. Các cờ xây dựng có liên quan phải được nhóm lại và đưa vào một tệp .hal
. Sử dụng HIDL để chỉ định các mục cấu hình bao gồm các lợi ích sau:
- Đã được phiên bản (để thêm các mục cấu hình mới, nhà cung cấp/OEM phải mở rộng HAL một cách rõ ràng)
- Được ghi chép đầy đủ
- Kiểm soát truy cập bằng SELinux
- Kiểm tra tính chính xác cho các mục cấu hình thông qua Bộ kiểm tra nhà cung cấp (kiểm tra phạm vi, kiểm tra sự phụ thuộc lẫn nhau giữa các mục, v.v.)
- API được tạo tự động trong cả C++ và Java
Xác định các cờ xây dựng được sử dụng bởi khung
Bắt đầu bằng cách xác định các cấu hình bản dựng được sử dụng để biên dịch khung có điều kiện, sau đó loại bỏ các cấu hình lỗi thời để thu gọn tập hợp. Ví dụ: bộ cờ xây dựng sau đây được xác định cho surfaceflinger
:
-
TARGET_USES_HWC2
-
TARGET_BOARD_PLATFORM
-
TARGET_DISABLE_TRIPLE_BUFFERING
-
TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
-
NUM_FRAMEBUFFER_SURFACE_BUFFERS
-
TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK
-
VSYNC_EVENT_PHASE_OFFSET_NS
-
SF_VSYNC_EVENT_PHASE_OFFSET_NS
-
PRESENT_TIME_OFFSET_FROM_VSYNC_NS
-
MAX_VIRTUAL_DISPLAY_DIMENSION
Tạo giao diện HAL
Cấu hình bản dựng cho hệ thống con được truy cập thông qua giao diện HAL, trong khi các giao diện cung cấp giá trị cấu hình được nhóm trong gói HAL android.hardware.configstore
(hiện ở phiên bản 1.0). Ví dụ: để tạo tệp giao diện HAL cho surfaceflinger
, trong hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
:
package android.hardware.configstore@1.0; interface ISurfaceFlingerConfigs { // TO-BE-FILLED-BELOW };
Sau khi tạo tệp .hal
, hãy chạy hardware/interfaces/update-makefiles.sh
để thêm tệp .hal
mới vào tệp Android.bp
và Android.mk
.
Thêm chức năng cho cờ xây dựng
Đối với mỗi cờ xây dựng, hãy thêm một chức năng mới vào giao diện. Ví dụ: trong hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
:
interface ISurfaceFlingerConfigs { disableTripleBuffering() generates(OptionalBool ret); forceHwcForVirtualDisplays() generates(OptionalBool ret); enum NumBuffers: uint8_t { USE_DEFAULT = 0, TWO = 2, THREE = 3, }; numFramebufferSurfaceBuffers() generates(NumBuffers ret); runWithoutSyncFramework() generates(OptionalBool ret); vsyncEventPhaseOffsetNs generates (OptionalUInt64 ret); presentTimeOffsetFromSyncNs generates (OptionalUInt64 ret); maxVirtualDisplayDimension() generates(OptionalInt32 ret); };
Khi thêm một chức năng:
- Hãy ngắn gọn với tên. Tránh chuyển đổi tên biến makefile thành tên hàm và hãy nhớ rằng tiền tố
TARGET_
vàBOARD_
không còn cần thiết nữa. - Thêm ý kiến. Giúp nhà phát triển hiểu mục đích của mục cấu hình, cách nó thay đổi hành vi của khung, giá trị hợp lệ và thông tin liên quan khác.
Các kiểu trả về của hàm có thể là Optional[Bool|String|Int32|UInt32|Int64|UInt64]
. Các loại được định nghĩa trong types.hal
trong cùng một thư mục và bao bọc các giá trị nguyên thủy bằng một trường cho biết liệu giá trị đó có được chỉ định bởi HAL hay không; nếu không, giá trị mặc định sẽ được sử dụng.
struct OptionalString { bool specified; string value; };
Khi thích hợp, hãy xác định enum thể hiện tốt nhất loại mục cấu hình và sử dụng enum đó làm kiểu trả về. Trong ví dụ trên, enum NumBuffers
được xác định để giới hạn số lượng giá trị hợp lệ. Khi xác định các loại dữ liệu tùy chỉnh như vậy, hãy thêm một trường hoặc giá trị enum (ví dụ: USE_DEFAULT
) để biểu thị xem giá trị đó có/không được HAL chỉ định hay không.
Không bắt buộc một cờ xây dựng phải trở thành một hàm duy nhất trong HIDL. Ngoài ra, chủ sở hữu mô-đun có thể tổng hợp các cờ xây dựng có liên quan chặt chẽ thành một cấu trúc và có hàm trả về cấu trúc đó (làm như vậy có thể giảm số lượng lệnh gọi hàm).
Ví dụ: một tùy chọn để tổng hợp hai cờ xây dựng thành một cấu trúc duy nhất trong hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
là:
interface ISurfaceFlingerConfigs { // other functions here struct SyncConfigs { OptionalInt64 vsyncEventPhaseoffsetNs; OptionalInt64 presentTimeoffsetFromSyncNs; }; getSyncConfigs() generates (SyncConfigs ret); // other functions here };
Các lựa chọn thay thế cho một chức năng HAL
Để thay thế cho việc sử dụng một hàm HAL duy nhất cho tất cả các cờ xây dựng, giao diện HAL cũng cung cấp các hàm đơn giản như getBoolean(string key)
và getInteger(string key)
. Các cặp key=value
thực tế được lưu trữ trong các tệp riêng biệt và dịch vụ HAL cung cấp các giá trị bằng cách đọc/phân tích cú pháp các tệp đó.
Mặc dù cách tiếp cận này dễ xác định nhưng nó không bao gồm các lợi ích do HIDL cung cấp (bắt buộc lập phiên bản, dễ dàng lập tài liệu, kiểm soát truy cập) và do đó không được khuyến khích.
Giao diện đơn và nhiều
Thiết kế giao diện HAL cho các mục cấu hình đưa ra hai lựa chọn:
- Một giao diện duy nhất bao gồm tất cả các mục cấu hình
- Nhiều giao diện, mỗi giao diện bao gồm một tập hợp các mục cấu hình liên quan
Một giao diện dễ dàng hơn nhưng có thể trở nên khó bảo trì khi có nhiều mục cấu hình được thêm vào một tệp. Ngoài ra, kiểm soát truy cập không được chi tiết, do đó, một quy trình được cấp quyền truy cập vào giao diện có thể đọc tất cả các mục cấu hình (không thể cấp quyền truy cập vào một phần các mục cấu hình). Ngoài ra, nếu quyền truy cập không được cấp thì không thể đọc được các mục cấu hình.
Vì những vấn đề này, Android sử dụng nhiều giao diện với một giao diện HAL duy nhất cho một nhóm mục cấu hình liên quan. Ví dụ: ISurfaceflingerConfigs
cho các mục cấu hình liên quan đến surfaceflinger
và IBluetoothConfigs
cho các mục cấu hình liên quan đến Bluetooth.