Google se compromete a promover la equidad racial para las comunidades negras. Ver cómo.
Se usó la API de Cloud Translation para traducir esta página.
Switch to English

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 pueden compilarse de forma independiente.

HIDL está destinado a ser utilizado para la comunicación entre procesos (IPC). La comunicación entre procesos se conoce como Binderized . Para las bibliotecas que deben estar vinculadas a un proceso, también está disponible un modo de acceso directo (no compatible con Java).

HIDL especifica estructuras de datos y 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. Los HAL serán construidos por vendedores o fabricantes de SOC y se colocarán en una partición /vendor en el dispositivo, permitiendo que el marco, en su propia partición, sea reemplazado por una OTA sin volver a compilar los HAL.

El diseño de HIDL equilibra las siguientes preocupaciones:

  • Interoperabilidad . Cree interfaces interoperables confiables entre procesos que pueden compilarse con diversas arquitecturas, cadenas de herramientas y configuraciones de compilación. Las interfaces HIDL están versionadas 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 entregan a código C ++ en estructuras de datos de diseño estándar C ++ que se pueden usar sin desempaquetar. HIDL también proporciona interfaces de memoria compartida y, dado que los RPC son inherentemente lentos, HIDL admite dos formas de transferir datos sin usar una llamada RPC: memoria compartida y una cola de mensajes rápida (FMQ).
  • Intuitivo HIDL evita problemas espinosos de propiedad de la memoria al usar solo in parámetros para RPC (consulte Lenguaje de definición de interfaz de Android (AIDL) ); los valores que no se pueden devolver de manera eficiente desde los métodos se devuelven mediante funciones de devolución de llamada. Ni pasar datos a HIDL para transferirlos 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 la función llamada regrese.

Usando el modo passthrough

Para actualizar los dispositivos que ejecutan versiones anteriores de Android a Android O, puede incluir los HAL convencionales (y heredados) en una nueva interfaz HIDL que sirve al HAL en modo binderizado y el mismo proceso (paso a través). Este ajuste es transparente tanto para el marco HAL como para Android.

El modo Passthrough solo está disponible 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 inherentemente vinculados.

Cuando se .hal un archivo .hal , hidl-gen produce un archivo de encabezado de paso adicional BsFoo.h además de los encabezados utilizados para la comunicación de la carpeta; Este encabezado define las funciones a ser dlopen . Como los HAL passthrough se ejecutan en el mismo proceso en el que se los llama, en la mayoría de los casos los métodos passthrough se invocan mediante una llamada a función directa (mismo hilo). oneway métodos oneway ejecutan en su propio subproceso ya que no están destinados a esperar a que el HAL los procese (esto significa que cualquier HAL que use métodos oneway en modo de transferencia debe ser seguro para el subproceso).

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 pasar las llamadas IPC usando Binder, las funciones deseadas se invocan directamente. Las implementaciones futuras de HAL pueden proporcionar implementaciones múltiples, como FooFast HAL y FooAccurate HAL. En tales casos, se crearía un archivo para cada implementación adicional (por ejemplo, PTFooFast.cpp y PTFooAccurate.cpp ).

HAL de paso de aglomerante

Puede vincular las implementaciones de HAL que admiten el modo de transferencia. Dada una interfaz HAL abcd@MN::IFoo , se crean dos paquetes:

  • abcd@MN::IFoo-impl . Contiene la implementación del HAL y expone la función IFoo* HIDL_FETCH_IFoo(const char* name) . En dispositivos heredados, este paquete se dlopen y la implementación se instancia usando HIDL_FETCH_IFoo . Puede generar el código base usando hidl-gen y -Lc++-impl -Landroidbp-impl y -Landroidbp-impl .
  • abcd@MN::IFoo-service . Abre el HAL passthrough y se registra a sí mismo como un servicio enlazado, permitiendo que la misma implementación de HAL se use como passthrough y binderized.

Dado el tipo IFoo , puede llamar a sp<IFoo> IFoo::getService(string name, bool getStub) para obtener acceso a una instancia de IFoo . Si getStub es verdadero, getService intenta abrir el HAL solo en el modo de acceso directo. Si getStub es falso, getService intenta encontrar un servicio enlazado; si eso falla, entonces trata de encontrar el servicio de acceso directo. El parámetro getStub nunca debe usarse, excepto en defaultPassthroughServiceImplementation . (Los dispositivos que se inician con Android O son dispositivos completamente vinculados, por lo que no se permite abrir un servicio en modo de transferencia).

Gramática HIDL

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

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

  • /** */ indica un comentario de documentación. Estos solo se pueden aplicar a declaraciones de tipo, método, campo y valor de enumeración.
  • /* */ indica un comentario multilínea.
  • // indica un comentario al final de la línea. Aparte de // , las nuevas líneas son las mismas que cualquier otro espacio en blanco.
  • En la gramática de ejemplo a continuación, el texto desde // 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 secuencia que contiene cero o más elementos con puntuación de separación como se indica. No hay argumentos variados en HIDL.
  • Comas separan elementos de secuencia.
  • Los punto y coma terminan cada elemento, incluido el último elemento.
  • MAYÚSCULAS es un no terminal.
  • italics es una familia de tokens, como un integer o un identifier (reglas de análisis C estándar).
  • constexpr es una expresión constante de estilo C (como 1 + 1 y 1L << 3 ).
  • import_name es un nombre de paquete o interfaz, calificado como se describe en Control de versiones HIDL .
  • Las words minúsculas son tokens 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:

aglutinado 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, síncrono Devuelve los datos de la implementación del método HIDL de un servidor al cliente. No se utiliza para métodos que devuelven nulo o un único valor primitivo.
cliente Proceso que llama a métodos de una interfaz particular. Un proceso HAL o framework 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 extender otra interfaz. Se puede usar 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 en un paquete anterior.
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 en una interfaz se llaman en la misma dirección: un proceso de cliente invoca métodos implementados por un proceso de servidor.
de una sola mano Cuando se aplica a un método HIDL, indica que el método no devuelve valores y no 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 por el cliente. En modo passthrough, el cliente y el servidor son el mismo proceso pero con bases de código separadas. Se usa solo para incorporar bases de código heredadas al modelo HIDL. Ver también Binderized .
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 enteros, mayor y menor. Los incrementos menores de la versión pueden agregar (pero no cambiar) tipos y métodos.