AIDL suporta anotações que fornecem 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 . Uma anotação é 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. Por exemplo:
@AnnotationName AidlEntity
Essas anotações não são iguais às anotações Java, embora pareçam muito semelhantes. Os usuários não podem definir anotações AIDL personalizadas; as anotações são todas pré-definidas. Algumas anotações afetam apenas um determinado back-end e são inoperantes em outros back-ends. Eles têm restrições diferentes onde podem ser anexados.
Abaixo está a lista de anotações AIDL pré-definidas:
| Anotações | Adicionado na versão Android |
|---|---|
nullable | 7 |
utf8InCpp | 7 |
VintfStability | 11 |
UnsupportedAppUsage | 10 |
Hide | 11 |
Backing | 11 |
JavaOnlyStableParcelable | 11 |
JavaDerive | 12 |
JavaPassthrough | 12 |
FixedSize | 12 |
Descriptor | 12 |
anulável
nullable declara que o valor da entidade anotada não pode ser fornecido.
Esta anotação só pode ser anexada a tipos de retorno de método, parâmetros de método e campos parcelable.
interface IFoo {
// method return types
@nullable Data method();
// method parameters
void method2(in @nullable Data d);
}
parcelable Data {
// parcelable fields
@nullable Data d;
}
As anotações não podem ser anexadas a tipos primitivos. O seguinte é um erro.
void method(in @nullable int a); // int is a primitive type
Esta anotação não é operacional para o back-end Java. Isso ocorre porque, em Java, todos os tipos não primitivos são passados por referência, que pode ser null .
No back-end CPP, @nullable T mapeia para std::unique_ptr<T> no Android 11 ou inferior e para std::optional<T> no Android 12 ou superior.
No back-end do NDK, @nullable T sempre mapeia para std::optional<T> .
Para um tipo de lista L , como T[] ou List<T> , @nullable L mapeia para std::optional<std::vector<std::optional<T>>> (ou std::unique_ptr<std::vector<std::unique_ptr<T>>> no caso do back-end CPP para Android 11 ou inferior).
Há uma exceção a esse mapeamento. Quando T é IBinder ou uma interface AIDL, @nullable é no-op. Em outras palavras, @nullable IBinder e IBinder igualmente mapeiam para android::sp<IBinder> , que já é anulável porque é um ponteiro forte (leituras CPP ainda impõem a nulidade, mas o tipo ainda é android::sp<IBinder> ).
Começando com o Android T (AOSP experimental), @nullable(heap=true) pode ser usado para campos parcelables para modelar tipos recursivos. @nullable(heap=true) não pode ser usado com parâmetros de método ou tipos de retorno. Quando anotado com ele, o campo é mapeado para uma referência alocada por heap std::unique_ptr<T> nos back-ends CPP/NDK. @nullable(heap=true) não é operacional no back-end Java.
utf8InCpp
utf8InCpp declara que uma String é representada no formato UTF8 para o back-end CPP. Como o próprio nome indica, a anotação não é operacional para outros back-ends. Especificamente, String é sempre UTF16 no backend Java e UTF8 no backend NDK.
Esta anotação pode ser anexada em qualquer lugar onde o tipo String possa ser usado, incluindo valores de retorno, parâmetros, declarações constantes e campos parcelable.
Para o back-end CPP, @utf8InCpp String em AIDL mapeia para std::string , enquanto String sem a anotação mapeia para android::String16 onde UTF16 é usado.
Observe que a existência da anotação utf8InCpp não altera a maneira como as strings são transmitidas pelo fio. Strings são sempre transmitidas como UTF16 pelo fio. Uma string anotada utf8InCpp é convertida em UTF16 antes de ser transmitida. Quando uma string é recebida, ela é convertida de UTF16 para UTF8 se tiver sido anotada como utf8InCpp .
Estabilidade Vintf
VintfStability declara que um tipo definido pelo usuário (interface, parcelable e enum) pode ser usado nos domínios do sistema e do fornecedor. Consulte AIDL para HALs para obter mais informações sobre a interoperabilidade do sistema com o 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 percorrer os processos do fornecedor e do sistema.
A anotação só pode ser anexada a declarações de tipo definidas pelo usuário, conforme mostrado abaixo:
@VintfStability
interface IFoo {
....
}
@VintfStability
parcelable Data {
....
}
@VintfStability
enum Type {
....
}
Quando um tipo é anotado com VintfStability , qualquer outro tipo referenciado no tipo também deve ser anotado como tal. No exemplo abaixo, Data e IBar devem 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ó podem ser construídos usando o tipo de módulo aidl_interface Soong, com a propriedade de stability definida como "vintf" .
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
Uso de aplicativo não suportado
A anotação UnsupportedAppUsage indica que o tipo AIDL anotado faz parte da interface não SDK que pode ser acessada por aplicativos herdados. Consulte Restrições em interfaces não SDK para obter mais informações sobre as APIs ocultas.
A anotação UnsupportedAppUsage não afeta o comportamento do código gerado. A anotação apenas anota a classe Java gerada com a anotação Java de mesmo nome.
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
Este é um não-op para back-ends não Java.
Apoio
A anotação de Backing especifica o tipo de armazenamento de um tipo de enumeração AIDL.
@Backing(type="int")
enum Color { RED, BLUE, }
No back-end CPP, o código acima 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 é mapeado para int8_t para o back-end CPP.
O argumento type pode ser definido apenas para os seguintes tipos integrais:
-
byte(8 bits de largura) -
int(32 bits de largura) -
long(largura de 64 bits)
JavaOnlyStableParcelable
JavaOnlyStableParcelable marca uma declaração parcelable (não definição) como estável para que possa ser referenciada de outros tipos AIDL estáveis.
O AIDL estável requer que todos os tipos definidos pelo usuário sejam estáveis. Para parcelables, ser estável requer que seus campos sejam explicitamente descritos no 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 apenas declarado), ele não pode ser referenciado.
parcelable Data; // Data is NOT a structured parcelable
parcelable AnotherData {
Data d; // Error
}
JavaOnlyStableParcelable permite substituir a verificação quando o parcelable que você está referenciando já está disponível com segurança como parte do Android SDK.
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
JavaDerive
JavaDerive gera automaticamente métodos para tipos parcelable no backend 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 suportados são:
-
equals=truegera métodosequalsehashCode. -
toString=truegera o métodotoStringque imprime o nome do tipo e dos campos. Por exemplo:Data{number: 42, str: foo}
JavaDefault
JavaDefault , adicionado no Android T (AOSP experimental), controla se o suporte de versão de implementação padrão é gerado (para setDefaultImpl ). Este suporte não é mais gerado por padrão para economizar espaço.
JavaPassthrough
JavaPassthrough permite que a API Java gerada seja anotada com uma anotação Java arbitrária.
As seguintes anotações em AIDL
@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")
vir a ser
@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)
no código Java gerado.
O valor do parâmetro de annotation é emitido diretamente. O compilador AIDL não analisa o valor do parâmetro. Se houver algum erro de sintaxe no nível do Java, ele não será detectado pelo compilador AIDL, mas pelo compilador Java.
Esta anotação pode ser anexada a qualquer entidade AIDL. Esta anotação não é operacional para back-ends não Java.
Tamanho fixo
FixedSize marca um parcelal estruturado como tamanho fixo. Uma vez marcado, o parcelable não poderá ter novos campos adicionados a ele. Todos os campos do parcelable também devem ser tipos de tamanho fixo, incluindo tipos primitivos, enums, arrays de tamanho fixo e outros parcelables marcados com FixedSize .
Isso não oferece nenhuma garantia em diferentes bits e não deve ser usado para comunicação de bits mistos.
Descritor
Descriptor especifica forçosamente o descritor de interface de uma interface.
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
O descritor da interface acima é android.bar.IWorld . Se a anotação do Descriptor estiver ausente, o descritor será android.foo.IHello .
Isso é útil para renomear uma interface já publicada. Tornar o descritor da interface renomeada igual ao descritor da interface antes da renomeação permite que as duas interfaces se comuniquem.
@esconder nos comentários
O compilador AIDL reconhece @hide nos comentários e o passa para a saída Java para o metalava coletar. Este comentário garante que o sistema de compilação do Android saiba que as APIs AIDL não são APIs do SDK.
@obsoleto 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 entidades obsoletas com uma anotação/atributo específico de back-end para que o código do cliente seja avisado se ele se referir às entidades obsoletas. Por exemplo, a anotação @Deprecated e a tag @deprecated são anexadas ao código gerado em Java.