Google cam kết thúc đẩy công bằng chủng tộc cho Cộng đồng người da đen. Xem cách thực hiện.

HIDL

Ngôn ngữ định nghĩa giao diện HAL hoặc HIDL (phát âm là "hide-l") là một ngôn ngữ mô tả giao diện (IDL) để chỉ định giao diện giữa HAL và người dùng của nó. Nó cho phép chỉ định các kiểu và các cuộc gọi phương thức, được thu thập vào các giao diện và gói. Nói rộng hơn, HIDL là một hệ thống giao tiếp giữa các cơ sở mã có thể được biên dịch độc lập. Kể từ Android 10, HIDL không được dùng nữa và Android sẽ chuyển sang sử dụng AIDL ở mọi nơi.

HIDL được thiết kế để sử dụng cho giao tiếp giữa các quá trình (IPC). Truyền thông giữa các quá trình được gọi là Binderized . Đối với các thư viện phải gắn với một quá trình, một chế độ passthrough cũng có sẵn (không được hỗ trợ trong Java).

HIDL chỉ định cấu trúc dữ liệu và chữ ký phương thức, được tổ chức trong các giao diện (tương tự như một lớp) được thu thập thành các gói. Cú pháp của HIDL sẽ trông quen thuộc với các lập trình viên C ++ và Java, mặc dù với một bộ từ khóa khác. HIDL cũng sử dụng các chú thích kiểu Java.

Thiết kế HIDL

Mục tiêu của HIDL là khung có thể được thay thế mà không cần phải xây dựng lại HAL. Hals sẽ được xây dựng bởi các nhà cung cấp hoặc các nhà sản xuất SOC và đặt trong một /vendor phân vùng trên thiết bị, tạo điều kiện khuôn khổ, trong phân vùng riêng của mình, để được thay thế bằng một OTA mà không cần biên dịch lại Hals.

Thiết kế HIDL cân bằng các mối quan tâm sau:

  • Khả năng cộng tác. Tạo các giao diện có thể tương tác đáng tin cậy giữa các quy trình có thể được biên dịch với nhiều kiến ​​trúc, dãy công cụ và cấu hình xây dựng. Giao diện HIDL được tạo phiên bản và không thể thay đổi sau khi chúng được xuất bản.
  • Hiệu quả. HIDL cố gắng giảm thiểu số lượng các thao tác sao chép. Dữ liệu do HIDL định nghĩa được chuyển đến mã C ++ trong cấu trúc dữ liệu bố cục tiêu chuẩn C ++ có thể được sử dụng mà không cần giải nén. HIDL cũng cung cấp giao diện bộ nhớ chia sẻ và vì RPC vốn dĩ hơi chậm, HIDL hỗ trợ hai cách để truyền dữ liệu mà không cần sử dụng cuộc gọi RPC: bộ nhớ chia sẻ và Hàng đợi tin nhắn nhanh (FMQ).
  • Trực quan. HIDL tránh gai góc vấn đề sở hữu bộ nhớ bằng cách chỉ sử dụng in các thông số cho RPC (xem giao diện Android Definition Language (AIDL) ); các giá trị không thể được trả về một cách hiệu quả từ các phương thức được trả về thông qua các hàm gọi lại. Việc chuyển dữ liệu vào HIDL để truyền hay nhận dữ liệu từ HIDL đều không thay đổi quyền sở hữu dữ liệu — quyền sở hữu luôn duy trì với hàm gọi. Dữ liệu chỉ cần tồn tại trong khoảng thời gian của hàm được gọi và có thể bị hủy ngay sau khi hàm được gọi trả về.

Sử dụng chế độ chuyển qua

Để cập nhật các thiết bị chạy phiên bản Android cũ hơn lên Android O, bạn có thể bọc cả HAL thông thường (và kế thừa) trong một giao diện HIDL mới phục vụ HAL ở chế độ liên kết và cùng một quy trình (chuyển qua). Gói này là trong suốt đối với cả HAL và Android framework.

Chế độ chuyển qua chỉ có sẵn cho ứng dụng C ++ và triển khai. Các thiết bị chạy phiên bản Android cũ hơn không có HAL được viết bằng Java, vì vậy HAL của Java vốn đã được ràng buộc.

Khi một .hal tập tin được biên dịch, hidl-gen sản sinh thêm passthrough file header BsFoo.h ngoài các tiêu đề được sử dụng để giao tiếp chất kết dính; này định nghĩa tiêu đề chức năng để được dlopen ed. Khi các HAL chuyển qua chạy trong cùng một quá trình mà chúng được gọi, trong hầu hết các trường hợp, các phương thức truyền qua được gọi bằng lệnh gọi hàm trực tiếp (cùng một luồng). oneway phương pháp chạy trong chủ đề riêng của họ khi họ không có ý định chờ cho HAL để xử lý chúng (phương tiện này bất kỳ HAL mà sử dụng oneway phương pháp trong chế độ passthrough phải được thread-safe).

