Chú thích trong AIDL

AIDL hỗ trợ các chú thích cung cấp cho trình biên dịch AIDL thông tin bổ sung về phần tử được chú thích, điều này cũng ảnh hưởng đến mã sơ khai được tạo.

Cú pháp tương tự như Java:

@AnnotationName(argument1=value, argument2=value) AidlEntity

Ở đây, AnnotationName là tên của chú thích và AidlEntity là một thực thể AIDL như interface Foo , void method() hoặc int arg . Một chú thích được gắn vào thực thể theo sau nó.

Một số chú thích có thể có các đối số được đặt bên trong dấu ngoặc đơn, như minh họa ở trên. Các chú thích không có đối số thì không cần dấu ngoặc đơn. Ví dụ:

@AnnotationName AidlEntity

Các chú thích này không giống với các chú thích Java, mặc dù chúng trông rất giống nhau. Người dùng không thể xác định chú thích AIDL tùy chỉnh; tất cả các chú thích đều được xác định trước. Một số chú thích chỉ ảnh hưởng đến một phần phụ trợ nhất định và không hoạt động trong các phần phụ trợ khác. Họ có những hạn chế khác nhau nơi họ có thể được gắn vào.

Dưới đây là danh sách các chú thích AIDL được xác định trước:

Chú thích Đã thêm vào phiên bản Android
nullable 7
utf8InCpp 7
VintfStability 11
UnsupportedAppUsage 10
Hide 11
Backing 11
NdkOnlyStableParcelable 14
JavaOnlyStableParcelable 11
JavaDerive 12
JavaPassthrough 12
FixedSize 12
Descriptor 12

có thể vô hiệu

nullable tuyên bố rằng giá trị của thực thể được chú thích có thể không được cung cấp.

Chú thích này chỉ có thể được đính kèm với các kiểu trả về của phương thức, các tham số của phương thức và các trường có thể phân chia.

interface IFoo {
    // method return types
    @nullable Data method();

    // method parameters
    void method2(in @nullable Data d);
}

parcelable Data {
    // parcelable fields
    @nullable Data d;
}

Chú thích không thể được gắn vào các kiểu nguyên thủy. Sau đây là một lỗi.

void method(in @nullable int a); // int is a primitive type

Chú thích này không hoạt động đối với chương trình phụ trợ Java. Điều này là do trong Java, tất cả các kiểu không nguyên thủy đều được truyền bằng tham chiếu, có thể là null .

Trong phần phụ trợ CPP, @nullable T ánh xạ tới std::unique_ptr<T> trong Android 11 trở xuống và tới std::optional<T> trong Android 12 trở xuống.

Trong phần phụ trợ NDK, @nullable T luôn ánh xạ tới std::optional<T> .

Đối với loại L giống như danh sách, chẳng hạn như T[] hoặc List<T> , @nullable L ánh xạ tới std::optional<std::vector<std::optional<T>>> (hoặc std::unique_ptr<std::vector<std::unique_ptr<T>>> trong trường hợp phụ trợ CPP cho Android 11 trở xuống).

Có một ngoại lệ cho bản đồ này. Khi TIBinder hoặc giao diện AIDL, @nullable không hoạt động. Nói cách khác, cả @nullable IBinderIBinder đều ánh xạ tới android::sp<IBinder> , vốn đã có giá trị rỗng vì nó là một con trỏ mạnh (đọc CPP vẫn thực thi tính vô hiệu, nhưng loại vẫn là android::sp<IBinder> ).

Bắt đầu từ Android 13, @nullable(heap=true) có thể được sử dụng cho các trường có thể phân chia để mô hình hóa các kiểu đệ quy. @nullable(heap=true) không thể được sử dụng với các tham số phương thức hoặc kiểu trả về. Khi được chú thích bằng nó, trường được ánh xạ tới tham chiếu được phân bổ vùng heap std::unique_ptr<T> trong phần phụ trợ CPP/NDK. @nullable(heap=true) không hoạt động trong phần phụ trợ Java.

utf8InCpp

utf8InCpp khai báo rằng String được thể hiện ở định dạng UTF8 cho chương trình phụ trợ CPP. Như tên của nó đã chỉ ra, chú thích này không dành cho các chương trình phụ trợ khác. Cụ thể, String luôn là UTF16 trong phần phụ trợ Java và UTF8 trong phần phụ trợ NDK.

Chú thích này có thể được đính kèm ở bất kỳ nơi nào có thể sử dụng loại String , bao gồm các giá trị trả về, tham số, khai báo hằng số và các trường có thể phân chia.

