Аннотации в AIDL

AIDL поддерживает аннотации, которые предоставляют компилятору AIDL дополнительную информацию об аннотируемом элементе, что также влияет на сгенерированный код-заглушку.

Синтаксис похож на синтаксис Java:

@AnnotationName(argument1=value, argument2=value) AidlEntity

Здесь AnnotationName — это имя аннотации, а AidlEntity — это сущность AIDL, например, interface Foo , void method() или int arg . К следующей за ней сущности прикрепляется аннотация.

Некоторые аннотации могут иметь аргументы, заданные внутри скобок, как показано в предыдущем примере. Аннотации, не имеющие аргументов, не нуждаются в скобках. Например:

@AnnotationName AidlEntity

Эти аннотации отличаются от аннотаций Java, хотя и выглядят похоже. Все аннотации предопределены и имеют ограничения по месту их применения. Некоторые аннотации влияют только на определенный бэкенд и не оказывают никакого воздействия на другие бэкенды.

Вот список предопределенных аннотаций 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 указывает, что значение аннотированного объекта может быть равно null.

Эту аннотацию можно добавлять только к типам возвращаемых значений методов, параметрам методов и полям, допускающим разделение по категориям:

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 .

В бэкенде C++ директива ` @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 или ниже).

There is an exception to this mapping. When T is IBinder or an AIDL interface, @nullable is a no-op for the Java, CPP, and NDK backends. For example, in the CPP backend, both @nullable IBinder and IBinder equally map to android::sp<IBinder> , which is already nullable because it is a strong pointer (CPP and NDK reads still enforce nullability, but the type remains android::sp<IBinder> or ndk::SpAIBinder ).

В бэкенде Rust типы, не реализующие Default ( IBinder , интерфейсы AIDL, ParcelFileDescriptor и неструктурированные парселируемые объекты), отображаются на Option<T> в зависимости от контекста:

  • Типы возвращаемых значений методов, in параметры и inout параметры: эти типы допускают значение null только в том случае, если они аннотированы @nullable , что соответствует Option<T> (или Option<&T> для in параметров и &mut Option<T> для inout параметров). Без @nullable они напрямую соответствуют T (или &T и &mut T ).
  • Parcelable fields and out parameters: Because generated Rust parcelables derive Default and out parameters are default-initialized, these types always map to Option<T> (and fixed-size arrays in these contexts map to [Option<T>; N] , while dynamic arrays in out parameters map to Vec<Option<T>> ), even without @nullable . When not annotated with @nullable , non-nullability is still enforced at runtime during parceling (returning StatusCode::UNEXPECTED_NULL if the value is None ).

Начиная с Android 13, аннотация @nullable(heap=true) может использоваться для полей, допускающих последовательность `parcelable`, для моделирования рекурсивных типов. @nullable(heap=true) нельзя использовать с параметрами методов или возвращаемыми типами. При использовании этой аннотации поле сопоставляется с выделенной в куче ссылкой std::unique_ptr<T> в бэкендах C++ и NDK. @nullable(heap=true) не выполняет никаких действий в бэкенде Java.

utf8InCpp

utf8InCpp указывает, что String представлена ​​в формате UTF8 для бэкенда C++. Как следует из названия, для других бэкендов эта аннотация ничего не делает. В частности, String всегда имеет кодировку UTF16 в бэкенде Java и UTF8 в бэкенде NDK.

Эту аннотацию можно добавить везде, где используется тип String , включая возвращаемые значения, параметры, объявления констант и поля, допускающие последовательность операций.

Для бэкенда на C++ @utf8InCpp String в AIDL соответствует std::string , тогда как String без аннотации соответствует android::String16 где используется кодировка UTF16.

VintfStability

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

Аннотация UnsupportedAppUsage указывает на то, что аннотированный тип AIDL является частью интерфейса, не входящего в SDK, который был доступен для устаревших приложений. Дополнительную информацию о скрытых API см. в разделе «Ограничения на интерфейсы, не входящие в SDK» .

Аннотация UnsupportedAppUsage не влияет на поведение сгенерированного кода. Эта аннотация применяется только к сгенерированному 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, }

В бэкенде C++ это генерирует класс перечисления 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 помечает объявление (а не определение) типа Parcelable как стабильное, чтобы на него можно было ссылаться из других стабильных типов AIDL. Это похоже на JavaOnlyStableParcelable , но NdkOnlyStableParcelable помечает объявление типа Parcelable как стабильное для бэкенда NDK, а не для Java.

Для использования этой посылки:

  • Необходимо указать ndk_header .
  • Необходимо наличие библиотеки NDK, указывающей на возможность использования Parcelable, и эта библиотека должна быть скомпилирована в основную библиотеку. Например, в основной системе сборки модуля cc_* используйте static_libs или shared_libs . Для aidl_interface добавьте библиотеку в additional_shared_libraries в Android.bp .

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 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:

@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 позволяет аннотировать сгенерированный 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, эта аннотация ничего не делает.

RustDerive

RustDerive автоматически реализует трейты для сгенерированных типов Rust.

Для аннотации требуются дополнительные параметры, определяющие процесс генерации. Поддерживаемые параметры:

  • Copy=true
  • Clone=true
  • Ord=true
  • PartialOrd=true
  • Eq=true
  • PartialEq=true
  • Hash=true

Для получения пояснений к этим свойствам см. документацию Rust .

Фиксированный размер

FixedSize помечает структурированный объект Parcelable как объект фиксированного размера. После присвоения такой маркировки добавлять новые поля в Parcelable нельзя. Все поля объекта Parcelable должны быть типами фиксированного размера, включая примитивные типы, перечисления, массивы фиксированного размера и другие объекты Parcelable, помеченные FixedSize .

Объекты FixedSize имеют стабильные размеры и выравнивание в бэкенде ndk .

Тип Размер (байты) Выравнивание (байты)
boolean 1 1
byte 1 1
char 2 2
int 4 4
long 8 8
float 4 4
double 8 8
parcelable Общий размер всех полей Наибольшее выравнивание всех полей
union Самое большое поле из всех. Наибольшее выравнивание всех полей
enum Размер типа подложки Выравнивание типа подложки
T[N] (массив фиксированного размера) Размер T * N Выравнивание T
String, IBinder, FileDescriptor, ParcelFileDescriptor N/A N/A

Дескриптор

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.

@deprecated в комментариях

Компилятор AIDL распознает @deprecated в комментариях как тег, указывающий на сущность AIDL, которую больше не следует использовать:

interface IFoo {
  /** @deprecated use bar() instead */
  void foo();
  void bar();
}

Каждый бэкенд помечает устаревшие сущности аннотацией или атрибутом, специфичным для бэкенда, чтобы клиентский код получал предупреждение, если он ссылается на устаревшие сущности. Например, к сгенерированному Java-коду добавляются аннотация @Deprecated и тег @deprecated .

,

AIDL поддерживает аннотации, которые предоставляют компилятору AIDL дополнительную информацию об аннотируемом элементе, что также влияет на сгенерированный код-заглушку.

Синтаксис похож на синтаксис Java:

@AnnotationName(argument1=value, argument2=value) AidlEntity

Здесь AnnotationName — это имя аннотации, а AidlEntity — это сущность AIDL, например, interface Foo , void method() или int arg . К следующей за ней сущности прикрепляется аннотация.

Некоторые аннотации могут иметь аргументы, заданные внутри скобок, как показано в предыдущем примере. Аннотации, не имеющие аргументов, не нуждаются в скобках. Например:

@AnnotationName AidlEntity

Эти аннотации отличаются от аннотаций Java, хотя и выглядят похоже. Все аннотации предопределены и имеют ограничения по месту их применения. Некоторые аннотации влияют только на определенный бэкенд и не оказывают никакого воздействия на другие бэкенды.

Вот список предопределенных аннотаций 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 указывает, что значение аннотированного объекта может быть равно null.

Эту аннотацию можно добавлять только к типам возвращаемых значений методов, параметрам методов и полям, допускающим разделение по категориям:

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 .

В бэкенде C++ директива ` @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 или ниже).