Với một IFoo.hal , BsFoo.h kết thúc tốt đẹp các phương pháp HIDL tạo để cung cấp các tính năng bổ sung (như làm oneway giao dịch chạy trong thread khác). Tập tin này cũng tương tự như BpFoo.h , tuy nhiên thay vì đi qua các cuộc gọi IPC sử dụng chất kết dính, các chức năng mong muốn được gọi trực tiếp. Triển khai trong tương lai của Hals có thể cung cấp nhiều sự bổ sung, chẳng hạn như FooFast HAL và FooAccurate HAL. Trong những trường hợp như vậy, một tập tin cho mỗi thực hiện bổ sung sẽ được tạo ra (ví dụ, PTFooFast.cppPTFooAccurate.cpp ).

Binderizing chuyển qua HAL

Bạn có thể ràng buộc các triển khai HAL hỗ trợ chế độ chuyển qua. Cho một HAL giao diện abcd@MN::IFoo , hai gói được tạo ra:

  • abcd@MN::IFoo-impl . Chứa thi hành HAL và phơi bày hoạt IFoo* HIDL_FETCH_IFoo(const char* name) . Trên các thiết bị di sản, gói này là dlopen ed và thực hiện được khởi tạo sử dụng HIDL_FETCH_IFoo . Bạn có thể tạo ra các mã cơ sở sử dụng hidl-gen-Lc++-impl-Landroidbp-impl .
  • abcd@MN::IFoo-service . Mở HAL chuyển qua và tự đăng ký dưới dạng dịch vụ được ràng buộc hóa, cho phép sử dụng cùng một HAL triển khai như cả chuyển qua và liên kết.

Căn cứ vào loại IFoo , bạn có thể gọi sp<IFoo> IFoo::getService(string name, bool getStub) để có được quyền truy cập vào một thể hiện của IFoo . Nếu getStub là đúng, getService nỗ lực để mở HAL chỉ trong chế độ passthrough. Nếu getStub là sai, getService nỗ lực để tìm một dịch vụ binderized; nếu không thành công, nó sẽ cố gắng tìm dịch vụ chuyển qua. Các getStub tham số không bao giờ nên được sử dụng trừ defaultPassthroughServiceImplementation . (Các thiết bị khởi chạy với Android O là các thiết bị được ràng buộc hoàn toàn, do đó, việc mở một dịch vụ ở chế độ chuyển qua không được phép.)

Ngữ pháp HIDL

Theo thiết kế, ngôn ngữ HIDL tương tự như C (nhưng không sử dụng bộ tiền xử lý C). Tất cả các dấu chấm câu không được mô tả dưới đây (ngoài việc sử dụng rõ ràng =| ) là một phần của ngữ pháp.

Lưu ý: Để biết chi tiết về mã phong cách HIDL, xem Mã Style Guide .

  • /** */ cho thấy một bình luận tài liệu. Chúng chỉ có thể được áp dụng cho các khai báo kiểu, phương thức, trường và giá trị enum.
  • /* */ Chỉ ra một lời nhận xét có nhiều dòng.
  • // chỉ ra một lời nhận xét đến cuối dòng. Ngoài // , dòng mới cũng giống như bất kỳ khoảng trắng khác.
  • Trong ví dụ dưới đây ngữ pháp, văn bản từ // đến hết dòng không phải là một phần của văn phạm mà thay vào đó là một lời nhận xét về ngữ pháp.
  • [empty] phương tiện mà thuật ngữ có thể rỗng.
  • ? theo sau một nghĩa đen hoặc thuật ngữ có nghĩa là nó là tùy chọn.
  • ... chỉ ra chuỗi chứa số không hay nhiều mục có tách chấm câu như đã nêu. Không có đối số khác nhau trong HIDL.
  • Dấu phẩy phân tách các phần tử của dãy.
  • Dấu chấm phẩy kết thúc mỗi phần tử, kể cả phần tử cuối cùng.
  • UPPERCASE là một danh nghĩa.
  • italics là một gia đình thẻ như integer hoặc identifier (quy tắc tiêu chuẩn C phân tích).
  • constexpr là một biểu thức hằng C phong cách (chẳng hạn như 1 + 11L << 3 ).
  • import_name là một gói hoặc giao diện tên, trình độ như mô tả trong HIDL Versioning .
  • Chữ thường words là thẻ chữ.

Thí dụ:

ROOT =
    PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... }  // not for types.hal
  | PACKAGE IMPORTS ITEM ITEM...  // only for types.hal; no method definitions

