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
сопоставляется с std::unique_ptr<T>
в Android 11 или более ранней версии и с std::optional<T>
в Android 12 или более поздней версии.
В бэкэнде NDK @nullable T
всегда сопоставляется с std::optional<T>
.
В бэкэнде Rust @nullable T
всегда сопоставляется с Option<T>
.
Для списка типа L
такого как T[]
или List<T>
, @nullable L
сопоставляется с std::optional<std::vector<std::optional<T>>>
(или std::unique_ptr<std::vector<std::unique_ptr<T>>>
в случае серверной части CPP для Android 11 или более ранней версии).
Есть исключение из этого сопоставления. Когда 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)
можно использовать для разделяемых полей для моделирования рекурсивных типов. @nullable(heap=true)
нельзя использовать с параметрами метода или возвращаемыми типами. Если оно снабжено аннотацией, поле сопоставляется с выделенной в куче ссылкой std::unique_ptr<T>
в серверных модулях CPP/NDK. @nullable(heap=true)
не работает в серверной части Java.
utf8InCpp
utf8InCpp
заявляет, что String
представлена в формате UTF8 для серверной части CPP. Как следует из названия, аннотация неактивна для других серверов. В частности, String
всегда имеет формат UTF16 в серверной части Java и UTF8 в серверной части NDK.
Эту аннотацию можно прикрепить везде, где может использоваться тип String
, включая возвращаемые значения, параметры, объявления констант и разделяемые поля.
Для серверной части CPP @utf8InCpp String
в AIDL сопоставляется с std::string
, тогда как String
без аннотации сопоставляется с android::String16
, где используется UTF16.
Обратите внимание, что наличие аннотации utf8InCpp
не меняет способ передачи строк по сети. Строки всегда передаются по сети в формате UTF16. Строка с аннотацией utf8InCpp
преобразуется в UTF16 перед передачей. Когда строка получена, она преобразуется из UTF16 в UTF8, если она была помечена как utf8InCpp
.
VintfСтабильность
VintfStability
заявляет, что определяемый пользователем тип (интерфейс, посылка и перечисление) может использоваться в доменах системы и поставщика. Дополнительную информацию о совместимости систем и поставщиков см. в разделе AIDL для HAL .
Аннотация не меняет сигнатуру типа, но когда она установлена, экземпляр типа помечается как стабильный, чтобы его можно было перемещать между процессами поставщика и системы.
Аннотация может быть прикреплена только к объявлениям определяемых пользователем типов, как показано здесь:
@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 {...}
Кроме того, файлы AIDL, определяющие типы, аннотированные с помощью VintfStability
могут быть созданы только с использованием типа модуля 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 это создает класс перечисления C++ типа int32_t
.
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
Если аннотация опущена, предполагается, что type
является byte
, который соответствует int8_t
для серверной части CPP.
Аргумент type
может быть установлен только для следующих целочисленных типов:
-
byte
(ширина 8 бит) -
int
(ширина 32 бита) -
long
(64-битный)
NdkOnlyStableParcelable
NdkOnlyStableParcelable
помечает разделяемое объявление (не определение) как стабильное, чтобы на него можно было ссылаться из других стабильных типов AIDL. Это похоже на JavaOnlyStableParcelable
, но NdkOnlyStableParcelable
помечает объявление посылки как стабильное для серверной части NDK, а не для Java.
Чтобы использовать эту посылку:
- Вы должны указать
ndk_header
. - У вас должна быть библиотека NDK, определяющая объект посылки, и библиотека должна быть скомпилирована в библиотеку. Например, в базовой системе сборки модуля
cc_*
используйтеstatic_libs
shared_libs
. Дляaidl_interface
добавьте библиотеку в разделadditional_shared_libraries
вAndroid.bp
.
JavaOnlyStableParcelable
JavaOnlyStableParcelable
помечает разделяемое объявление (не определение) как стабильное, чтобы на него можно было ссылаться из других стабильных типов AIDL.
Стабильный AIDL требует, чтобы все определяемые пользователем типы были стабильными. Стабильность парцеллярных объектов требует, чтобы их поля были явно описаны в исходном файле 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 Data; // Data is NOT a structured parcelable
parcelable AnotherData {
Data d; // Error
}
JavaOnlyStableParcelable
позволяет переопределить проверку, когда объект, на который вы ссылаетесь, уже безопасно доступен как часть Android SDK.
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
JavaDerive
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}
JavaDefault
JavaDefault
, добавленный в Android 13, контролирует, создается ли поддержка управления версиями реализации по умолчанию (для setDefaultImpl
). Эта поддержка больше не создается по умолчанию в целях экономии места.
JavaPassthrough
JavaPassthrough
позволяет добавлять к сгенерированному API Java произвольную аннотацию Java.
Следующие аннотации в 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
помечает структурированный участок как фиксированный размер. После пометки к земельному участку нельзя будет добавлять новые поля. Все поля участка также должны иметь типы фиксированного размера, включая примитивные типы, перечисления, массивы фиксированного размера и другие объекты, помеченные FixedSize
.
Это не дает никаких гарантий для разных разрядностей, и на него не следует полагаться при обмене данными со смешанной разрядностью.
Дескриптор
Descriptor
принудительно определяет дескриптор интерфейса.
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
Дескриптор этого интерфейса — android.bar.IWorld
. Если аннотация Descriptor
отсутствует, дескриптор будет иметь вид android.foo.IHello
.
Это полезно для переименования уже опубликованного интерфейса. Создание дескриптора переименованного интерфейса таким же, как дескриптор интерфейса перед переименованием, позволяет двум интерфейсам взаимодействовать друг с другом.
@скрыть в комментариях
Компилятор AIDL распознает @hide
в комментариях и передает его на вывод Java для использования Metalava. Этот комментарий гарантирует, что система сборки Android знает, что API AIDL не являются API SDK.
@устарело в комментариях
Компилятор AIDL распознает @deprecated
в комментариях как тег, идентифицирующий объект AIDL, который больше не следует использовать.
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
Каждая серверная часть помечает устаревшие сущности аннотацией или атрибутом, специфичным для серверной части, чтобы клиентский код получал предупреждение, если он ссылается на устаревшие сущности. Например, аннотация @Deprecated
и тег @deprecated
прикреплены к коду, сгенерированному Java.