AIDL は、アノテーションを付けた要素に関する詳細情報を AIDL コンパイラに提供するアノテーションをサポートしています。これは生成されたスタブコードにも影響します。
この構文は Java の構文に似ています。
@AnnotationName(argument1=value, argument2=value) AidlEntity
ここで、AnnotationName
はアノテーションの名前で、AidlEntity
は interface Foo
、void method()
、int arg
などの AIDL エンティティです。その後のエンティティにはアノテーションが付けられます。
上記のように、一部のアノテーションではかっこ内に引数を設定できます。引数のないアノテーションでは、かっこは不要です。次に例を示します。
@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
nullable
は、アノテーションが付けられたエンティティの値を指定できない場合があることを宣言します。
このアノテーションは、メソッドの戻り値の型、メソッド パラメータ、Parcelable フィールドだけに付加できます。
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>
にマッピングされます。
Rust バックエンドでは、@nullable T
は常に Option<T>
にマッピングされます。
T[]
や List<T>
のような list-like 型の L
の場合、@nullable L
は std::optional<std::vector<std::optional<T>>>
にマッピングされます(Android 11 以下の CPP バックエンドの場合は std::unique_ptr<std::vector<std::unique_ptr<T>>>
)。
このマッピングには例外があります。T
が IBinder
または AIDL インターフェースの場合、@nullable
はどのバックエンドにも影響しません(Rust を除く)。つまり、@nullable IBinder
と IBinder
はどちらも android::sp<IBinder>
にマッピングされますが、すでに null 値を許容できます。これは、強いポインタであるためです(CPP 読み取りは引き続き null 可能性を適用しますが、型は android::sp<IBinder>
のままです)。Rust では、これらの型は @nullable
のアノテーションが付けられている場合にのみ、nullable
になります。アノテーションが付けられている場合、Option<T>
にマッピングされます。
Android 13 以降では、@nullable(heap=true)
を Parcelable フィールドに使用して、再帰型をモデル化できます。@nullable(heap=true)
は、メソッド パラメータや戻り値の型と一緒には使用できません。アノテーションが付けられると、このフィールドは CPP/NDK バックエンドのヒープ割り当て参照 std::unique_ptr<T>
にマッピングされます。@nullable(heap=true)
は Java バックエンドには影響しません。
utf8InCpp
utf8InCpp
は、String
を CPP バックエンドに対して UTF8 形式で表すことを宣言します。名前が示すように、このアノテーションは他のバックエンドには影響しません。具体的には、String
は常に Java バックエンドでは UTF16、NDK バックエンドでは UTF8 です。
このアノテーションは、戻り値、パラメータ、定数宣言、Parcelable フィールドなど、String
型が使用されている任意の場所に付加できます。
CPP バックエンドの場合、AIDL の @utf8InCpp String
は std::string
にマッピングされ、アノテーションなしの String
は、UTF16 が使用される android::String16
にマッピングされます。
utf8InCpp
アノテーションが存在しても、文字列が送信される方法は変わりません。文字列は常に UTF16 として送信されます。utf8InCpp
アノテーション付きの文字列は、送信前に UTF16 に変換されます。受け取った文字列に utf8InCpp
のアノテーションが付いていた場合、UTF16 から UTF8 に変換されます。
VintfStability
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 ファイルを作成するには、stability
プロパティを "vintf"
に設定した aidl_interface
Soong モジュール型を使用する必要があります。
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
UnsupportedAppUsage
UnsupportedAppUsage
アノテーションは、アノテーション付き AIDL 型が、従来のアプリでアクセス可能な SDK 以外のインターフェースの一部であることを示します。非表示の API について詳しくは、非 SDK インターフェースの制限をご覧ください。
UnsupportedAppUsage
アノテーションは、生成されたコードの動作には影響しません。このアノテーションは、生成された Java クラスに、同じ名前の Java アノテーションを付けるだけです。
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
これは、Java 以外のバックエンドには影響しません。
Backing
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
は、他の安定版 AIDL 型から参照できるように、Parcelable 宣言を(定義ではなく)安定版としてマークします。これは JavaOnlyStableParcelable
と似ていますが、NdkOnlyStableParcelable
は Java ではなく NDK バックエンドの Parcelable 宣言を安定版としてマークします。
この Parcelable を使用するには:
ndk_header
を指定する必要があります。- Parcelable を指定する NDK ライブラリが必要です。このライブラリはライブラリにコンパイルする必要があります。たとえば、
cc_*
モジュールのコア ビルドシステムでは、static_libs
またはshared_libs
を使用します。aidl_interface
については、Android.bp
のadditional_shared_libraries
にライブラリを追加します。
JavaOnlyStableParcelable
JavaOnlyStableParcelable
は、他の安定版 AIDL 型から参照できるように、Parcelable 宣言を(定義ではなく)安定版としてマークします。
安定版 AIDL では、すべてのユーザー定義型が安定版である必要があります。Parcelable の場合、安定版にするには、フィールドを 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
}
JavaOnlyStableParcelable
を使用すると、参照する Parcelable が Android SDK の一部として安全に使用可能になったときにチェックをオーバーライドできます。
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
JavaDerive
JavaDerive
は、Java バックエンドの Parcelable 型のメソッドを自動的に生成します。
@JavaDerive(equals = true, toString = true)
parcelable Data {
int number;
String str;
}
アノテーションには、何を生成するかを制御するための追加のパラメータが必要です。現在サポートされているパラメータは次のとおりです:
equals=true
は、equals
メソッドとhashCode
メソッドを生成します。toString=true
は、型とフィールドの名前を出力するtoString
メソッドを生成します(例:Data{number: 42, str: foo}
)。
JavaDefault
Android 13 で追加された JavaDefault
は、デフォルトの実装バージョニング サポートを生成するかどうかを制御します(setDefaultImpl
用)。スペース節約のために、このサポートはデフォルトで生成されなくなりました。
JavaPassthrough
JavaPassthrough
を使用すると、生成された Java API に任意の Java アノテーションを付けることができます。
次に示す AIDL のアノテーションは
@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")
生成された Java コードで
@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)
このようになります。
annotation
パラメータの値は直接出力されます。AIDL コンパイラはパラメータの値については考慮しません。Java レベルの構文エラーがある場合、これは AIDL コンパイラではなく Java コンパイラによって捕捉されます。
このアノテーションは、任意の AIDL エンティティに付加できます。Java 以外のバックエンドには影響しません。
FixedSize
FixedSize
は、構造化された Parcelable を固定サイズとしてマークします。一度指定すると、Parcelable に新しいフィールドを追加できなくなります。また、Parcelable のすべてのフィールドは、プリミティブ型、列挙型、固定サイズ配列、FixedSize
でマークされた他の Parcelable など、サイズが固定された型でなければなりません。
ただし、ビットが異なる場合については保証されないため、ビットが混在する通信ではこの方法に依存しないでください。
Descriptor
Descriptor
は、インターフェースのインターフェース記述子を強制的に指定します。
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
このインターフェースの記述子は android.bar.IWorld
です。Descriptor
アノテーションがない場合、記述子は android.foo.IHello
になります。
これは、公開済みのインターフェースの名前を変更する場合に役立ちます。名前を変更したインターフェースの記述子を、名前を変更する前のインターフェースの記述子と同じにすると、2 つのインターフェースが相互に通信できるようになります。
コメント内の @hide
AIDL コンパイラは、コメント内の @hide
を認識して Java 出力にこれを渡し、metalava が受け取れるようにします。このコメントにより、AIDL API が SDK API ではないことを Android ビルドシステムが認識できるようになります。
コメント内の @deprecated
AIDL コンパイラは、コメント内の @deprecated
をタグとして認識し、使用すべきでない AIDL エンティティを識別します。
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
各バックエンドは、非推奨のエンティティをバックエンド固有のアノテーション / 属性でマークして、非推奨のエンティティを参照する場合にクライアント コードが警告されるようにします。たとえば、@Deprecated
アノテーションと @deprecated
タグは Java で生成されたコードに付加されます。