Google cam kết thúc đẩy công bằng chủng tộc cho các cộng đồng Đen. Xem thế nào.
Trang này được dịch bởi Cloud Translation API.
Switch to English

Phiên bản

HIDL yêu cầu mọi giao diện được viết bằng HIDL phải được phiên bản. Sau khi giao diện HAL được xuất bản, nó bị đóng băng và mọi thay đổi khác phải được thực hiện đối với phiên bản mới của giao diện đó. Mặc dù một giao diện được công bố nhất định có thể không được sửa đổi, nó có thể được mở rộng bởi một giao diện khác.

Cấu trúc mã HIDL

Mã HIDL được tổ chức theo kiểu, giao diện và gói do người dùng định nghĩa:

  • Các loại do người dùng định nghĩa (UDT) . HIDL cung cấp quyền truy cập vào một tập hợp các kiểu dữ liệu nguyên thủy có thể được sử dụng để soạn các kiểu phức tạp hơn thông qua các cấu trúc, hiệp hội và liệt kê. UDT được truyền cho các phương thức của giao diện và có thể được xác định ở cấp độ của gói (chung cho tất cả các giao diện) hoặc cục bộ cho giao diện.
  • Giao diện . Là một khối xây dựng cơ bản của HIDL, một giao diện bao gồm các khai báo UDT và phương thức. Các giao diện cũng có thể kế thừa từ một giao diện khác.
  • Gói . Tổ chức các giao diện HIDL liên quan và các loại dữ liệu mà chúng hoạt động. Một gói được xác định bởi một tên và một phiên bản và bao gồm:
    • Tệp định nghĩa kiểu dữ liệu được gọi là types.hal .
    • Không có hoặc nhiều giao diện, mỗi giao diện trong tệp .hal của riêng họ.

Các tệp định nghĩa kiểu dữ types.hal chỉ chứa UDT (tất cả các UDT cấp gói được giữ trong một tệp). Các đại diện trong ngôn ngữ đích có sẵn cho tất cả các giao diện trong gói.

Triết lý phiên bản

Gói HIDL (chẳng hạn như android.hardware.nfc ), sau khi được xuất bản cho một phiên bản nhất định (chẳng hạn như 1.0 ), là bất biến; nó không thể thay đổi Việc sửa đổi các giao diện trong gói hoặc bất kỳ thay đổi nào đối với UDT của nó chỉ có thể diễn ra trong gói khác .

Trong HIDL, phiên bản áp dụng ở cấp gói, không phải ở cấp giao diện và tất cả các giao diện và UDT trong gói đều có chung phiên bản. Các phiên bản gói theo phiên bản ngữ nghĩa mà không có các thành phần mức độ vá và siêu dữ liệu xây dựng. Trong một gói nhất định, một gói phiên bản nhỏ ngụ ý phiên bản mới của gói tương thích ngược với gói cũ và một gói phiên bản chính ngụ ý phiên bản mới của gói không tương thích ngược với gói cũ.

Về mặt khái niệm, một gói có thể liên quan đến một gói khác theo một trong nhiều cách:

  • Không hề .
  • Khả năng mở rộng tương thích ngược cấp độ gói . Điều này xảy ra đối với uprevs phiên bản nhỏ mới (sửa đổi tăng dần tiếp theo) của gói; gói mới có cùng tên và phiên bản chính với gói cũ, nhưng phiên bản phụ cao hơn. Về mặt chức năng, gói mới là một siêu bộ của gói cũ, có nghĩa là:
    • Các giao diện cấp cao nhất của gói cha có mặt trong gói mới, mặc dù các giao diện có thể có các phương thức mới, UDT cục bộ giao diện mới (phần mở rộng cấp giao diện được mô tả bên dưới) và UDT mới trong types.hal .
    • Giao diện mới cũng có thể được thêm vào gói mới.
    • Tất cả các loại dữ liệu của gói cha đều có trong gói mới và có thể được xử lý bằng các phương thức (có thể được thực hiện lại) từ gói cũ.
    • Các kiểu dữ liệu mới cũng có thể được thêm vào để sử dụng bằng các phương pháp mới của các giao diện hiện có hoặc các giao diện mới.
  • Khả năng mở rộng tương thích ngược cấp độ giao diện . Gói mới cũng có thể mở rộng gói ban đầu bằng cách bao gồm các giao diện riêng biệt hợp lý chỉ cung cấp chức năng bổ sung chứ không phải là giao diện cốt lõi. Đối với mục đích này, những điều sau đây có thể được mong muốn:
    • Các giao diện trong gói mới cần truy vấn các kiểu dữ liệu của gói cũ.
    • Các giao diện trong gói mới có thể mở rộng giao diện của một hoặc nhiều gói cũ.
  • Mở rộng sự không tương thích ngược ban đầu . Đây là một phiên bản chính của gói và không cần có bất kỳ mối tương quan nào giữa hai gói. Trong phạm vi có, nó có thể được biểu thị bằng sự kết hợp các loại từ phiên bản cũ hơn của gói và kế thừa một tập hợp con của các giao diện gói cũ.

