AIDL oferece suporte a 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 colocados entre parênteses, conforme mostrado acima. Anotações que não possuem argumento não precisam de parênteses. Por exemplo:
@AnnotationName AidlEntity
Essas anotações não são iguais às anotações Java, embora sejam muito semelhantes. Os usuários não podem definir anotações AIDL personalizadas; as anotações são todas predefinidas. Algumas anotações afetam apenas um determinado back-end e não funcionam em outros back-ends. Eles têm diferentes restrições onde podem ser anexados.
Abaixo está a lista de anotações AIDL predefinidas:
Anotações | Adicionado na versão 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 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 parcelados.
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 funciona para o back-end Java. Isso porque, em Java, todos os tipos não primitivos são passados por referência, que poderia ser null
.
No back-end do 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 L
semelhante a uma lista, 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
é autônomo. Em outras palavras, @nullable IBinder
e IBinder
mapeiam igualmente para android::sp<IBinder>
, que já é anulável porque é um ponteiro forte (as leituras do CPP ainda impõem nulidade, mas o tipo ainda é android::sp<IBinder>
).
A partir do Android 13, @nullable(heap=true)
pode ser usado para campos parcelados 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 em heap std::unique_ptr<T>
nos back-ends CPP/NDK. @nullable(heap=true)
não funciona no back-end Java.
utf8InCpp
utf8InCpp
declara que uma String
é representada no formato UTF8 para o backend CPP. Como o próprio nome indica, a anotação não funciona para outros back-ends. Especificamente, String
é sempre UTF16 no backend Java e UTF8 no backend NDK.
Essa 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 parcelados.
Para o backend 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 pela rede. As strings são sempre transmitidas como UTF16 pela rede. 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
.
VintfEstabilidade
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 entre fornecedores de sistemas.
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 pelos 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 tipos anotados com VintfStability
só podem ser construídos usando o tipo de módulo aidl_interface
Soong, com a propriedade 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 está acessível para aplicativos legados. 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 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 backend CPP, o acima emite uma classe enum C++ do tipo int32_t
.
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
Se a anotação for omitida, o type
será assumido como byte
, que mapeia para int8_t
para o back-end do CPP.
O argumento type
pode ser definido apenas para os seguintes tipos integrais:
-
byte
(8 bits de largura) -
int
(largura de 32 bits) -
long
(largura de 64 bits)
NdkOnlyStableParcelável
NdkOnlyStableParcelable
marca uma declaração parcelavel (não uma definição) como estável para que possa ser referenciada a partir de outros tipos AIDL estáveis. É como JavaOnlyStableParcelable
, mas NdkOnlyStableParcelable
marca uma declaração parcelavel como estável para o back-end do NDK em vez de para Java.
Para usar este parcelable: * Você deve especificar ndk_header
. * Você deve ter uma biblioteca NDK especificando o parcelable e a biblioteca deve ser compilada na biblioteca. Por exemplo, no sistema de compilação principal em um módulo cc_*
, use static_libs
ou shared_libs
. Para aidl_interface
, adicione a biblioteca em additional_shared_libraries
em Android.bp
.
JavaOnlyStableParcelável
JavaOnlyStableParcelable
marca uma declaração parcelavel (não uma definição) como estável para que possa ser referenciada a partir de outros tipos AIDL estáveis.
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 fonte 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 for estruturado (ou apenas declarado), ele não poderá 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á estiver 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 parcelados 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}
JavaPadrão
JavaDefault
, adicionado no Android 13, 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)")
tornar-se
@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. O compilador AIDL não analisa o valor do parâmetro. Se houver algum erro de sintaxe no nível 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 é autônoma para back-ends não Java.
Tamanho fixo
FixedSize
marca um parcelamento estruturado como tamanho fixo. Uma vez marcado, o parcelavel não poderá ter novos campos adicionados. Todos os campos do parcelable também devem ser tipos de tamanho fixo, incluindo tipos primitivos, enums, matrizes de tamanho fixo e outros parcelables marcados com FixedSize
.
Isso não fornece 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 Descriptor
estiver faltando, o descritor será android.foo.IHello
.
Isto é ú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.
@ocultar nos comentários
O compilador AIDL reconhece @hide
nos comentários e passa-o para a saída Java para que o metalava seja coletado. Este comentário garante que o sistema de compilação do Android saiba que as APIs AIDL não são APIs SDK.
@depreciado 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 backend marca entidades obsoletas com uma anotação/atributo específico de backend para que o código do cliente seja avisado se fizer referência às entidades obsoletas. Por exemplo, a anotação @Deprecated
e a tag @deprecated
são anexadas ao código gerado em Java.