El HIDL se basa en interfaces, un tipo abstracto que se usa en interfaces lenguajes de programación para definir los comportamientos. Cada interfaz es parte de un paquete.
Paquetes
Los nombres de paquetes pueden tener subniveles, como package.subpackage
. El
el directorio raíz de los paquetes HIDL publicados es hardware/interfaces
o vendor/vendorName
(por ejemplo, vendor/google
para Pixel
dispositivos). El nombre del paquete forma uno o más subdirectorios debajo de la raíz
directory; Todos los archivos que definen un paquete están en el mismo directorio. Por ejemplo:
Se encontró package android.hardware.example.extension.light@2.0
por debajo de hardware/interfaces/example/extension/light/2.0
.
En la siguiente tabla, se enumeran las ubicaciones y los prefijos de los paquetes:
Prefijo del paquete | Ubicación | Tipos de interfaz |
---|---|---|
android.hardware.* |
hardware/interfaces/* |
HAL |
android.frameworks.* |
frameworks/hardware/interfaces/* |
marcos de trabajo/ relacionados |
android.system.* |
system/hardware/interfaces/* |
sistema/ relacionado |
android.hidl.* |
system/libhidl/transport/* |
core |
El directorio del paquete contiene archivos con extensión .hal
. Cada
debe contener una sentencia package
en la que se mencione el paquete
versión de la que forma parte el archivo. El archivo types.hal
, si está presente, no
no definen una interfaz, sino que definen los tipos de datos a los que pueden acceder
en el paquete.
Definición de interfaz
Además de types.hal
, todos los demás archivos .hal
definen
una interfaz. Por lo general, una interfaz se define de la siguiente manera:
interface IBar extends IFoo { // IFoo is another interface // embedded types struct MyStruct {/*...*/}; // interface methods create(int32_t id) generates (MyStruct s); close(); };
Una interfaz sin una declaración extends
explícita de forma implícita
se extiende desde android.hidl.base@1.0::IBase
(similar a
java.lang.Object
en Java). La interfaz IBase, implícitamente
importado, declara varios métodos reservados que no deben ni pueden
volver a declararse en interfaces definidas por el usuario o usarse de alguna otra forma. Estos métodos
incluyen:
ping
interfaceChain
interfaceDescriptor
notifySyspropsChanged
linkToDeath
unlinkToDeath
setHALInstrumentation
getDebugInfo
debug
getHashChain
Proceso de importación
La sentencia import
es un mecanismo HIDL para acceder al paquete
interfaces y tipos en otro paquete. Una sentencia import
se preocupa por dos entidades:
- La entidad de importación, que puede ser un paquete o interfaz
- Es la entidad imported, que puede ser un paquete o interfaz
La entidad de importación está determinada por la ubicación de la
import
. Cuando la sentencia está dentro del directorio
types.hal
, lo que se está importando es visible para todo el paquete.
Esta es una importación a nivel del paquete. Cuando la sentencia está dentro de
archivo de interfaz, la entidad importada es la propia interfaz; este es un
Importación a nivel de interfaz.
La entidad importada está determinada por el valor después de import
palabra clave. No es necesario que el valor sea un nombre completamente calificado. Si un componente
se omite, se completa automáticamente con información del paquete actual.
Para valores completamente calificados, se admiten los siguientes casos de importación:
- Importaciones de todo el paquete. Si el valor es un nombre de paquete y un (sintaxis descrita a continuación), entonces, se importa todo el paquete al importada.
- Importaciones parciales. Si el valor es el siguiente:
- Una interfaz, el
types.hal
del paquete y esa interfaz son importada a la entidad importada. - Una UDT definida en
types.hal
, solo se importa esa UDT en la entidad de importación (no se importan otros tipos entypes.hal
)
- Una interfaz, el
- Importaciones de solo tipos. Si el valor usa la sintaxis de una
importación parcial descrita anteriormente, pero con la palabra clave
types
en su lugar de un nombre de interfaz, solo las UDT entypes.hal
de la el paquete se importaron.
La entidad importadora obtiene acceso a una combinación de lo siguiente:
- Las UDT comunes del paquete importado que se definen en
types.hal
- Las interfaces del paquete importado (para una importación de paquete completo) o valores especificados (para una importación parcial) con el fin de invocarlos, pasarlos o los que hereda de ellos.
La sentencia de importación usa la sintaxis de nombre de tipo completamente calificado para proporcionar la nombre y versión del paquete o la interfaz que se importa:
import android.hardware.nfc@1.0; // import a whole package import android.hardware.example@1.0::IQuux; // import an interface and types.hal import android.hardware.example@1.0::types; // import just types.hal
Herencia de la interfaz
Una interfaz puede ser una extensión de una interfaz definida previamente. Las extensiones pueden ser de uno de estos tres tipos:
- La interfaz puede agregar funcionalidad a otra, incorporando su API sin cambios.
- El paquete puede agregar funcionalidad a otra mediante la incorporación de su API sin cambios.
- Puede importar tipos de un paquete o de una interfaz específica.
Una interfaz puede extender solo una interfaz más (sin herencia múltiple).
Cada interfaz en un paquete con un número de versión secundario distinto de cero debe extender un
de la versión anterior del paquete. Por ejemplo, si una interfaz
IBar
en la versión 4.0 del paquete derivative
se basa en
(extiende) una interfaz IFoo
en la versión 1.2 del paquete
original
y la versión 1.3 del paquete original
es
creado, la versión 4.1 de IBar
no puede extender la versión 1.3 de
IFoo
En cambio, la versión 4.1 de IBar
debe extender
Versión 4.0 de IBar
, que está vinculada a la versión 1.2 de IFoo
.
La versión 5.0 de IBar
podría extender la versión 1.3 de IFoo
si
deseado.
Las extensiones de interfaz no implican la dependencia de bibliotecas ni la inclusión entre HAL. en el código generado; solo importan la estructura de datos y el método en el nivel del HIDL. Cada método en una HAL debe implementarse en ese HAL.
Extensiones de proveedores
En algunos casos, las extensiones de proveedores se implementan como una subclase del un objeto base que representa la interfaz principal que extienden. El mismo objeto se registrados con el nombre y la versión de la HAL de base y el nombre Nombre y versión de la HAL (proveedor).
Control de versiones
Los paquetes tienen control de versiones, y las interfaces tienen la versión de su paquete. Las versiones se expresan en dos números enteros, mayor.menor.
- Las versiones principales no son retrocompatibles. Incrementando el número de versión principal restablece el número de versión secundario a 0.
- Las versiones secundarias son retrocompatibles. Aumentar el un número menor indica que la versión más reciente es totalmente retrocompatible con el versión anterior. Se pueden agregar nuevas estructuras de datos y métodos, pero no hay las estructuras de datos o las firmas de métodos pueden cambiar.
Puede haber varias versiones principales o secundarias de una HAL en un dispositivo al mismo tiempo. Sin embargo, se debe preferir una versión secundaria en lugar de una principal porque el código del cliente que funciona con una interfaz de versión secundaria anterior funciona con versiones secundarias posteriores de esa misma interfaz. Para ver más sobre el control de versiones y las extensiones de proveedores, consulta Control de versiones HIDL
Resumen del diseño de la interfaz
Esta sección resume cómo administrar un paquete de interfaz HIDL (como
hardware/interfaces
) y consolida la información presentada.
en toda la sección de HIDL. Antes de leer, asegúrate de familiarizarte con
Control de versiones de HIDL
la codificación hash con
conceptos de hidl-gen y los detalles para trabajar con
HIDL en general y las siguientes definiciones:
Término | Definición |
---|---|
interfaz binaria de la aplicación (ABI) | Interfaz de programación de aplicaciones más las vinculaciones binarias necesarias. |
nombre completamente calificado (fqName) | Nombre para distinguir un tipo hidl. Ejemplo:
android.hardware.foo@1.0::IFoo |
paquete | Paquete que contiene una interfaz HIDL y tipos. Ejemplo:
android.hardware.foo@1.0 |
raíz del paquete | Paquete raíz que contiene las interfaces HIDL. Ejemplo: la interfaz HIDL
android.hardware está en la raíz del paquete.
android.hardware.foo@1.0 |
ruta raíz del paquete | Ubicación en el árbol de fuentes de Android a la que se asigna la raíz de un paquete. |
Consulta más definiciones en HIDL. Terminología
Todos los archivos se pueden encontrar desde la asignación raíz del paquete y su nombre completamente calificado
Las raíces del paquete se especifican en hidl-gen
como argumento.
-r android.hardware:hardware/interfaces
Por ejemplo, si el
el paquete es vendor.awesome.foo@1.0::IFoo
y hidl-gen
se envía el -r vendor.awesome:some/device/independent/path/interfaces
,
entonces el archivo de interfaz debería estar ubicado en
$ANDROID_BUILD_TOP/some/device/independent/path/interfaces/foo/1.0/IFoo.hal
En la práctica, se recomienda para un OEM o proveedor llamado awesome
.
para colocar sus interfaces estándar en vendor.awesome
. Después de un paquete
de la ruta de acceso seleccionada, no debes cambiarla, ya que está integrada en la ABI de
la interfaz.
La asignación de la ruta del paquete debe ser única
Por ejemplo, si tienes -rsome.package:$PATH_A
y
-rsome.package:$PATH_B
, $PATH_A
debe ser igual a
$PATH_B
para un directorio de interfaz coherente (esto también hace que
interfaces con control de versiones
más fácil).
La raíz del paquete debe tener un archivo de control de versiones
Si creas una ruta de paquete como
-r vendor.awesome:vendor/awesome/interfaces
, también deberías
crea el archivo
$ANDROID_BUILD_TOP/vendor/awesome/interfaces/current.txt
, que
debe contener hashes de interfaces creadas con la opción -Lhash
en
hidl-gen
(esto se analiza detalladamente en
Hash con
hidl-gen).
Las interfaces son independientes del dispositivo ubicaciones
En la práctica, recomendamos compartir interfaces entre ramas. Esta permite reutilizar el código al máximo y realizar la prueba máxima del código en diferentes dispositivos y casos de uso.