ITEM =
    ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?;
  |  safe_union identifier { UFIELD; UFIELD; ...};
  |  struct identifier { SFIELD; SFIELD; ...};  // Note - no forward declarations
  |  union identifier { UFIELD; UFIELD; ...};
  |  enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... }; // TYPE = enum or scalar
  |  typedef TYPE identifier;

VERSION = integer.integer;

PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION;

PREAMBLE = interface identifier EXTENDS

EXTENDS = <empty> | extends import_name  // must be interface, not package

GENERATES = generates (FIELD, FIELD ...)

// allows the Binder interface to be used as a type
// (similar to typedef'ing the final identifier)
IMPORTS =
   [empty]
  |  IMPORTS import import_name;

TYPE =
  uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t |
 float | double | bool | string
|  identifier  // must be defined as a typedef, struct, union, enum or import
               // including those defined later in the file
|  memory
|  pointer
|  vec<TYPE>
|  bitfield<TYPE>  // TYPE is user-defined enum
|  fmq_sync<TYPE>
|  fmq_unsync<TYPE>
|  TYPE[SIZE]

FIELD =
   TYPE identifier

UFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...};
  |  struct identifier { FIELD; FIELD; ...};
  |  union identifier { FIELD; FIELD; ...};
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SIZE =  // Must be greater than zero
     constexpr

ANNOTATIONS =
     [empty]
  |  ANNOTATIONS ANNOTATION

ANNOTATION =
  |  @identifier
  |  @identifier(VALUE)
  |  @identifier(ANNO_ENTRY, ANNO_ENTRY  ...)

ANNO_ENTRY =
     identifier=VALUE

VALUE =
     "any text including \" and other escapes"
  |  constexpr
  |  {VALUE, VALUE ...}  // only in annotations

ENUM_ENTRY =
     identifier
  |  identifier = constexpr

Thuật ngữ

Phần này sử dụng các thuật ngữ liên quan đến HIDL sau:

ràng buộc Cho biết HIDL đang được sử dụng cho các cuộc gọi thủ tục từ xa giữa các quy trình, được thực hiện trên cơ chế giống như Binder. Xem thêm passthrough.
gọi lại, không đồng bộ Giao diện do người dùng HAL phục vụ, được chuyển tới HAL (thông qua phương thức HIDL) và được HAL gọi để trả về dữ liệu bất kỳ lúc nào.
gọi lại, đồng bộ Trả về dữ liệu từ triển khai phương thức HIDL của máy chủ cho máy khách. Không được sử dụng cho các phương thức trả về void hoặc một giá trị nguyên thủy duy nhất.
khách hàng Quy trình gọi các phương thức của một giao diện cụ thể. HAL hoặc quy trình khuôn khổ có thể là một ứng dụng khách của một giao diện và một máy chủ của một giao diện khác. Xem thêm passthrough.
kéo dài Cho biết một giao diện bổ sung các phương thức và / hoặc kiểu vào một giao diện khác. Một giao diện chỉ có thể mở rộng một giao diện khác. Có thể được sử dụng để tăng phiên bản nhỏ trong cùng một tên gói hoặc cho một gói mới (ví dụ: phần mở rộng của nhà cung cấp) để xây dựng trên một gói cũ hơn.
tạo ra Chỉ ra một phương thức giao diện trả về các giá trị cho máy khách. Để trả về một giá trị không phải nguyên thủy hoặc nhiều giá trị, một hàm gọi lại đồng bộ sẽ được tạo.
giao diện Bộ sưu tập các phương pháp và loại. Được dịch thành một lớp trong C ++ hoặc Java. Tất cả các phương thức trong một giao diện được gọi theo cùng một hướng: một tiến trình máy khách gọi các phương thức được thực hiện bởi một tiến trình máy chủ.
một chiều Khi được áp dụng cho một phương thức HIDL, cho biết phương thức không trả về giá trị nào và không chặn.
Bưu kiện Tập hợp các giao diện và kiểu dữ liệu dùng chung một phiên bản.
chuyển qua Phương thức HIDL trong đó máy chủ là một thư viện chia sẻ, dlopen ed của khách hàng. Trong chế độ chuyển qua, máy khách và máy chủ là cùng một quy trình nhưng các cơ sở mã riêng biệt. Chỉ được sử dụng để đưa các cơ sở mã kế thừa vào mô hình HIDL. Xem thêm Binderized.
người phục vụ Quy trình thực hiện các phương thức của một giao diện. Xem thêm passthrough.
vận chuyển Cơ sở hạ tầng HIDL di chuyển dữ liệu giữa máy chủ và máy khách.
phiên bản Phiên bản của một gói. Bao gồm hai số nguyên, chính và phụ. Các bước tăng phiên bản nhỏ có thể thêm (nhưng không thay đổi) các loại và phương pháp.