Cấu trúc giao diện

Đối với giao diện có cấu trúc tốt, việc thêm các loại chức năng mới không phải là một phần của thiết kế ban đầu cần phải sửa đổi giao diện HIDL. Ngược lại, nếu bạn có thể hoặc mong muốn thực hiện thay đổi ở cả hai phía của giao diện giới thiệu chức năng mới mà không thay đổi giao diện, thì giao diện không được cấu trúc.

Treble hỗ trợ các thành phần hệ thống và nhà cung cấp được biên dịch riêng trong đó nhà vendor.img trên thiết bị và system.img có thể được biên dịch riêng. Tất cả các tương tác giữa nhà vendor.imgsystem.img phải được xác định rõ ràng và kỹ lưỡng để chúng có thể tiếp tục hoạt động trong nhiều năm. Điều này bao gồm nhiều bề mặt API, nhưng một bề mặt chính là cơ chế IPC HIDL sử dụng để liên lạc giữa các quá trình trên ranh giới system.img / vendor.img .

Yêu cầu

Tất cả dữ liệu được truyền qua HIDL phải được xác định rõ ràng. Để đảm bảo triển khai và khách hàng có thể tiếp tục làm việc cùng nhau ngay cả khi được biên dịch riêng hoặc phát triển độc lập, dữ liệu phải tuân thủ các yêu cầu sau:

  • Có thể được mô tả trực tiếp trong HIDL (sử dụng enuc structs, v.v.) với tên và ý nghĩa ngữ nghĩa.
  • Có thể được mô tả bởi một tiêu chuẩn công cộng, chẳng hạn như ISO / IEC 7816.
  • Có thể được mô tả bởi một tiêu chuẩn phần cứng hoặc bố trí vật lý của phần cứng.
  • Có thể là dữ liệu mờ (như khóa công khai, id, v.v.) nếu cần thiết.

Nếu dữ liệu mờ được sử dụng, nó chỉ được đọc bởi một bên của giao diện HIDL. Ví dụ: nếu mã nhà cung vendor.img cung cấp một thành phần trên system.img một thông báo chuỗi hoặc dữ liệu vec<uint8_t> , thì dữ liệu đó không thể được phân tích cú pháp bởi chính system.img ; nó chỉ có thể được gửi lại cho nhà vendor.img để giải thích. Khi chuyển một giá trị từ nhà cung vendor.img sang mã nhà cung cấp trên system.img hoặc đến một thiết bị khác, định dạng của dữ liệu và cách diễn giải nó phải được mô tả chính xác và vẫn là một phần của giao diện .

Hướng dẫn

Bạn sẽ có thể viết một triển khai hoặc ứng dụng khách của HAL chỉ bằng các tệp .hal (tức là bạn không cần phải xem nguồn Android hoặc các tiêu chuẩn công khai). Chúng tôi khuyên bạn nên chỉ định hành vi chính xác cần thiết. Các tuyên bố như "việc triển khai có thể làm A hoặc B" khuyến khích việc triển khai trở nên đan xen với các khách hàng mà họ được phát triển cùng.

Bố cục mã HIDL

HIDL bao gồm các gói cốt lõi và nhà cung cấp.

