AIDL 支援註釋,為 AIDL 編譯器提供有關註釋元素的額外信息,這也會影響生成的存根程式碼。
語法與Java類似:
@AnnotationName(argument1=value, argument2=value) AidlEntity
這裡, AnnotationName
是註解的名稱, AidlEntity
是一個 AIDL 實體,例如interface Foo
、 void 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 後端)。
此映射有一個例外。當T
是IBinder
或AIDL介面時, @nullable
是無操作的。換句話說, @nullable IBinder
和IBinder
同樣映射到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
註解類型時,該類型中引用的任何其他類型也應如此註解。在下面的範例中, Data
和IBar
都應使用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,
}
如果省略註釋,則假定type
為byte
,它對應到 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_libs
或shared_libs
。對於aidl_interface
,請在Android.bp
的additional_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
產生equals
和hashCode
方法。 -
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 產生的程式碼中。