El lenguaje AIDL se basa libremente en el lenguaje Java. Los archivos especifican un contrato de interfaz y varios tipos de datos y constantes utilizados en este contrato.
Paquete
Cada archivo AIDL comienza con un paquete opcional que corresponde a los nombres de los paquetes en varios servidores. Una declaración de paquete se ve así:
package my.package;
Al igual que en Java, los archivos AIDL deben estar en una estructura de carpetas que coincida con su paquete. Los archivos con el paquete my.package
deben estar en la carpeta my/package/
.
Tipos
En los archivos AIDL, hay muchos lugares donde se pueden especificar tipos. Para obtener una lista exacta de los tipos admitidos en el lenguaje AIDL, consulte Tipos de backends AIDL .
Anotaciones
Varias partes del lenguaje AIDL admiten anotaciones. Para obtener una lista de anotaciones y dónde se pueden aplicar, consulte Anotaciones AIDL .
Importaciones
Para utilizar tipos definidos en otras interfaces, primero debe agregar dependencias en el sistema de compilación. En los módulos cc_*
y java_*
Soong, donde los archivos .aidl
se usan directamente bajo srcs
en las compilaciones de la plataforma Android, puede agregar directorios usando el campo aidl: { include_dirs: ... }
. Para importaciones utilizando aidl_interface
, consulte aquí .
Una importación se ve así:
import some.package.Foo; // explicit import
Al importar un tipo en el mismo paquete, se puede omitir el paquete. Sin embargo, omitir el paquete puede generar errores de importación ambiguos cuando los tipos se especifican sin un paquete y se colocan en el espacio de nombres global (generalmente todos los tipos deben tener un espacio de nombres):
import Foo; // same as my.package.Foo
Definición de tipos
Los archivos AIDL generalmente definen tipos que se utilizan como interfaz.
Interfaces
Aquí hay un ejemplo de interfaz AIDL:
interface ITeleport {
void teleport(Location baz, float speed);
String getName();
}
Una interfaz define un objeto con una serie de métodos. Los métodos pueden ser oneway
( oneway void doFoo()
) o sincrónicos. Si una interfaz se define como oneway
( oneway interface ITeleport {...}
), entonces todos los métodos que contiene son implícitamente oneway
. Los métodos unidireccionales se envían de forma asincrónica y no pueden devolver un resultado. También se garantiza que los métodos unidireccionales del mismo subproceso al mismo cuaderno se ejecuten en serie (aunque potencialmente en subprocesos diferentes). Para obtener información sobre cómo configurar subprocesos, consulte Gestión de subprocesos de backends de AIDL .
Los métodos pueden tener cero o más argumentos. Los argumentos de los métodos pueden ser in
, out
o inout
. Para obtener una explicación sobre cómo esto afecta los tipos de argumentos, consulte Direccionalidad de los backends de AIDL .
Parcelables
Para obtener una descripción de cómo crear parcelables específicos de backend, AIDL backends parcelables personalizados .
Android 10 y versiones posteriores admiten definiciones parcelables directamente en AIDL. Este tipo de parcelable se denomina parcelable estructurado. Para obtener más información sobre cómo se relacionan AIDL estructurado y estable en el compilador AIDL y nuestro sistema de compilación, consulte AIDL estructurado versus estable .
Por ejemplo:
package my.package;
import my.package.Boo;
parcelable Baz {
@utf8InCpp String name = "baz";
Boo boo;
}
Sindicatos
Android 12 y versiones posteriores admiten declaraciones sindicales. Por ejemplo:
package my.package;
import my.package.FooSettings;
import my.package.BarSettings;
union Settings {
FooSettings fooSettings;
BarSettings barSettings;
@utf8InCpp String str;
int number;
}
Enumeraciones
Android 11 y versiones posteriores admiten declaraciones de enumeración. Por ejemplo:
package my.package;
enum Boo {
A = 1 * 4,
B = 3,
}
Declaraciones de tipo anidadas
Android 13 y versiones posteriores admiten declaraciones de tipos anidados. Por ejemplo:
package my.package;
import my.package.Baz;
interface IFoo {
void doFoo(Baz.Nested nested); // defined in my/package/Baz.aidl
void doBar(Bar bar); // defined below
parcelable Bar { ... } // nested type definition
}
Constantes
Las interfaces, parcelables y uniones AIDL personalizadas también pueden contener constantes enteras y de cadena, como por ejemplo:
const @utf8InCpp String HAPPY = ":)";
const String SAD = ":(";
const byte BYTE_ME = 1;
const int ANSWER = 6 * 7;
Expresiones constantes
Las constantes AIDL, los tamaños de matrices y los enumeradores se pueden especificar mediante expresiones constantes. Las expresiones pueden utilizar paréntesis para anidar operaciones. Los valores de expresión constante se pueden utilizar con valores integrales o flotantes.
Los literales true
y false
representan valores booleanos. Valores con .
pero sin sufijo, como 3.8
, se consideran valores dobles. Los valores flotantes tienen el sufijo f
, como 2.4f
. Un valor integral con el sufijo l
o L
indica un valor de 64 bits de longitud. De lo contrario, los valores integrales obtienen el tipo con signo más pequeño que conserva el valor entre 8 bits (byte), 32 bits (int) y 64 bits (long). Entonces, 256
se considera un int
, pero 255 + 1
se desborda y es el byte
0
. Los valores hexadecimales, como 0x3
, se interpretan primero como el tipo sin signo que conserva el valor más pequeño entre 32 y 64 bits y luego se reinterpretan como valores sin signo. Entonces, 0xffffffff
tiene el valor int
-1
. A partir de Android 13, el sufijo u8
se puede agregar a constantes, como 3u8
, para representar un valor byte
. Este sufijo es importante para que un cálculo, como 0xffu8 * 3
, se interprete como -3
con tipo byte
mientras que 0xff * 3
es 765
con tipo int
.
Los operadores admitidos tienen semántica de C++ y Java. En orden de menor a mayor prioridad, los operadores binarios son || && | ^ & == != < > <= >= << >> + - * / %
. Los operadores unarios son + - ! ~
.