There is an exception to this mapping. When T is IBinder or an AIDL interface, @nullable is a no-op for the Java, CPP, and NDK backends. For example, in the CPP backend, both @nullable IBinder and IBinder equally map to android::sp<IBinder> , which is already nullable because it is a strong pointer (CPP and NDK reads still enforce nullability, but the type remains android::sp<IBinder> or ndk::SpAIBinder ).

В бэкенде Rust типы, не реализующие Default ( IBinder , интерфейсы AIDL, ParcelFileDescriptor и неструктурированные парселируемые объекты), отображаются на Option<T> в зависимости от контекста:

  • Типы возвращаемых значений методов, in параметры и inout параметры: эти типы допускают значение null только в том случае, если они аннотированы @nullable , что соответствует Option<T> (или Option<&T> для in параметров и &mut Option<T> для inout параметров). Без @nullable они напрямую соответствуют T (или &T и &mut T ).
  • Parcelable fields and out parameters: Because generated Rust parcelables derive Default and out parameters are default-initialized, these types always map to Option<T> (and fixed-size arrays in these contexts map to [Option<T>; N] , while dynamic arrays in out parameters map to Vec<Option<T>> ), even without @nullable . When not annotated with @nullable , non-nullability is still enforced at runtime during parceling (returning StatusCode::UNEXPECTED_NULL if the value is None ).