Đối với phần phụ trợ CPP, @utf8InCpp String trong AIDL ánh xạ tới std::string , trong khi String không có chú thích ánh xạ tới android::String16 trong đó UTF16 được sử dụng.

Lưu ý rằng sự tồn tại của chú thích utf8InCpp không thay đổi cách truyền chuỗi qua dây. Chuỗi luôn được truyền dưới dạng UTF16 qua dây. Chuỗi chú thích utf8InCpp được chuyển đổi thành UTF16 trước khi được truyền đi. Khi nhận được một chuỗi, nó sẽ được chuyển đổi từ UTF16 sang UTF8 nếu nó được chú thích là utf8InCpp .

VintfTính ổn định

VintfStability tuyên bố rằng loại do người dùng xác định (giao diện, có thể gửi được và enum) có thể được sử dụng trên toàn hệ thống và các miền của nhà cung cấp. Xem AIDL cho HAL để biết thêm về khả năng tương tác giữa nhà cung cấp hệ thống và hệ thống.

Chú thích không thay đổi chữ ký của loại, nhưng khi nó được đặt, phiên bản của loại được đánh dấu là ổn định để nó có thể di chuyển qua các quy trình của nhà cung cấp và hệ thống.

Chú thích chỉ có thể được đính kèm với các khai báo kiểu do người dùng xác định như dưới đây:

@VintfStability
interface IFoo {
    ....
}

@VintfStability
parcelable Data {
    ....
}

@VintfStability
enum Type {
    ....
}

Khi một loại được chú thích bằng VintfStability , bất kỳ loại nào khác được tham chiếu trong loại đó cũng phải được chú thích như vậy. Trong ví dụ bên dưới, cả DataIBar đều phải được chú thích bằng VintfStability .

@VintfStability
interface IFoo {
    void doSomething(in IBar b); // references IBar
    void doAnother(in Data d); // references Data
}

@VintfStability // required
interface IBar {...}

@VintfStability // required
parcelable Data {...}

Ngoài ra, các tệp AIDL xác định loại được chú thích bằng VintfStability chỉ có thể được xây dựng bằng cách sử dụng loại mô-đun aidl_interface Soong, với thuộc tính stability được đặt thành "vintf" .

aidl_interface {
    name: "my_interface",
    srcs: [...],
    stability: "vintf",
}

Cách sử dụng ứng dụng không được hỗ trợ

Chú thích UnsupportedAppUsage biểu thị rằng loại AIDL được chú thích là một phần của giao diện không phải SDK mà các ứng dụng cũ có thể truy cập được. Xem phần Hạn chế đối với giao diện không phải SDK để biết thêm thông tin về các API ẩn.

Chú thích UnsupportedAppUsage không ảnh hưởng đến hoạt động của mã được tạo. Chú thích chỉ chú thích lớp Java được tạo bằng chú thích Java có cùng tên.

// in AIDL
@UnsupportedAppUsage
interface IFoo {...}

// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}

Đây là tính năng không hoạt động đối với các chương trình phụ trợ không phải Java.

Sao lưu

Chú thích Backing chỉ định loại lưu trữ của loại enum AIDL.

@Backing(type="int")
enum Color { RED, BLUE, }

Trong phần phụ trợ CPP, phần trên phát ra một lớp enum C++ loại int32_t .

enum class Color : int32_t {
    RED = 0,
    BLUE = 1,
}

Nếu chú thích bị bỏ qua, type được giả định là byte , ánh xạ tới int8_t cho phần phụ trợ CPP.

Đối type chỉ có thể được đặt thành các loại tích phân sau:

  • byte (rộng 8 bit)
  • int (rộng 32 bit)
  • long (rộng 64 bit)

NdkOnlyStableParcelable

NdkOnlyStableParcelable đánh dấu một khai báo có thể gửi được (không phải định nghĩa) là ổn định để nó có thể được tham chiếu từ các loại AIDL ổn định khác. Điều này giống như JavaOnlyStableParcelable , nhưng NdkOnlyStableParcelable đánh dấu một khai báo có thể phân chia là ổn định cho phần phụ trợ NDK thay vì cho Java.

Để sử dụng gói này: * Bạn phải chỉ định ndk_header . * Bạn phải có thư viện NDK chỉ định khả năng phân phối và thư viện phải được biên dịch vào thư viện. Ví dụ: trong hệ thống xây dựng cốt lõi trên mô-đun cc_* , hãy sử dụng static_libs hoặc shared_libs . Đối với aidl_interface , hãy thêm thư viện trong phần additional_shared_libraries trong Android.bp .

JavaOnlyỔn địnhParcelable

JavaOnlyStableParcelable đánh dấu một khai báo có thể phân chia (không phải định nghĩa) là ổn định để nó có thể được tham chiếu từ các loại AIDL ổn định khác.

