AIDL 中的註解

AIDL 支持為 AIDL 編譯器提供有關帶註釋元素的額外信息的註釋,這也會影響生成的存根代碼。

語法類似於Java:

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

這裡, AnnotationName是註解的名稱, AidlEntity是一個 AIDL 實體,例如interface Foovoid method()int arg 。註釋附加到它後面的實體。

一些註釋可以在括號內設置參數,如上所示。沒有參數的註釋不需要括號。例如:

@AnnotationName AidlEntity

這些註釋與 Java 註釋不同,儘管它們看起來非常相似。用戶不能定義自定義 AIDL 註解;註釋都是預定義的。一些註釋只影響某個後端並且在其他後端是無操作的。它們在可以附加的地方有不同的限制。

下面是預定義的 AIDL 註釋列表:

註釋安卓版新增
nullable 7
utf8InCpp 7
VintfStability 11
UnsupportedAppUsage 10
Hide 11
Backing 11
JavaOnlyStableParcelable 11
JavaDerive 12
JavaPassthrough 12
FixedSize 12
Descriptor 12

可為空的

nullable聲明可能不提供註釋實體的值。

此註解只能附加到方法返回類型、方法參數和可打包字段。

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

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

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

註釋不能附加到原始類型。以下是一個錯誤。

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

此註解對於 Java 後端是無操作的。這是因為,在 Java 中,所有非原始類型都是通過引用傳遞的,它可能是null

在 CPP 後端, @nullable T在 Android 11 或更低版本中映射到std::unique_ptr<T> ,在 Android 12 或更高版本中映射到std::optional<T>

在 NDK 後端, @nullable T始終映射到std::optional<T>

對於類似列表的類型L ,例如T[]List<T>@nullable L映射到std::optional<std::vector<std::optional<T>>> (或std::unique_ptr<std::vector<std::unique_ptr<T>>>如果是 Android 11 或更低版本的 CPP 後端)。

此映射有一個例外。當TIBinder或 AIDL 接口時, @nullable是無操作的。換句話說, @nullable IBinderIBinder同樣映射到android::sp<IBinder> ,它已經可以為空,因為它是一個強指針(CPP 讀取仍然強制可空性,但類型仍然是android::sp<IBinder> )。

從 Android T(AOSP 實驗性)開始, @nullable(heap=true)可用於 parcelable 字段以對遞歸類型進行建模。 @nullable(heap=true)不能與方法參數或返回類型一起使用。當使用它進行註釋時,該字段將映射到 CPP/NDK 後端中的堆分配引用std::unique_ptr<T>@nullable(heap=true)在 Java 後端是無操作的。

utf8InCpp

utf8InCpp聲明一個String以 UTF8 格式表示 CPP 後端。顧名思義,註解對於其他後端是無操作的。具體來說, String在 Java 後端始終為 UTF16,在 NDK 後端始終為 UTF8。

這個註解可以附加到任何可以使用String類型的地方,包括返回值、參數、常量聲明和 parcelable 字段。

對於 CPP 後端,AIDL 中的@utf8InCpp String映射到std::string ,而沒有註釋的String映射到使用 UTF16 的android::String16

請注意, utf8InCpp註釋的存在不會改變字符串通過網絡傳輸的方式。字符串始終以 UTF16 格式通過網絡傳輸。一個utf8InCpp註釋的字符串在傳輸之前被轉換為 UTF16。當接收到一個字符串時,如果它被註釋為utf8InCpp ,它會從 UTF16 轉換為 UTF8。

Vintf穩定性

VintfStability聲明用戶定義的類型(接口、parcelable 和枚舉)可以跨系統和供應商域使用。有關係統供應商互操作性的更多信息,請參閱HAL 的 AIDL

註解不會改變類型的簽名,但是當它被設置時,類型的實例被標記為穩定的,這樣它就可以跨越供應商和系統進程。

註解只能附加到用戶定義的類型聲明,如下所示:

@VintfStability
interface IFoo {
    ....
}

@VintfStability
parcelable Data {
    ....
}

@VintfStability
enum Type {
    ....
}