Начиная с Android 13, аннотация @nullable(heap=true) может использоваться для полей, допускающих последовательность `parcelable`, для моделирования рекурсивных типов. @nullable(heap=true) нельзя использовать с параметрами методов или возвращаемыми типами. При использовании этой аннотации поле сопоставляется с выделенной в куче ссылкой std::unique_ptr<T> в бэкендах C++ и NDK. @nullable(heap=true) не выполняет никаких действий в бэкенде Java.

utf8InCpp

utf8InCpp указывает, что String представлена ​​в формате UTF8 для бэкенда C++. Как следует из названия, для других бэкендов эта аннотация ничего не делает. В частности, String всегда имеет кодировку UTF16 в бэкенде Java и UTF8 в бэкенде NDK.

Эту аннотацию можно добавить везде, где используется тип String , включая возвращаемые значения, параметры, объявления констант и поля, допускающие последовательность операций.

Для бэкенда на C++ @utf8InCpp String в AIDL соответствует std::string , тогда как String без аннотации соответствует android::String16 где используется кодировка UTF16.

VintfStability

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

Аннотация UnsupportedAppUsage указывает на то, что аннотированный тип AIDL является частью интерфейса, не входящего в SDK, который был доступен для устаревших приложений. Дополнительную информацию о скрытых API см. в разделе «Ограничения на интерфейсы, не входящие в SDK» .

Аннотация UnsupportedAppUsage не влияет на поведение сгенерированного кода. Эта аннотация применяется только к сгенерированному 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, }

В бэкенде C++ это генерирует класс перечисления 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 помечает объявление (а не определение) типа Parcelable как стабильное, чтобы на него можно было ссылаться из других стабильных типов AIDL. Это похоже на JavaOnlyStableParcelable , но NdkOnlyStableParcelable помечает объявление типа Parcelable как стабильное для бэкенда NDK, а не для Java.

Для использования этой посылки:

  • Необходимо указать ndk_header .
  • Необходимо наличие библиотеки NDK, указывающей на возможность использования Parcelable, и эта библиотека должна быть скомпилирована в основную библиотеку. Например, в основной системе сборки модуля cc_* используйте static_libs или shared_libs . Для aidl_interface добавьте библиотеку в additional_shared_libraries в Android.bp .

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 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:

@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 позволяет аннотировать сгенерированный 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, эта аннотация ничего не делает.

RustDerive

RustDerive автоматически реализует трейты для сгенерированных типов Rust.

Для аннотации требуются дополнительные параметры, определяющие процесс генерации. Поддерживаемые параметры:

  • Copy=true
  • Clone=true
  • Ord=true
  • PartialOrd=true
  • Eq=true
  • PartialEq=true
  • Hash=true

Для получения пояснений к этим свойствам см. документацию Rust .

Фиксированный размер

FixedSize помечает структурированный объект Parcelable как объект фиксированного размера. После присвоения такой маркировки добавлять новые поля в Parcelable нельзя. Все поля объекта Parcelable должны быть типами фиксированного размера, включая примитивные типы, перечисления, массивы фиксированного размера и другие объекты Parcelable, помеченные FixedSize .

