Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

HIDL

El lenguaje de definición de interfaz HAL o HIDL (pronunciado "hide-l") es un lenguaje de descripción de interfaz (IDL) para especificar la interfaz entre un HAL y sus usuarios. Permite especificar tipos y llamadas a métodos, recopilados en interfaces y paquetes. En términos más generales, HIDL es un sistema para comunicarse entre bases de código que se pueden compilar de forma independiente. A partir de Android 10, HIDL está obsoleto y Android está migrando para usar AIDL en todas partes.

HIDL está diseñado para utilizarse para la comunicación entre procesos (IPC). La comunicación entre procesos se conoce como revestidas con un aglutinante . Para las bibliotecas que deben estar vinculados a un proceso, un modo de pasarela también está disponible (no soportado en Java).

HIDL especifica las estructuras de datos y las firmas de métodos, organizadas en interfaces (similares a una clase) que se recopilan en paquetes. La sintaxis de HIDL les resultará familiar a los programadores de C ++ y Java, aunque con un conjunto diferente de palabras clave. HIDL también usa anotaciones de estilo Java.

Diseño HIDL

El objetivo de HIDL es que el marco se pueda reemplazar sin tener que reconstruir HAL. HAL serán construidas por los proveedores o fabricantes de SOC y poner en un /vendor partición en el dispositivo, lo que permite el marco, en su propia partición, para ser reemplazada con una OTA sin recompilar los HAL.

El diseño de HIDL equilibra las siguientes preocupaciones:

  • Interoperabilidad. Cree interfaces confiables e interoperables entre procesos que se pueden compilar con varias arquitecturas, cadenas de herramientas y configuraciones de compilación. Las interfaces HIDL tienen versiones y no se pueden cambiar después de su publicación.
  • Eficiencia. HIDL intenta minimizar el número de operaciones de copia. Los datos definidos por HIDL se envían al código C ++ en estructuras de datos de diseño estándar de C ++ que se pueden utilizar sin desempaquetar. HIDL también proporciona interfaces de memoria compartida y, dado que las RPC son inherentemente algo lentas, HIDL admite dos formas de transferir datos sin utilizar una llamada RPC: memoria compartida y una cola de mensajes rápidos (FMQ).
  • Intuitiva. HIDL evita espinosos problemas de la propiedad de memoria utilizando sólo in parámetros para RPC (véase la interfaz de Android Definition Language (AIDL) ); los valores que no se pueden devolver de manera eficiente desde los métodos se devuelven a través de funciones de devolución de llamada. Ni pasar datos a HIDL para su transferencia ni recibir datos de HIDL cambia la propiedad de los datos; la propiedad siempre permanece con la función de llamada. Los datos deben persistir solo durante la duración de la función llamada y pueden destruirse inmediatamente después de que regrese la función llamada.

Usando el modo de paso a través

Para actualizar dispositivos que ejecutan versiones anteriores de Android a Android O, puede empaquetar HAL convencionales (y heredados) en una nueva interfaz HIDL que sirve a HAL en modos enlazados y del mismo proceso (paso a través). Esta envoltura es transparente tanto para HAL como para el marco de Android.

El modo de paso a través está disponible solo para clientes e implementaciones de C ++. Los dispositivos que ejecutan versiones anteriores de Android no tienen HAL escritos en Java, por lo que los HAL de Java están intrínsecamente vinculados.

Cuando un .hal se compila archivo, hidl-gen produce un archivo de cabecera passthrough adicional BsFoo.h además de las cabeceras utilizadas para la comunicación aglutinante; Esto funciona Define las cabeceras a ser dlopen ed. Como los HAL de paso a través se ejecutan en el mismo proceso en el que se llaman, en la mayoría de los casos, los métodos de paso a través se invocan mediante una llamada de función directa (mismo hilo). oneway métodos ejecutan en su propio hilo, ya que no tienen la intención de esperar a que el HAL para procesarlos (Esto significa que cualquier HAL que los usos oneway métodos en modo de traspaso debe ser seguro para subprocesos).