當一個類型使用VintfStability註釋時,該類型中引用的任何其他類型也應該這樣註釋。在下面的示例中, DataIBar都應使用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 {...}

此外,定義使用VintfStability註釋的類型的 AIDL 文件只能使用aidl_interface Soong 模塊類型構建, stability屬性設置為"vintf"

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

不支持的應用程序使用情況

UnsupportedAppUsage註釋表示帶註釋的 AIDL 類型是舊版應用程序可訪問的非 SDK 接口的一部分。有關隱藏 API 的更多信息,請參閱對非 SDK 接口的限制

UnsupportedAppUsage註釋不會影響生成代碼的行為。註解只用同名的Java註解對生成的Java類進行註解。

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

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

這對於非 Java 後端是無操作的。

後盾

Backing註解指定 AIDL 枚舉類型的存儲類型。

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

在 CPP 後端,上面發出一個int32_t類型的 C++ 枚舉類。

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

如果省略註釋,則假定typebyte ,它映射到 CPP 後端的int8_t

type參數只能設置為以下整數類型:

  • byte (8 位寬)
  • int (32 位寬)
  • long (64 位寬)

JavaOnlyStableParcelable

JavaOnlyStableParcelable將 parcelable 聲明(而非定義)標記為穩定,以便可以從其他穩定的 AIDL 類型引用它。

穩定的 AIDL 要求所有用戶定義的類型都是穩定的。對於 parcelables,穩定要求其字段在 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
}

如果 parcelable 是非結構化的(或剛剛聲明的),則無法引用它。

parcelable Data; // Data is NOT a structured parcelable

parcelable AnotherData {
    Data d; // Error
}

當您引用的 Parcelable 已作為 Android SDK 的一部分安全可用時, JavaOnlyStableParcelable允許您覆蓋檢查。

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

Java派生

JavaDerive在 Java 後端自動為可打包類型生成方法。

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

註釋需要額外的參數來控制生成什麼。支持的參數有:

  • equals=true生成equalshashCode方法。
  • toString=true生成打印類型和字段名稱的toString方法。例如: Data{number: 42, str: foo}

Java默認

JavaDefault在 Android T(AOSP 實驗性)中添加,控制是否生成默認實現版本控制支持(用於setDefaultImpl )。為了節省空間,默認情況下不再生成此支持。

JavaPassthrough

JavaPassthrough允許使用任意 Java 註釋對生成的 Java API 進行註釋。

AIDL 中的以下註解

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

變得

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

在生成的 Java 代碼中。

直接發出annotation參數的值。 AIDL 編譯器不會查看參數的值。如果有任何 Java 級別的語法錯誤,它不會被 AIDL 編譯器捕獲,而是被 Java 編譯器捕獲。

此註釋可以附加到任何 AIDL 實體。此註解對於非 Java 後端是無操作的。

固定尺寸

FixedSize將結構化 Parcelable 標記為固定大小。一旦標記,parcelable 將不允許添加新字段。 parcelable 的所有字段也必須是固定大小的類型,包括原始類型、枚舉、固定大小的數組和其他標有 FixedSize 的FixedSize

這不提供跨不同位的任何保證,並且不應依賴於混合位通信。

描述符

Descriptor強制指定接口的接口描述符。

package android.foo;

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

上述接口的描述符是android.bar.IWorld 。如果缺少Descriptor註釋,則描述符將為android.foo.IHello

這對於重命名已發布的接口很有用。使重命名接口的描述符與重命名前接口的描述符相同,允許兩個接口相互通信。

@隱藏在評論中

AIDL 編譯器識別註釋中的@hide並將其傳遞到 Java 輸出以供 metalava 拾取。此註釋可確保 Android 構建系統知道 AIDL API 不是 SDK API。

@deprecated 在評論中

AIDL 編譯器將註釋中的@deprecated識別為標記,以標識不應再使用的 AIDL 實體。

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

每個後端使用特定於後端的註釋/屬性標記不推薦使用的實體,以便客戶端代碼在引用不推薦使用的實體時收到警告。例如, @Deprecated註釋和@deprecated標記附加到 Java 生成的代碼。