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=true
gera métodosequals
ehashCode
. -
toString=true
gera o métodotoString
que 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.