AIDL 中的註解

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

語法與Java類似:

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

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

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

@AnnotationName AidlEntity

這些註解與 Java 註解不同,儘管它們看起來非常相似。使用者無法定義自訂AIDL註解;註釋都是預先定義的。有些註解只影響某個後端,在其他後端不起作用。它們有不同的附加限制。

以下是預先定義的 AIDL 註解清單:

註解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

可為空的

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 13 開始, @nullable(heap=true)可用於 Parcelable 欄位來建模遞歸類型。 @nullable(heap=true)不能與方法參數或傳回類型一起使用。當使用它註解時,該欄位將對應到 CPP/NDK 後端中的堆疊分配引用std::unique_ptr<T>@nullable(heap=true)在 Java 後端是無操作的。

utf8InCpp

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

此註解可以附加到可以使用String類型的任何地方,包括傳回值、參數、常數聲明和可分割欄位。

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

請注意, utf8InCpp註解的存在不會改變字串透過線路傳輸的方式。字串始終以 UTF16 格式透過線路傳輸。 utf8InCpp註解的字串在傳輸之前會轉換為 UTF16。當接收到字串時,如果它被註解為utf8InCpp ,則會從 UTF16 轉換為 UTF8。

穩定性

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 位寬)

NdkOnlyStableParcelable

NdkOnlyStableParcelable將 Parcelable 聲明(而不是定義)標記為穩定,以便可以從其他穩定的 AIDL 類型引用它。這類似於JavaOnlyStableParcelable ,但NdkOnlyStableParcelable將 Parcelable 聲明標記為 NDK 後端穩定,而不是 Java。

若要使用此 Parcelable: * 您必須指定ndk_header 。 * 您必須有一個指定 Parcelable 的 NDK 函式庫,且該函式庫必須編譯到該函式庫中。例如,在cc_*模組上的核心建置系統中,使用static_libsshared_libs 。對於aidl_interface ,請在Android.bpadditional_shared_libraries下方新增庫。

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預設值

Android 13 中新增的JavaDefault控制是否會產生預設實作版本控制支援(對於setDefaultImpl )。為了節省空間,預設不再產生此支援。

Java直通

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的 Parcelable。

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

描述符

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。

@在評論中已棄用

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

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

每個後端都使用後端特定的註釋/屬性來標記已棄用的實體,以便用戶端程式碼在引用已棄用的實體時收到警告。例如, @Deprecated註解和@deprecated標記附加到 Java 產生的程式碼中。