AIDL 支持為 AIDL 編譯器提供有關帶註釋元素的額外信息的註釋,這也會影響生成的存根代碼。
語法類似於Java:
@AnnotationName(argument1=value, argument2=value) AidlEntity
這裡, AnnotationName
是註解的名稱, AidlEntity
是一個 AIDL 實體,例如interface Foo
、 void 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 後端)。
此映射有一個例外。當T
是IBinder
或 AIDL 接口時, @nullable
是無操作的。換句話說, @nullable IBinder
和IBinder
同樣映射到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
註釋時,該類型中引用的任何其他類型也應該這樣註釋。在下面的示例中, 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 位寬)
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默認
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 生成的代碼。