Giao diện HIDL lõi là những giao diện được chỉ định bởi Google. Các gói họ thuộc về bắt đầu với android.hardware. và được đặt tên theo hệ thống con, có khả năng với các mức đặt tên lồng nhau. Ví dụ: gói NFC có tên android.hardware.nfc và gói máy ảnh là android.hardware.camera . Nói chung, một gói lõi có tên android.hardware. [ name1 ]. [ name2 ] Ngày. Các gói HIDL có một phiên bản ngoài tên của chúng. Ví dụ: gói android.hardware.camera có thể ở phiên bản 3.4 ; điều này rất quan trọng, vì phiên bản của gói ảnh hưởng đến vị trí của nó trong cây nguồn.

Tất cả các gói cốt lõi được đặt dưới hardware/interfaces/ trong hệ thống xây dựng. Gói phần mềm android.hardware. [ name1 ]. [ name2 ] Có phiên bản $m.$n nằm dưới hardware/interfaces/name1/name2/ /$m.$n/ ; gói android.hardware.camera phiên bản 3.4 nằm trong thư mục hardware/interfaces/camera/3.4/. Ánh xạ mã hóa cứng tồn tại giữa tiền tố gói android.hardware.hardware/interfaces/ đường dẫn hardware/interfaces/ .

Các gói không cốt lõi (nhà cung cấp) là các gói được sản xuất bởi nhà cung cấp SoC hoặc ODM. Tiền tố cho các gói không cốt lõi là vendor.$(VENDOR).hardware. trong đó $(VENDOR) đề cập đến một nhà cung cấp SoC hoặc OEM / ODM. Ánh xạ này tới các vendor/$(VENDOR)/interfaces đường dẫn vendor/$(VENDOR)/interfaces trong cây (ánh xạ này cũng được mã hóa cứng).

Tên loại do người dùng xác định đầy đủ

Trong HIDL, mọi UDT đều có một tên đủ điều kiện bao gồm tên UDT, tên gói nơi UDT được xác định và phiên bản gói. Tên đủ điều kiện chỉ được sử dụng khi các phiên bản của loại được khai báo và không phải nơi mà chính loại được xác định. Ví dụ: giả sử gói android.hardware.nfc, phiên bản 1.0 định nghĩa một cấu trúc có tên NfcData . Tại trang web của khai báo (cho dù trong types.hal hoặc trong khai báo của giao diện), khai báo chỉ đơn giản ghi:

struct NfcData {
    vec<uint8_t> data;
};

Khi khai báo một thể hiện của loại này (cho dù trong cấu trúc dữ liệu hoặc dưới dạng tham số phương thức), hãy sử dụng tên loại đủ điều kiện:

android.hardware.nfc@1.0::NfcData

Cú pháp chung là PACKAGE @ VERSION :: UDT , trong đó:

  • PACKAGE là tên được phân tách bằng dấu chấm của gói HIDL (ví dụ: android.hardware.nfc ).
  • VERSION là định dạng phiên bản Major.minor được phân tách bằng dấu chấm của gói (ví dụ: 1.0 ).
  • UDT là tên được phân tách bằng dấu chấm của UDL UDT. Vì HIDL hỗ trợ các UDT lồng nhau và giao diện HIDL có thể chứa UDT (một loại khai báo lồng nhau), nên các dấu chấm được sử dụng để truy cập vào tên.

Ví dụ: nếu khai báo lồng nhau sau được xác định trong tệp loại phổ biến trong gói android.hardware.example phiên bản 1.0 :

// types.hal
package android.hardware.example@1.0;
struct Foo {
    struct Bar {
        // …
    };
    Bar cheers;
};

Tên đủ điều kiện cho Barandroid.hardware.example@1.0::Foo.Bar . Nếu, ngoài việc nằm trong gói trên, khai báo lồng nhau nằm trong giao diện có tên IQuux :

// IQuux.hal
package android.hardware.example@1.0;
interface IQuux {
    struct Foo {
        struct Bar {
            // …
        };
        Bar cheers;
    };
    doSomething(Foo f) generates (Foo.Bar fb);
};

Tên đủ điều kiện cho Barandroid.hardware.example@1.0::IQuux.Foo.Bar .

Trong cả hai trường hợp, Bar có thể được gọi là Bar trong phạm vi khai báo của Foo . Ở cấp độ gói hoặc giao diện, bạn phải tham khảo Bar qua Foo : Foo.Bar , như trong khai báo phương thức doSomething ở trên. Ngoài ra, bạn có thể khai báo phương thức rõ ràng hơn như sau:

// IQuux.hal
doSomething(android.hardware.example@1.0::IQuux.Foo f) generates (android.hardware.example@1.0::IQuux.Foo.Bar fb);

Giá trị liệt kê đủ điều kiện

Nếu UDT là một loại enum, thì mỗi giá trị của loại enum có một tên đủ điều kiện bắt đầu bằng tên đủ điều kiện của loại enum, theo sau là dấu hai chấm, sau đó là tên của giá trị enum. Ví dụ: giả sử gói android.hardware.nfc, phiên bản 1.0 định nghĩa một loại NfcStatus :

enum NfcStatus {
    STATUS_OK,
    STATUS_FAILED
};

Khi đề cập đến STATUS_OK , tên đủ điều kiện là:

android.hardware.nfc@1.0::NfcStatus:STATUS_OK

Cú pháp chung là PACKAGE @ VERSION :: UDT : VALUE , trong đó:

  • PACKAGE @ VERSION :: UDT là tên chính xác đủ điều kiện cho loại enum.
  • VALUE là tên của giá trị.

Quy tắc tự động suy luận

Tên UDT đủ điều kiện không cần phải được chỉ định. Tên UDT có thể bỏ qua một cách an toàn như sau:

  • Gói, ví dụ @1.0::IFoo.Type
  • Cả gói và phiên bản, ví dụ IFoo.Type

HIDL cố gắng hoàn thành tên bằng quy tắc tự động can thiệp (số quy tắc thấp hơn có nghĩa là mức độ ưu tiên cao hơn).

Quy tắc 1

Nếu không có gói và phiên bản nào được cung cấp, việc tra cứu tên địa phương sẽ được thử. Thí dụ:

interface Nfc {
    typedef string NfcErrorMessage;
    send(NfcData d) generates (@1.0::NfcStatus s, NfcErrorMessage m);
};

NfcErrorMessage được tra cứu tại địa phương và tìm thấy typedef ở trên. NfcData cũng được tra cứu cục bộ, nhưng vì nó không được xác định cục bộ, quy tắc 2 và 3 được sử dụng. @1.0::NfcStatus cung cấp phiên bản, vì vậy quy tắc 1 không áp dụng.

Quy tắc 2

Nếu quy tắc 1 không thành công và một thành phần của tên đủ điều kiện bị thiếu (gói, phiên bản hoặc gói và phiên bản), thì thành phần đó được tự động điền thông tin từ gói hiện tại. Trình biên dịch HIDL sau đó tìm trong tệp hiện tại (và tất cả các lần nhập) để tìm tên đủ điều kiện tự động điền. Sử dụng ví dụ trên, giả sử khai báo ExtendedNfcData được thực hiện trong cùng một gói ( android.hardware.nfc ) ở cùng phiên bản ( 1.0 ) như NfcData , như sau:

struct ExtendedNfcData {
    NfcData base;
    // … additional members
};

Trình biên dịch HIDL điền tên gói và tên phiên bản từ gói hiện tại để tạo ra tên UDT đủ điều kiện android.hardware.nfc@1.0::NfcData . Vì tên tồn tại trong gói hiện tại (giả sử nó được nhập đúng), nên nó được sử dụng để khai báo.

Tên trong gói hiện tại chỉ được nhập nếu một trong những điều sau là đúng:

  • Nó được nhập khẩu rõ ràng với một tuyên bố import .
  • Nó được định nghĩa trong types.hal trong gói hiện tại

Quá trình tương tự được thực hiện nếu NfcData chỉ đủ điều kiện chỉ bằng số phiên bản:

struct ExtendedNfcData {
    // autofill the current package name (android.hardware.nfc)
    @1.0::NfcData base;
    // … additional members
};

Quy tắc 3

Nếu quy tắc 2 không tạo được kết quả khớp (UDT không được xác định trong gói hiện tại), trình biên dịch HIDL sẽ quét tìm một kết quả khớp trong tất cả các gói đã nhập. Sử dụng ví dụ trên, giả sử ExtendedNfcData được khai báo trong phiên bản 1.1 của gói android.hardware.nfc , 1.1 nhập 1.0 nếu cần (xem Tiện ích mở rộng cấp gói ) và định nghĩa chỉ xác định tên UDT:

struct ExtendedNfcData {
    NfcData base;
    // … additional members
};

Trình biên dịch tìm kiếm bất kỳ UDT nào có tên NfcData và tìm thấy một trong android.hardware.nfc tại phiên bản 1.0 , dẫn đến một UDT đủ điều kiện của android.hardware.nfc@1.0::NfcData . Nếu tìm thấy nhiều hơn một trận đấu cho một UDT đủ điều kiện nhất định, trình biên dịch HIDL sẽ đưa ra một lỗi.

Thí dụ

Sử dụng quy tắc 2, loại đã nhập được xác định trong gói hiện tại được ưu tiên hơn loại đã nhập từ gói khác:

// hardware/interfaces/foo/1.0/types.hal
package android.hardware.foo@1.0;
struct S {};

// hardware/interfaces/foo/1.0/IFooCallback.hal
package android.hardware.foo@1.0;
interface IFooCallback {};

// hardware/interfaces/bar/1.0/types.hal
package android.hardware.bar@1.0;
typedef string S;

// hardware/interfaces/bar/1.0/IFooCallback.hal
package android.hardware.bar@1.0;
interface IFooCallback {};

// hardware/interfaces/bar/1.0/IBar.hal
package android.hardware.bar@1.0;
import android.hardware.foo@1.0;
interface IBar {
    baz1(S s); // android.hardware.bar@1.0::S
    baz2(IFooCallback s); // android.hardware.foo@1.0::IFooCallback
};
  • S được nội suy là android.hardware.bar@1.0::S và được tìm thấy trong bar/1.0/types.hal (vì types.hal được nhập tự động).
  • IFooCallback được nội suy dưới dạng android.hardware.bar@1.0::IFooCallback sử dụng quy tắc 2, nhưng không thể tìm thấy vì bar/1.0/IFooCallback.hal không được nhập tự động (như types.hal là). Do đó, quy tắc 3 giải quyết nó thành android.hardware.foo@1.0::IFooCallback , được nhập thông qua import android.hardware.foo@1.0; ).

các loại

Mỗi gói HIDL chứa một tệp types.hal chứa UDT được chia sẻ giữa tất cả các giao diện tham gia gói đó. Các loại HIDL luôn được công khai; bất kể UDT được khai báo theo types.hal hay trong khai báo giao diện, các loại này đều có thể truy cập được ngoài phạm vi nơi chúng được xác định. types.hal không có nghĩa là để mô tả API công khai của gói, mà là để lưu trữ UDT được sử dụng bởi tất cả các giao diện trong gói. Do tính chất của HIDL, tất cả các UDT là một phần của giao diện.

types.hal bao gồm UDT và báo cáo import . Bởi vì types.hal được cung cấp cho mọi giao diện của gói (nó là một nhập khẩu ngầm), các báo cáo import này là cấp độ gói theo định nghĩa. UDT trong types.hal cũng có thể kết hợp UDT và giao diện do đó được nhập.

Ví dụ: đối với IFoo.hal :

package android.hardware.foo@1.0;
// whole package import
import android.hardware.bar@1.0;
// types only import
import android.hardware.baz@1.0::types;
// partial imports
import android.hardware.qux@1.0::IQux.Quux;
// partial imports
import android.hardware.quuz@1.0::Quuz;

Sau đây là nhập khẩu:

  • android.hidl.base@1.0::IBase (ngầm)
  • android.hardware.foo@1.0::types (ngầm)
  • Mọi thứ trong android.hardware.bar@1.0 (bao gồm tất cả các giao diện và loại của types.hal )
  • types.hal từ android.hardware.baz@1.0::types (giao diện trong android.hardware.baz@1.0 không được nhập)
  • IQux.haltypes.hal từ android.hardware.qux@1.0
  • Quuz từ android.hardware.quuz@1.0 (giả sử Quuz được định nghĩa trong types.hal , toàn bộ tệp types.hal được phân tích cú pháp, nhưng các loại khác ngoài Quuz không được nhập).

Phiên bản cấp giao diện

Mỗi giao diện trong một gói nằm trong tệp riêng của nó. Gói giao diện thuộc về được khai báo ở đầu giao diện bằng cách sử dụng câu lệnh package . Theo khai báo gói, nhập khẩu cấp độ giao diện bằng 0 hoặc nhiều hơn (một phần hoặc toàn bộ gói) có thể được liệt kê. Ví dụ:

package android.hardware.nfc@1.0;

Trong HIDL, các giao diện có thể kế thừa từ các giao diện khác bằng cách sử dụng từ khóa extends . Để một giao diện mở rộng giao diện khác, nó phải có quyền truy cập vào nó thông qua một câu lệnh import . Tên của giao diện được mở rộng (giao diện cơ sở) tuân theo các quy tắc về trình độ tên loại được giải thích ở trên. Một giao diện chỉ có thể kế thừa từ một giao diện; HIDL không hỗ trợ nhiều kế thừa.

Các ví dụ phiên bản uprev dưới đây sử dụng gói sau:

// types.hal
package android.hardware.example@1.0
struct Foo {
    struct Bar {
        vec<uint32_t> val;
    };
};

// IQuux.hal
package android.hardware.example@1.0
interface IQuux {
    fromFooToBar(Foo f) generates (Foo.Bar b);
}

Quy tắc Uprev

Để xác định gói package@major.minor , A hoặc tất cả B phải đúng:

Quy tắc A "Là phiên bản nhỏ bắt đầu": Không được xác định tất cả các phiên bản nhỏ trước đó, package@major.0 , package@major.1 , lỗi, package@major.(minor-1) không được xác định.
HOẶC LÀ
Quy tắc B

Tất cả những điều sau đây là đúng:

  1. "Phiên bản phụ trước đó là hợp lệ": package@major.(minor-1) phải được xác định và tuân theo quy tắc A (không có package@major.(minor-2) package@major.0 đến package@major.(minor-2) được xác định) hoặc quy tắc B (nếu đó là một uprev từ @major.(minor-2) );



  2. "Kế thừa ít nhất một giao diện có cùng tên": package@major.minor::IFoo giao package@major.minor::IFoo mở rộng package@major.(minor-1)::IFoo (nếu gói trước có giao diện);



  3. "Không có giao diện được kế thừa với một tên khác": Không được tồn tại package@major.minor::IBar mở rộng package@major.(minor-1)::IBaz , trong đó IBarIBaz là hai tên khác nhau. Nếu có một giao diện có cùng tên, package@major.minor::IBar phải mở rộng package@major.(minor-k)::IBar sao cho không có IBar tồn tại với k nhỏ hơn.

Vì quy tắc A:

  • Gói có thể bắt đầu với bất kỳ số phiên bản nhỏ nào (ví dụ: android.hardware.biometrics.fingerprint bắt đầu từ @2.1 .)
  • Yêu cầu " android.hardware.foo@1.0 không được xác định" có nghĩa là hardware/interfaces/foo/1.0 thư mục hardware/interfaces/foo/1.0 thậm chí không tồn tại.

Tuy nhiên, quy tắc A không ảnh hưởng đến một gói có cùng tên gói mà là một phiên bản chính khác (ví dụ: android.hardware.camera.device có cả @1.0@3.2 được xác định; @3.2 không cần tương tác với @1.0 .) Do đó, @3.2::IExtFoo có thể mở rộng @1.0::IFoo .

Với tên gói là khác nhau, package@major.minor::IBar có thể mở rộng từ một giao diện có tên khác (ví dụ: android.hardware.bar@1.0::IBar có thể mở rộng android.hardware.baz@2.2::IBaz ). Nếu một giao diện không khai báo rõ ràng một loại siêu với từ khóa extend , nó sẽ mở rộng android.hidl.base@1.0::IBase (ngoại trừ chính IBase ).

B.2 và B.3 phải được theo dõi cùng một lúc. Ví dụ: ngay cả khi android.hardware.foo@1.1::IFoo mở rộng android.hardware.foo@1.0::IFoo để vượt qua quy tắc B.2, nếu android.hardware.foo@1.1::IExtBar mở rộng android.hardware.foo@1.0::IBar , đây vẫn chưa phải là một uprev hợp lệ.

Giao diện nâng cấp

Để uprev android.hardware.example@1.0 (được xác định ở trên) thành @1.1 :

// types.hal
package android.hardware.example@1.1;
import android.hardware.example@1.0;

