HIDL se basa en interfaces, un tipo abstracto utilizado en lenguajes orientados a objetos para definir comportamientos. Cada interfaz es parte de un paquete.
Paquetes
Los nombres de los paquetes pueden tener subniveles, como package.subpackage
. El directorio raíz para los paquetes HIDL publicados es hardware/interfaces
o vendor/vendorName
(por ejemplo vendor/google
para dispositivos Pixel). El nombre del paquete forma uno o más subdirectorios bajo el directorio raíz; todos los archivos que definen un paquete están en el mismo directorio. Por ejemplo, el package android.hardware.example.extension.light@2.0
se puede encontrar en hardware/interfaces/example/extension/light/2.0
.
La siguiente tabla enumera los prefijos y las ubicaciones de los paquetes:
Prefijo de paquete | Ubicación | Tipos de interfaz |
---|---|---|
android.hardware.* | hardware/interfaces/* | HAL |
android.frameworks.* | frameworks/hardware/interfaces/* | marcos / relacionados |
android.system.* | system/hardware/interfaces/* | sistema/relacionado |
android.hidl.* | system/libhidl/transport/* | centro |
El directorio del paquete contiene archivos con extensión .hal
. Cada archivo debe contener una declaración de package
que nombre el paquete y la versión de la que forma parte el archivo. El archivo types.hal
, si está presente, no define una interfaz, sino que define los tipos de datos accesibles para todas las interfaces del paquete.
Definición de interfaz
Además de types.hal
, todos los demás archivos .hal
definen una interfaz. Una interfaz se define típicamente 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 extendida explícita implícitamente se extends
desde android.hidl.base@1.0::IBase
(similar a java.lang.Object
en Java). La interfaz IBase, implícitamente importada, declara varios métodos reservados que no deben y no pueden ser redeclarados en interfaces definidas por el usuario o utilizadas de otra manera. Estos métodos incluyen:
-
ping
-
interfaceChain
-
interfaceDescriptor
-
notifySyspropsChanged
-
linkToDeath
-
unlinkToDeath
-
setHALInstrumentation
-
getDebugInfo
-
debug
-
getHashChain
Importador
La declaración de import
es un mecanismo HIDL para acceder a las interfaces y tipos de paquetes en otro paquete. Una declaración de import
se refiere a dos entidades:
- La entidad importadora , que puede ser un paquete o una interfaz; y
- La entidad importada , que también puede ser un paquete o una interfaz.
La entidad importadora está determinada por la ubicación de la declaración de import
. Cuando la declaración está dentro del paquete types.hal
, lo que se importa es visible para todo el paquete; esta es una importación a nivel de paquete . Cuando la declaración está dentro de un archivo de interfaz, la entidad importadora es la propia interfaz; esta es una importación a nivel de interfaz .
La entidad importada está determinada por el valor después de la palabra clave de import
. No es necesario que el valor sea un nombre completo; si se omite un componente, se completa automáticamente con información del paquete actual. Para valores totalmente calificados, se admiten los siguientes casos de importación:
- Importaciones de paquete completo . Si el valor es un nombre de paquete y una versión (sintaxis descrita a continuación), el paquete completo se importa a la entidad de importación.
- Importaciones parciales . Si el valor es:
- Una interfaz, los
types.hal
del paquete y esa interfaz se importan a la entidad de importación. - Un UDT definido en
types.hal
, solo ese UDT se importa a la entidad de importación (otros tipos entypes.hal
no se importan).
- Una interfaz, los
- Importaciones de solo tipos . Si el valor usa la sintaxis de una importación parcial descrita anteriormente, pero con los
types
de palabra clave en lugar de un nombre de interfaz, solo se importan los UDT entypes.hal
del paquete designado.
La entidad importadora obtiene acceso a una combinación de:
- Los UDT comunes del paquete importado definidos en
types.hal
; - Las interfaces del paquete importado (para una importación de paquete completo) o la interfaz especificada (para una importación parcial) con el fin de invocarlos, pasarles identificadores y/o heredar de ellos.
La declaración de importación utiliza la sintaxis de nombre de tipo totalmente calificado para proporcionar el nombre y la versión del paquete o la interfaz que se está importando:
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 interfaz
Una interfaz puede ser una extensión de una interfaz previamente definida. Las extensiones pueden ser de uno de los siguientes tres tipos:
- La interfaz puede agregar funcionalidad a otra, incorporando su API sin cambios.
- El paquete puede agregar funcionalidad a otro, incorporando su API sin cambios.
- La interfaz puede importar tipos de un paquete o de una interfaz específica.
Una interfaz puede extender solo otra interfaz (sin herencia múltiple). Cada interfaz en un paquete con un número de versión menor distinto de cero debe extender una interfaz en 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 se crea una versión 1.3 del paquete original
, la versión 4.1 de IBar
no puede extender la versión 1.3 de IFoo
. En su lugar, la versión 4.1 de IBar
debe extender la 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 lo desea.
Las extensiones de interfaz no implican la dependencia de la biblioteca o la inclusión cruzada de HAL en el código generado; simplemente importan la estructura de datos y las definiciones de métodos en el nivel HIDL. Todos los métodos de una HAL deben implementarse en esa HAL.
Extensiones de proveedor
En algunos casos, las extensiones del proveedor se implementarán como una subclase del objeto base que representa la interfaz central que extienden. El mismo objeto se registrará con el nombre y la versión de la HAL base y con el nombre y la versión de la HAL de la extensión (proveedor).
Versionado
Los paquetes están versionados y las interfaces tienen la versión de su paquete. Las versiones se expresan en dos enteros, mayor . menor
- Las versiones principales no son compatibles con versiones anteriores. Incrementar el número de versión principal restablece el número de versión secundaria a 0.
- Las versiones menores son compatibles con versiones anteriores. Incrementar el número menor indica que la versión más nueva es totalmente compatible con la versión anterior. Se pueden agregar nuevas estructuras de datos y métodos, pero no se pueden cambiar estructuras de datos o firmas de métodos existentes.
Varias versiones principales o secundarias de una HAL pueden estar presentes en un dispositivo simultáneamente. Sin embargo, se debe preferir una versión secundaria a una versión principal porque el código de cliente que funciona con una interfaz de versión secundaria anterior también funcionará con versiones secundarias posteriores de esa misma interfaz. Para obtener más detalles sobre el control de versiones y las extensiones de proveedores, consulte Control de versiones de 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 a lo largo de la sección HIDL. Antes de leer, asegúrese de estar familiarizado con el control de versiones de HIDL , los conceptos de hashing en Hashing con hidl-gen , los detalles del trabajo con HIDL en general y las siguientes definiciones:
Término | Definición |
---|---|
Interfaz binaria de aplicación (ABI) | Interfaz de programación de aplicaciones + cualquier enlace binario requerido. |
Nombre completo (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. |
Para obtener más definiciones, consulte Terminología de HIDL.
Cada archivo se puede encontrar desde el mapeo raíz del paquete y su nombre completo
Las raíces del paquete se especifican para hidl-gen
como el argumento -r android.hardware:hardware/interfaces
. Por ejemplo, si el paquete es vendor.awesome.foo@1.0::IFoo
y se hidl-gen
-r vendor.awesome:some/device/independent/path/interfaces
, entonces el archivo de interfaz debe ubicarse en $ANDROID_BUILD_TOP/some/device/independent/path/interfaces/foo/1.0/IFoo.hal
.
En la práctica, se recomienda que un proveedor u OEM llamado awesome
coloque sus interfaces estándar en vendor.awesome
. Una vez que se ha seleccionado la ruta de un paquete, no se debe cambiar, ya que está integrada en la ABI de la interfaz.
El mapeo de la ruta del paquete debe ser único
Por ejemplo, si tiene -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 facilita mucho el control de versiones de las interfaces ).
La raíz del paquete debe tener un archivo de control de versiones
Si crea una ruta de paquete como -r vendor.awesome:vendor/awesome/interfaces
, también debe crear el archivo $ANDROID_BUILD_TOP/vendor/awesome/interfaces/current.txt
, que debe contener hashes de interfaces creadas con -Lhash
opción en hidl-gen
(esto se analiza extensamente en Hashing con hidl-gen ).
Las interfaces van en ubicaciones independientes del dispositivo
En la práctica, se recomienda compartir interfaces entre sucursales. Esto permite la máxima reutilización del código y la máxima prueba del código en diferentes dispositivos y casos de uso.