AIDL ổn định yêu cầu tất cả các loại do người dùng xác định đều ổn định. Đối với các bưu kiện, để ổn định, các trường của nó phải được mô tả rõ ràng trong tệp nguồn AIDL.

parcelable Data { // Data is a structured parcelable.
    int x;
    int y;
}

parcelable AnotherData { // AnotherData is also a structured parcelable
    Data d; // OK, because Data is a structured parcelable
}

Nếu bưu kiện không có cấu trúc (hoặc chỉ được khai báo) thì nó không thể được tham chiếu.

parcelable Data; // Data is NOT a structured parcelable

parcelable AnotherData {
    Data d; // Error
}

JavaOnlyStableParcelable cho phép bạn ghi đè kiểm tra khi gói có thể gửi mà bạn đang tham chiếu đã có sẵn một cách an toàn như một phần của SDK Android.

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

JavaDẫn xuất

JavaDerive tự động tạo ra các phương thức cho các loại có thể phân chia được trong phần phụ trợ Java.

@JavaDerive(equals = true, toString = true)
parcelable Data {
  int number;
  String str;
}

Chú thích yêu cầu các tham số bổ sung để kiểm soát nội dung cần tạo. Các tham số được hỗ trợ là:

  • equals=true tạo ra các phương thức equalshashCode .
  • toString=true tạo ra phương thức toString in tên của loại và các trường. Ví dụ: Data{number: 42, str: foo}

JavaMặc định

JavaDefault , được thêm vào Android 13, kiểm soát xem có tạo hỗ trợ phiên bản triển khai mặc định hay không (đối với setDefaultImpl ). Hỗ trợ này không còn được tạo theo mặc định để tiết kiệm dung lượng.

Truyền qua Java

JavaPassthrough cho phép API Java được tạo được chú thích bằng chú thích Java tùy ý.

Các chú thích sau trong AIDL

@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")

trở nên

@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)

trong mã Java được tạo.

Giá trị của tham số annotation được phát ra trực tiếp. Trình biên dịch AIDL không xem xét giá trị của tham số. Nếu có bất kỳ lỗi cú pháp cấp độ Java nào, nó sẽ không bị trình biên dịch AIDL phát hiện mà bởi trình biên dịch Java.

Chú thích này có thể được đính kèm với bất kỳ thực thể AIDL nào. Chú thích này không dành cho các chương trình phụ trợ không phải Java.

Kích thước cố định

FixedSize đánh dấu một gói có cấu trúc có kích thước cố định. Sau khi được đánh dấu, bưu kiện sẽ không được phép thêm trường mới vào đó. Tất cả các trường của gói có thể phân chia cũng phải là loại có kích thước cố định, bao gồm các loại nguyên thủy, enum, mảng có kích thước cố định và các loại có thể phân chia khác được đánh dấu bằng FixedSize .

Điều này không cung cấp bất kỳ sự đảm bảo nào trên các bit khác nhau và không nên dựa vào đó để liên lạc với các bit hỗn hợp.

Bộ mô tả

Descriptor buộc phải chỉ định bộ mô tả giao diện của một giao diện.

package android.foo;

@Descriptor(value="android.bar.IWorld")
interface IHello {...}

Mô tả của giao diện trên là android.bar.IWorld . Nếu thiếu chú thích Descriptor , bộ mô tả sẽ là android.foo.IHello .

Điều này rất hữu ích cho việc đổi tên một giao diện đã được xuất bản. Việc làm cho bộ mô tả của giao diện được đổi tên giống với bộ mô tả của giao diện trước khi đổi tên cho phép hai giao diện giao tiếp với nhau.

@ẩn trong bình luận

Trình biên dịch AIDL nhận ra @hide trong các nhận xét và chuyển nó đến đầu ra Java để metalava tiếp nhận. Nhận xét này đảm bảo rằng hệ thống xây dựng Android biết rằng API AIDL không phải là API SDK.

@deprecated trong nhận xét

Trình biên dịch AIDL nhận dạng @deprecated trong nhận xét dưới dạng thẻ để xác định thực thể AIDL không còn được sử dụng nữa.

interface IFoo {
  /** @deprecated use bar() instead */
  void foo();
  void bar();
}

Mỗi phần phụ trợ đánh dấu các thực thể không được dùng nữa bằng chú thích/thuộc tính dành riêng cho phần phụ trợ để mã máy khách được cảnh báo nếu nó đề cập đến các thực thể không được dùng nữa. Ví dụ: chú thích @Deprecated và thẻ @deprecated được đính kèm với mã do Java tạo ra.