Anotações na AIDL

A AIDL oferece suporte a anotações que dão ao compilador AIDL informações extras sobre o elemento anotado, o que também afeta o código stub gerado.

A sintaxe é semelhante à do Java:

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

Aqui, AnnotationName é o nome da anotação e AidlEntity é uma entidade AIDL, como interface Foo, void method() ou int arg. Um é anexada à entidade que a segue.

Algumas anotações podem ter argumentos definidos entre parênteses, como mostrado acima. Anotações que não têm um argumento não precisam de parênteses. Exemplo:

@AnnotationName AidlEntity

Essas anotações não são iguais às anotações, embora sejam muito semelhantes. Os usuários não podem definir a AIDL personalizada anotações todas as anotações são predefinidas. Algumas anotações afetam apenas de um determinado back-end e são autônomos em outros. Eles têm diferentes restrições em que podem ser anexados.

Confira a lista de anotações AIDL predefinidas:

Anotações Adicionado à versão do 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

anulável

nullable declara que o valor da entidade anotada pode não ser fornecido.

Essa anotação só pode ser anexada a tipos de retorno, parâmetros de método e parcelable.

interface IFoo {
    // method return types
    @nullable Data method();

    // method parameters
    void method2(in @nullable Data d);
}

parcelable Data {
    // parcelable fields
    @nullable Data d;
}

Anotações não podem ser anexadas a tipos primitivos. Veja a seguir um erro.

void method(in @nullable int a); // int is a primitive type

Essa anotação não opera para o back-end Java. Isso porque, em Java, tipos não primitivos são transmitidos por referência, que pode ser null.

No back-end do CPP, @nullable T é mapeado para std::unique_ptr<T> no Android. 11 ou anterior e para std::optional<T> no Android 12 ou superior.

No back-end do NDK, @nullable T sempre é mapeado para std::optional<T>.

Para um tipo de lista L, como T[] ou List<T>, @nullable L é mapeado para std::optional<std::vector<std::optional<T>>> (ou std::unique_ptr<std::vector<std::unique_ptr<T>>> no caso do back-end de CPP para o Android 11 ou versões anteriores).

Há uma exceção nesse mapeamento. Quando T é IBinder ou uma interface AIDL, @nullable é um ambiente autônomo. Em outras palavras, tanto @nullable IBinder e IBinder mapeiam igualmente para android::sp<IBinder>, que já é anulável porque é um ponteiro forte (o CPP lê aplicar a nulidade, mas o tipo ainda é android::sp<IBinder>).

A partir do Android 13, a @nullable(heap=true) pode ser usada para Campos parcelable para modelar tipos recursivos. Não é possível usar @nullable(heap=true) com parâmetros de método ou tipos de retorno. Quando anotado com ele, o campo é mapeado para uma referência std::unique_ptr<T> alocada por heap no CPP/NDK back-ends de aplicativos. @nullable(heap=true) é um ambiente autônomo no back-end Java.

utf8InCpp

utf8InCpp declara que um String é representado no formato UTF8 para o CPP. back-end. Como o nome indica, a anotação é um ambiente autônomo para outros back-ends. Especificamente, String é sempre UTF16 no back-end do Java e UTF8 no NDK. back-end.

Essa anotação pode ser anexada em qualquer lugar em que o tipo String possa ser usado. incluindo valores de retorno, parâmetros, declarações constantes e parcelable campos.

Para o back-end do CPP, @utf8InCpp String na AIDL é mapeado para std::string, enquanto String sem a anotação é mapeado para android::String16, em que UTF16 é usado.

A existência da anotação utf8InCpp não muda a maneira como as strings são transmitidas pelos fios. Strings sempre são transmitidas como UTF16 pelos fios. Uma string com a anotação utf8InCpp é convertida em UTF16 antes de ser transmitidos. Quando uma string é recebida, ela é convertida de UTF16 para UTF8, foi anotado como utf8InCpp.

VintfStability

VintfStability declara que um tipo definido pelo usuário (interface, parcelable, e enum) podem ser usadas nos domínios do sistema e do fornecedor. Consulte AIDL para HALs para saber mais sobre e a interoperabilidade entre sistema e fornecedor.

A anotação não altera a assinatura do tipo, mas, quando é definida, a instância do tipo é marcada como estável para que possa viajar do fornecedor e dos processos do sistema.

A anotação só pode ser anexada a declarações de tipo definidas pelo usuário, conforme mostrado aqui:

@VintfStability
interface IFoo {
    ....
}

@VintfStability
parcelable Data {
    ....
}

@VintfStability
enum Type {
    ....
}

Quando um tipo é anotado com VintfStability, qualquer outro tipo que seja referenciados no tipo também precisam ser anotados dessa forma. Nos seguintes exemplo, Data e IBar precisam ser anotados com 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 {...}

Além disso, os arquivos AIDL que definem os tipos anotados com VintfStability só pode ser criado usando o tipo de módulo Soong aidl_interface, com o A propriedade stability foi definida como "vintf".

aidl_interface {
    name: "my_interface",
    srcs: [...],
    stability: "vintf",
}

Uso não aceito no app