Dado un IFoo.hal , BsFoo.h envuelve los métodos generado HIDL-para proporcionar características adicionales (como hacer oneway transacciones ejecutar en otro hilo). Este archivo es similar a BpFoo.h , sin embargo, en lugar de transmitir llamadas IPC utilizando aglutinante, las funciones deseadas se invocan directamente. Implementaciones futuras de HAL pueden proporcionar múltiples implementaciones, tales como FooFast HAL y un HAL FooAccurate. En tales casos, un archivo para cada aplicación adicional sería creado (por ejemplo, PTFooFast.cpp y PTFooAccurate.cpp ).

Aglutinantes passthrough HAL

Puede enlazar implementaciones de HAL que admitan el modo de transferencia. Dado un HAL interfaz abcd@MN::IFoo , dos paquetes se crean:

  • abcd@MN::IFoo-impl . Contiene la aplicación de la HAL y expone funcionan IFoo* HIDL_FETCH_IFoo(const char* name) . En los dispositivos de legado, este paquete es dlopen ed y la implementación se crea una instancia utilizando HIDL_FETCH_IFoo . Puede generar el código base usando hidl-gen y -Lc++-impl y -Landroidbp-impl .
  • abcd@MN::IFoo-service . Abre el HAL de paso a través y se registra a sí mismo como un servicio enlazado, lo que permite utilizar la misma implementación de HAL como paso a través y enlazado.

Dado el tipo IFoo , puede llamar sp<IFoo> IFoo::getService(string name, bool getStub) para obtener acceso a una instancia de IFoo . Si getStub es cierto, getService intentos para abrir el HAL sólo en el modo de paso a través. Si getStub es falsa, getService intentos de encontrar un servicio con un aglutinante; si eso falla, intenta encontrar el servicio de paso a través. El getStub parámetro nunca debe ser usado excepto en defaultPassthroughServiceImplementation . (Los dispositivos que se inician con Android O son dispositivos totalmente vinculados, por lo que no se permite abrir un servicio en modo de acceso directo).

Gramática HIDL

Por diseño, el lenguaje HIDL es similar a C (pero no usa el preprocesador de C). Todo puntuacion no se describe a continuación (aparte del uso evidente de = y | ) es parte de la gramática.

Nota: Para obtener más detalles sobre el estilo de código HIDL, consulte la Guía de Estilo de Código .

  • /** */ indica un comentario documentación. Estos solo se pueden aplicar a declaraciones de valor de tipo, método, campo y enumeración.
  • /* */ Indica un comentario de varias líneas.
  • // indica un comentario al final de la línea. Aparte de // , saltos de línea son los mismos que cualquier otro espacio en blanco.
  • En el ejemplo de la gramática a continuación, el texto de // hasta el final de la línea no es parte de la gramática sino que es un comentario sobre la gramática.
  • [empty] significa que el término puede estar vacío.
  • ? seguir un literal o término significa que es opcional.
  • ... indica la secuencia que contiene cero o más elementos, con la separación de puntuacion como se indica. No hay argumentos variados en HIDL.
  • Las comas separan los elementos de la secuencia.
  • Los puntos y comas terminan cada elemento, incluido el último elemento.
  • MAYÚSCULAS es un no terminal.
  • italics es una familia de contadores tales como integer o identifier (reglas C de análisis estándar).
  • constexpr es una expresión constante estilo C (tal como 1 + 1 y 1L << 3 ).
  • import_name es un nombre de paquete o interfaz, calificado como se describe en HIDL de versiones .
  • Minúsculas words son símbolos literales.

Ejemplo:

ROOT =
    PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... }  // not for types.hal
  | PACKAGE IMPORTS ITEM ITEM...  // only for types.hal; no method definitions