Объекты FixedSize имеют стабильные размеры и выравнивание в бэкенде ndk .

Тип Размер (байты) Выравнивание (байты)
boolean 1 1
byte 1 1
char 2 2
int 4 4
long 8 8
float 4 4
double 8 8
parcelable Общий размер всех полей Наибольшее выравнивание всех полей
union Самое большое поле из всех. Наибольшее выравнивание всех полей
enum Размер типа подложки Выравнивание типа подложки
T[N] (массив фиксированного размера) Размер T * N Выравнивание T
String, IBinder, FileDescriptor, ParcelFileDescriptor N/A N/A

Дескриптор

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.

@deprecated в комментариях

Компилятор AIDL распознает @deprecated в комментариях как тег, указывающий на сущность AIDL, которую больше не следует использовать:

interface IFoo {
  /** @deprecated use bar() instead */
  void foo();
  void bar();
}

Каждый бэкенд помечает устаревшие сущности аннотацией или атрибутом, специфичным для бэкенда, чтобы клиентский код получал предупреждение, если он ссылается на устаревшие сущности. Например, к сгенерированному Java-коду добавляются аннотация @Deprecated и тег @deprecated .

,

AIDL поддерживает аннотации, которые предоставляют компилятору AIDL дополнительную информацию об аннотируемом элементе, что также влияет на сгенерированный код-заглушку.

Синтаксис похож на синтаксис Java:

@AnnotationName(argument1=value, argument2=value) AidlEntity

Здесь AnnotationName — это имя аннотации, а AidlEntity — это сущность AIDL, например, interface Foo , void method() или int arg . К следующей за ней сущности прикрепляется аннотация.

Некоторые аннотации могут иметь аргументы, заданные внутри скобок, как показано в предыдущем примере. Аннотации, не имеющие аргументов, не нуждаются в скобках. Например:

@AnnotationName AidlEntity

Эти аннотации отличаются от аннотаций Java, хотя и выглядят похоже. Все аннотации предопределены и имеют ограничения по месту их применения. Некоторые аннотации влияют только на определенный бэкенд и не оказывают никакого воздействия на другие бэкенды.

Вот список предопределенных аннотаций 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 указывает, что значение аннотированного объекта может быть равно null.

Эту аннотацию можно добавлять только к типам возвращаемых значений методов, параметрам методов и полям, допускающим разделение по категориям:

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 .

