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 |
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 std::optional<T>
в Android 12 или более поздней версии.
В бэкэнде 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>>>
в случае серверной части CPP для Android 11 или ниже).
Существует исключение из этого сопоставления. Когда T
является IBinder
или AIDL, @nullable
не работает. Другими словами, как @nullable IBinder
, так и IBinder
в равной степени сопоставляются с android::sp<IBinder>
, который уже допускает значение NULL, поскольку является сильным указателем (чтение CPP по-прежнему обеспечивает обнуляемость, но тип по-прежнему остается android::sp<IBinder>
).
Начиная с Android T (экспериментальный AOSP), @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-битный)
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
}
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}
JavaDefault
JavaDefault
, добавленный в Android T (экспериментальный AOSP), управляет созданием поддержки версий реализации по умолчанию (для setDefaultImpl
). Эта поддержка больше не создается по умолчанию в целях экономии места.
JavaPassthrough
JavaPassthrough
позволяет аннотировать созданный Java API произвольной аннотацией 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 для захвата металавой. Этот комментарий гарантирует, что система сборки Android знает, что API-интерфейсы AIDL не являются API-интерфейсами SDK.
@deprecated в комментариях
Компилятор AIDL распознает @deprecated
в комментариях как тег для идентификации объекта AIDL, который больше не следует использовать.
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
Каждая серверная часть помечает устаревшие объекты с помощью аннотации/атрибута, характерной для серверной части, чтобы код клиента предупреждался, если он ссылается на устаревшие объекты. Например, аннотация @Deprecated
и тег @deprecated
присоединяются к сгенерированному коду Java.