ITEM =
    ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?;
  |  safe_union identifier { UFIELD; UFIELD; ...};
  |  struct identifier { SFIELD; SFIELD; ...};  // Note - no forward declarations
  |  union identifier { UFIELD; UFIELD; ...};
  |  enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... }; // TYPE = enum or scalar
  |  typedef TYPE identifier;

VERSION = integer.integer;

PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION;

PREAMBLE = interface identifier EXTENDS

EXTENDS = <empty> | extends import_name  // must be interface, not package

GENERATES = generates (FIELD, FIELD ...)

// allows the Binder interface to be used as a type
// (similar to typedef'ing the final identifier)
IMPORTS =
   [empty]
  |  IMPORTS import import_name;

TYPE =
  uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t |
 float | double | bool | string
|  identifier  // must be defined as a typedef, struct, union, enum or import
               // including those defined later in the file
|  memory
|  pointer
|  vec<TYPE>
|  bitfield<TYPE>  // TYPE is user-defined enum
|  fmq_sync<TYPE>
|  fmq_unsync<TYPE>
|  TYPE[SIZE]

FIELD =
   TYPE identifier

UFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...};
  |  struct identifier { FIELD; FIELD; ...};
  |  union identifier { FIELD; FIELD; ...};
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SIZE =  // Must be greater than zero
     constexpr

ANNOTATIONS =
     [empty]
  |  ANNOTATIONS ANNOTATION

ANNOTATION =
  |  @identifier
  |  @identifier(VALUE)
  |  @identifier(ANNO_ENTRY, ANNO_ENTRY  ...)

ANNO_ENTRY =
     identifier=VALUE

VALUE =
     "any text including \" and other escapes"
  |  constexpr
  |  {VALUE, VALUE ...}  // only in annotations

ENUM_ENTRY =
     identifier
  |  identifier = constexpr

Terminología

Esta sección utiliza los siguientes términos relacionados con HIDL:

encuadernado Indica que HIDL se está utilizando para llamadas a procedimientos remotos entre procesos, implementado sobre un mecanismo similar a Binder. Ver también passthrough.
devolución de llamada, asincrónica Interfaz servida por un usuario de HAL, pasada a HAL (a través de un método HIDL) y llamada por HAL para devolver datos en cualquier momento.
devolución de llamada, sincrónico Devuelve datos de la implementación del método HIDL de un servidor al cliente. No se usa para métodos que devuelven vacío o un solo valor primitivo.
cliente Proceso que llama a métodos de una interfaz en particular. Un proceso HAL o marco puede ser un cliente de una interfaz y un servidor de otra. Ver también passthrough.
se extiende Indica una interfaz que agrega métodos y / o tipos a otra interfaz. Una interfaz solo puede ampliar otra interfaz. Puede usarse para un incremento de versión menor en el mismo nombre de paquete o para un nuevo paquete (por ejemplo, una extensión de proveedor) para construir sobre un paquete más antiguo.
genera Indica un método de interfaz que devuelve valores al cliente. Para devolver un valor no primitivo, o más de un valor, se genera una función de devolución de llamada síncrona.
interfaz Colección de métodos y tipos. Traducido a una clase en C ++ o Java. Todos los métodos de una interfaz se llaman en la misma dirección: un proceso cliente invoca métodos implementados por un proceso servidor.
de una sola mano Cuando se aplica a un método HIDL, indica que el método no devuelve valores y no se bloquea.
paquete Colección de interfaces y tipos de datos que comparten una versión.
pasar por Modo de HIDL en el que el servidor es una biblioteca compartida, dlopen ed por el cliente. En el modo de transferencia, el cliente y el servidor son el mismo proceso pero bases de código separadas. Se usa solo para incorporar bases de código heredadas al modelo HIDL. Ver también revestidas con un aglutinante.
servidor Proceso que implementa métodos de una interfaz. Ver también passthrough.
transporte Infraestructura HIDL que mueve datos entre el servidor y el cliente.
versión Versión de un paquete. Consta de dos números enteros, mayor y menor. Los incrementos de versiones menores pueden agregar (pero no cambiar) tipos y métodos.