// IQuux.hal
package android.hardware.example@1.1
interface IQuux extends @1.0::IQuux {
    fromBarToFoo(Foo.Bar b) generates (Foo f);
}

Đây là bản import cấp gói phiên bản 1.0 của android.hardware.example trong types.hal . Mặc dù không có UDT mới nào được thêm vào trong phiên bản 1.1 của gói, nhưng các tham chiếu đến UDT trong phiên bản 1.0 vẫn cần thiết, do đó nhập cấp độ gói trong types.hal . (Hiệu ứng tương tự có thể đạt được với nhập cấp độ giao diện trong IQuux.hal .)

Trong phần extends @1.0::IQuux trong phần khai báo của IQuux , chúng tôi đã chỉ định phiên bản IQuux đang được kế thừa (yêu cầu định hướng là do IQuux được sử dụng để khai báo giao diện và kế thừa từ giao diện). Vì các khai báo chỉ là các tên kế thừa tất cả các thuộc tính gói và phiên bản tại trang web của khai báo, nên sự định hướng phải nằm trong tên của giao diện cơ sở; chúng tôi có thể đã sử dụng UDT đủ điều kiện là tốt, nhưng điều đó sẽ là dư thừa.

Giao diện mới IQuux không khai báo lại phương thức fromFooToBar() mà nó kế thừa từ @1.0::IQuux ; nó chỉ đơn giản là liệt kê phương thức mới mà nó thêm fromBarToFoo() . Trong HIDL, các phương thức được kế thừa có thể không được khai báo lại trong các giao diện con, vì vậy giao diện IQuux không thể khai báo rõ ràng phương thức fromFooToBar() .

Công ước Uprev

Đôi khi tên giao diện phải đổi tên giao diện mở rộng. Chúng tôi khuyên rằng các phần mở rộng enum, cấu trúc và công đoàn có cùng tên với những gì chúng mở rộng trừ khi chúng đủ khác nhau để đảm bảo một tên mới. Ví dụ:

// in parent hal file
enum Brightness : uint32_t { NONE, WHITE };

// in child hal file extending the existing set with additional similar values
enum Brightness : @1.0::Brightness { AUTOMATIC };

// extending the existing set with values that require a new, more descriptive name:
enum Color : @1.0::Brightness { HW_GREEN, RAINBOW };

Nếu một phương thức có thể có một tên ngữ nghĩa mới (ví dụ fooWithLocation ) thì đó là ưu tiên. Mặt khác, nó nên được đặt tên tương tự như những gì nó đang mở rộng. Ví dụ: phương thức foo_1_1 trong @1.1::IFoo có thể thay thế chức năng của phương thức foo trong @1.0::IFoo nếu không có tên thay thế tốt hơn.

Phiên bản cấp gói

Phiên bản HIDL xảy ra ở cấp độ gói; sau khi một gói được xuất bản, nó là bất biến (bộ giao diện và UDT của nó không thể thay đổi). Các gói có thể liên quan với nhau theo nhiều cách, tất cả đều có thể biểu thị thông qua sự kết hợp giữa kế thừa cấp giao diện và xây dựng UDT theo thành phần.

Tuy nhiên, một loại mối quan hệ được xác định nghiêm ngặt và phải được thi hành: Kế thừa tương thích ngược cấp độ gói . Trong trường hợp này, gói cha là gói được kế thừa và gói con là gói mở rộng cha mẹ. Các quy tắc thừa kế tương thích ngược cấp độ gói như sau:

  1. Tất cả các giao diện cấp cao nhất của gói cha được kế thừa từ các giao diện trong gói con.
  2. Các giao diện mới cũng có thể được thêm gói mới (không hạn chế về mối quan hệ với các giao diện khác trong các gói khác).
  3. Các kiểu dữ liệu mới cũng có thể được thêm vào để sử dụng bằng các phương pháp mới của các giao diện hiện có hoặc các giao diện mới.

Các quy tắc này có thể được thực hiện bằng cách sử dụng kế thừa UDL và thành phần UDT, nhưng yêu cầu kiến ​​thức cấp độ meta để biết các mối quan hệ này tạo thành một phần mở rộng gói tương thích ngược. Kiến thức này được suy luận như sau:

Nếu một gói đáp ứng yêu cầu này, hidl-gen thực thi các quy tắc tương thích ngược.