A anotação UnsupportedAppUsage indica que o tipo AIDL com anotação é parte da interface externa ao SDK acessível a apps legados. Consulte Restrições para produtos que não são do SDK interfaces para mais informações sobre as APIs ocultas.

A anotação UnsupportedAppUsage não afeta o comportamento do código gerado. A anotação anota apenas a classe Java gerada com o Java com o mesmo nome.

// in AIDL
@UnsupportedAppUsage
interface IFoo {...}

// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}

Este é um ambiente autônomo para back-ends não Java.

Apoio

A anotação Backing especifica o tipo de armazenamento de um tipo de enumeração AIDL.

@Backing(type="int")
enum Color { RED, BLUE, }

No back-end do CPP, isso emite uma classe de enumeração C++ do tipo int32_t.

enum class Color : int32_t {
    RED = 0,
    BLUE = 1,
}

Se a anotação for omitida, o type será considerado byte, que mapeia para int8_t no back-end de CPP.

O argumento type pode ser definido apenas para os seguintes tipos de integrais:

  • byte (8 bits de largura)
  • int (32 bits de largura)
  • long (64 bits de largura)

NdkOnlyStableParcelable

NdkOnlyStableParcelable marca uma declaração fracionável (não definição). como estável para que possa ser referenciado de outros tipos de AIDL estáveis. Isso é como JavaOnlyStableParcelable, mas NdkOnlyStableParcelable marca uma declaração parcelable como estável para o NDK. em vez de para Java.

Para usar o parcelable:

  • É necessário especificar ndk_header.
  • Você precisa ter uma biblioteca do NDK especificando o parcelable, e a biblioteca precisa ser compilado na biblioteca. Por exemplo, no sistema de build principal em um cc_*, use static_libs ou shared_libs. Para aidl_interface, adicione a biblioteca em additional_shared_libraries em Android.bp.

JavaOnlyStableParcelable

JavaOnlyStableParcelable marca uma declaração fracionável (não definição). como estável para que possa ser referenciado de outros tipos de AIDL estáveis.

A AIDL estável exige que todos os tipos definidos pelo usuário sejam estáveis. Para parcelables, a estabilidade requer que os campos sejam descritos explicitamente em o arquivo de origem 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
}

Se o parcelable não foi estruturado (ou acabou de ser declarado), ele não poderá ser referenciadas.

parcelable Data; // Data is NOT a structured parcelable

parcelable AnotherData {
    Data d; // Error
}

JavaOnlyStableParcelable permite substituir a verificação quando o parcelable já está disponível com segurança como parte do SDK do Android.

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

JavaDerive

O JavaDerive gera automaticamente métodos para tipos fracionáveis no back-end do Java.

@JavaDerive(equals = true, toString = true)
parcelable Data {
  int number;
  String str;
}

A anotação requer parâmetros adicionais para controlar o que gerar. Os parâmetros aceitos são:

  • equals=true gera os métodos equals e hashCode.
  • toString=true gera um método toString que mostra o nome do tipo e campos. Por exemplo: Data{number: 42, str: foo}

Padrão Java

A JavaDefault, adicionada no Android 13, controla se o suporte de controle de versão de implementação padrão é gerado (para setDefaultImpl). Esse suporte não é mais gerado por padrão para para economizar espaço.

JavaPassthrough

JavaPassthrough permite que a API Java gerada seja anotada com uma anotação Anotação Java.

As seguintes anotações na AIDL

@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")

se tornar

@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)

no código Java gerado.

O valor do parâmetro annotation é emitido diretamente. A AIDL não analisa o valor do parâmetro. Se houver Erro de sintaxe no nível do Java, não será capturado pelo compilador AIDL, mas pelo Compilador Java.

Essa anotação pode ser anexada a qualquer entidade AIDL. Esta anotação é um ambiente autônomo para back-ends não Java.

Tamanho fixo

FixedSize marca um parcelable estruturado como tamanho fixo. Uma vez marcada, a A parcelable não poderá ter novos campos adicionados a ela. Todos os campos de o parcelable também precisa ter tipos de tamanho fixos, incluindo tipos primitivos, tipos enumerados, matrizes de tamanho fixo e outros parcelables marcados com FixedSize.

Isso não fornece nenhuma garantia para diferentes bits e não deve ser muito usados para comunicação de bits mistas.

Descritor

Descriptor especifica à força o descritor de uma interface.

package android.foo;

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

O descritor dessa interface é android.bar.IWorld. Se o A anotação Descriptor está ausente. O descritor seria: android.foo.IHello.

Isso é útil para renomear uma interface já publicada. Fazer o descritor da interface renomeada igual ao descritor da interface antes da renomeação permite que as duas interfaces se comuniquem.

@ocultar nos comentários

O compilador AIDL reconhece @hide nos comentários e o transmite para saída Java para metalava para retirada. Esse comentário garante que o ambiente sistema de build sabe que as APIs AIDL não são APIs do SDK.

@descontinuado nos comentários

O compilador AIDL reconhece @deprecated nos comentários como uma tag para identificar uma Entidade AIDL que não deve mais ser usada.

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

Cada back-end marca as entidades descontinuadas com uma anotação específica do back-end ou para que o código do cliente seja avisado caso se refira à entidades. Por exemplo, a anotação @Deprecated e o @deprecated são anexadas ao código gerado em Java.