Interfaces y paquetes

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 en types.hal)
  • 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 en types.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.