В бэкенде C++ директива ` @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 или ниже).

There is an exception to this mapping. When T is IBinder or an AIDL interface, @nullable is a no-op for the Java, CPP, and NDK backends. For example, in the CPP backend, both @nullable IBinder and IBinder equally map to android::sp<IBinder> , which is already nullable because it is a strong pointer (CPP and NDK reads still enforce nullability, but the type remains android::sp<IBinder> or ndk::SpAIBinder ).

В бэкенде Rust типы, не реализующие Default ( IBinder , интерфейсы AIDL, ParcelFileDescriptor и неструктурированные парселируемые объекты), отображаются на Option<T> в зависимости от контекста:

  • Типы возвращаемых значений методов, in параметры и inout параметры: эти типы допускают значение null только в том случае, если они аннотированы @nullable , что соответствует Option<T> (или Option<&T> для in параметров и &mut Option<T> для inout параметров). Без @nullable они напрямую соответствуют T (или &T и &mut T ).
  • Parcelable fields and out parameters: Because generated Rust parcelables derive Default and out parameters are default-initialized, these types always map to Option<T> (and fixed-size arrays in these contexts map to [Option<T>; N] , while dynamic arrays in out parameters map to Vec<Option<T>> ), even without @nullable . When not annotated with @nullable , non-nullability is still enforced at runtime during parceling (returning StatusCode::UNEXPECTED_NULL if the value is None ).

Начиная с Android 13, аннотация @nullable(heap=true) может использоваться для полей, допускающих последовательность `parcelable`, для моделирования рекурсивных типов. @nullable(heap=true) нельзя использовать с параметрами методов или возвращаемыми типами. При использовании этой аннотации поле сопоставляется с выделенной в куче ссылкой std::unique_ptr<T> в бэкендах C++ и NDK. @nullable(heap=true) не выполняет никаких действий в бэкенде Java.

utf8InCpp

utf8InCpp указывает, что String представлена ​​в формате UTF8 для бэкенда C++. Как следует из названия, для других бэкендов эта аннотация ничего не делает. В частности, String всегда имеет кодировку UTF16 в бэкенде Java и UTF8 в бэкенде NDK.

Эту аннотацию можно добавить везде, где используется тип String , включая возвращаемые значения, параметры, объявления констант и поля, допускающие последовательность операций.

Для бэкенда на C++ @utf8InCpp String в AIDL соответствует std::string , тогда как String без аннотации соответствует android::String16 где используется кодировка UTF16.

VintfStability

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

Аннотация UnsupportedAppUsage указывает на то, что аннотированный тип AIDL является частью интерфейса, не входящего в SDK, который был доступен для устаревших приложений. Дополнительную информацию о скрытых API см. в разделе «Ограничения на интерфейсы, не входящие в SDK» .

Аннотация UnsupportedAppUsage не влияет на поведение сгенерированного кода. Эта аннотация применяется только к сгенерированному 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, }

В бэкенде C++ это генерирует класс перечисления 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 помечает объявление (а не определение) типа Parcelable как стабильное, чтобы на него можно было ссылаться из других стабильных типов AIDL. Это похоже на JavaOnlyStableParcelable , но NdkOnlyStableParcelable помечает объявление типа Parcelable как стабильное для бэкенда NDK, а не для Java.

Для использования этой посылки:

  • Необходимо указать ndk_header .
  • Необходимо наличие библиотеки NDK, указывающей на возможность использования Parcelable, и эта библиотека должна быть скомпилирована в основную библиотеку. Например, в основной системе сборки модуля cc_* используйте static_libs или shared_libs . Для aidl_interface добавьте библиотеку в additional_shared_libraries в Android.bp .

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 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:

@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 позволяет аннотировать сгенерированный 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, эта аннотация ничего не делает.

RustDerive

RustDerive автоматически реализует трейты для сгенерированных типов Rust.

Для аннотации требуются дополнительные параметры, определяющие процесс генерации. Поддерживаемые параметры:

  • Copy=true
  • Clone=true
  • Ord=true
  • PartialOrd=true
  • Eq=true
  • PartialEq=true
  • Hash=true

Для получения пояснений к этим свойствам см. документацию Rust .

Фиксированный размер

FixedSize помечает структурированный объект Parcelable как объект фиксированного размера. После присвоения такой маркировки добавлять новые поля в Parcelable нельзя. Все поля объекта Parcelable должны быть типами фиксированного размера, включая примитивные типы, перечисления, массивы фиксированного размера и другие объекты Parcelable, помеченные FixedSize .

FixedSize objects have stable sizes and alignements in the ndk backend.

Тип Размер (байты) Alignment (bytes)
boolean 1 1
byte 1 1
char 2 2
int 4 4
long 8 8
float 4 4
double 8 8
parcelable Total size of all fields Largest alignment of all fields
union Largest size of all fields Largest alignment of all fields
enum Size of backing type Alignment of backing type
T[N] (fixed-size array) Size of T * N Alignment of T
String, IBinder, FileDescriptor, ParcelFileDescriptor N/A N/A

Дескриптор

Descriptor forcibly specifies the interface descriptor of an interface:

package android.foo;

@Descriptor(value="android.bar.IWorld")
interface IHello {...}

The descriptor of this interface is android.bar.IWorld . If the Descriptor annotation is missing, the descriptor would be android.foo.IHello .

This is useful for renaming an already published interface. Making the descriptor of the renamed interface the same as the descriptor of the interface before the renaming allows the two interfaces to talk to each other.

@hide in comments

The AIDL compiler recognizes @hide in comments and passes it through to Java output for metalava to pickup. This comment helps ensure that the Android build system recognizes that AIDL APIs aren't SDK APIs.

@deprecated in comments

The AIDL compiler recognizes @deprecated in comments as a tag to identify an AIDL entity that should no longer be used:

interface IFoo {
  /** @deprecated use bar() instead */
  void foo();
  void bar();
}

Each backend marks deprecated entities with a backend-specific annotation or attribute so that the client code is warned if it refers the deprecated entities. For example, the @Deprecated annotation and the @deprecated tag are attached to the Java generated code.