O Google está comprometido em promover a equidade racial para as comunidades negras. Veja como.
Esta página foi traduzida pela API Cloud Translation.
Switch to English

HIDL

A linguagem de definição de interface HAL ou HIDL (pronunciado "hide-l") é uma linguagem de descrição de interface (IDL) para especificar a interface entre um HAL e seus usuários. Permite especificar tipos e chamadas de métodos, coletados em interfaces e pacotes. Mais amplamente, o HIDL é um sistema para comunicação entre bases de código que podem ser compiladas independentemente.

O HIDL deve ser usado para comunicação entre processos (IPC). A comunicação entre processos é conhecida como encadernada . Para bibliotecas que devem ser vinculadas a um processo, também está disponível um modo de passagem (não suportado em Java).

HIDL especifica estruturas de dados e assinaturas de métodos, organizadas em interfaces (semelhantes a uma classe) que são coletadas em pacotes. A sintaxe do HIDL parecerá familiar para os programadores de C ++ e Java, embora com um conjunto diferente de palavras-chave. O HIDL também usa anotações no estilo Java.

Design HIDL

O objetivo do HIDL é que a estrutura possa ser substituída sem a necessidade de reconstruir HALs. Os HALs serão construídos por fornecedores ou fabricantes de SOC e colocados em uma partição /vendor no dispositivo, permitindo que a estrutura, em sua própria partição, seja substituída por um OTA sem recompilar os HALs.

O design do HIDL equilibra as seguintes preocupações:

  • Interoperabilidade . Crie interfaces interoperáveis ​​e confiáveis ​​entre processos que podem ser compilados com várias arquiteturas, cadeias de ferramentas e configurações de compilação. As interfaces HIDL têm versão e não podem ser alteradas após a publicação.
  • Eficiência . O HIDL tenta minimizar o número de operações de cópia. Os dados definidos pelo HIDL são entregues ao código C ++ nas estruturas de dados de layout padrão do C ++ que podem ser usadas sem descompactar. O HIDL também fornece interfaces de memória compartilhada e, como as RPCs são inerentemente lentas, o HIDL suporta duas maneiras de transferir dados sem usar uma chamada RPC: memória compartilhada e uma fila de mensagens rápida (FMQ).
  • Intuitivo . HIDL evita espinhosa questões de propriedade de memória usando somente in parâmetros para RPC (ver interface Android Definition Language (AIDL) ); valores que não podem ser retornados com eficiência de métodos são retornados por meio de funções de retorno de chamada. Nem a passagem de dados para o HIDL para transferência nem o recebimento de dados do HIDL altera a propriedade dos dados - a propriedade permanece sempre com a função de chamada. Os dados precisam persistir apenas durante a duração da função chamada e podem ser destruídos imediatamente após o retorno da função chamada.

Usando o modo de passagem

Para atualizar dispositivos executando versões anteriores do Android para Android O, você pode agrupar os HALs convencionais (e herdados) em uma nova interface HIDL que serve o HAL nos modos encadernado e do mesmo processo (passagem). Esse empacotamento é transparente para a estrutura HAL e Android.

O modo de transmissão está disponível apenas para clientes e implementações C ++. Os dispositivos que executam versões anteriores do Android não possuem HALs gravados em Java, portanto, os HALs Java são inerentemente vinculados.

Quando um arquivo .hal é compilado, o hidl-gen produz um arquivo de cabeçalho de passagem extra BsFoo.h , além dos cabeçalhos usados ​​para a comunicação do fichário; esse cabeçalho define as funções a serem dlopen . Como os HALs de passagem são executados no mesmo processo em que são chamados, na maioria dos casos, os métodos de passagem são chamados por chamada de função direta (mesmo encadeamento). oneway métodos oneway são executados em seu próprio encadeamento, pois não pretendem aguardar o processamento do HAL (isso significa que qualquer HAL que use métodos oneway no modo passthrough deve ser seguro para encadeamento).

Dado um IFoo.hal , o BsFoo.h agrupa os métodos gerados pelo HIDL para fornecer recursos adicionais (como fazer transações oneway executadas em outro encadeamento). Este arquivo é semelhante ao BpFoo.h , no entanto, em vez de repassar chamadas IPC usando o fichário, as funções desejadas são chamadas diretamente. As implementações futuras de HALs podem fornecer várias implementações, como FooFast HAL e FooAccurate HAL. Nesses casos, um arquivo para cada implementação adicional seria criado (por exemplo, PTFooFast.cpp e PTFooAccurate.cpp ).

HALs de passagem Binderizing

Você pode aglomerar implementações de HAL compatíveis com o modo de passagem. Dada uma interface HAL abcd@MN::IFoo , dois pacotes são criados:

  • abcd@MN::IFoo-impl . Contém a implementação do HAL e expõe a função IFoo* HIDL_FETCH_IFoo(const char* name) . Em dispositivos legados, este pacote é dlopen e a implementação é instanciada usando HIDL_FETCH_IFoo . Você pode gerar o código base usando hidl-gen e -Lc++-impl e -Landroidbp-impl .
  • abcd@MN::IFoo-service . Abre o HAL de passagem e se registra como um serviço encadernado, permitindo que a mesma implementação de HAL seja usada como passthrough e encadernado.

Dado o tipo IFoo , você pode chamar sp<IFoo> IFoo::getService(string name, bool getStub) para obter acesso a uma instância do IFoo . Se getStub for verdadeiro, o getService tenta abrir o HAL apenas no modo de passagem. Se getStub for falso, getService tenta encontrar um serviço vinculado; se isso falhar, ele tenta encontrar o serviço de passagem. O parâmetro getStub nunca deve ser usado, exceto em defaultPassthroughServiceImplementation . (Os dispositivos iniciados com o Android O são dispositivos totalmente bloqueados, portanto, a abertura de um serviço no modo de passagem não é permitida.)

Gramática HIDL

Por design, a linguagem HIDL é semelhante a C (mas não usa o pré-processador C). Toda pontuação não descrita abaixo (além do uso óbvio de = e | ) faz parte da gramática.

Nota: Para obter detalhes sobre o estilo de código HIDL, consulte o Code Style Guide .

  • /** */ indica um comentário da documentação. Eles podem ser aplicados apenas a declarações de tipo, método, campo e valor de enumeração.
  • /* */ indica um comentário de várias linhas.
  • // indica um comentário até o final da linha. Além de // , as novas linhas são iguais a qualquer outro espaço em branco.
  • Na gramática de exemplo abaixo, o texto de // até o final da linha não faz parte da gramática, mas é um comentário sobre a gramática.
  • [empty] significa que o termo pode estar vazio.
  • ? seguir um literal ou termo significa que é opcional.
  • ... indica sequência contendo zero ou mais itens com pontuação de separação, conforme indicado. Não há argumentos variados no HIDL.
  • Vírgulas separam os elementos da sequência.
  • O ponto e vírgula encerra cada elemento, incluindo o último elemento.
  • MAIÚSCULAS é um termo não-terminal.
  • italics é uma família de tokens, como integer ou identifier (regras de análise padrão C).
  • constexpr é uma expressão constante do estilo C (como 1 + 1 e 1L << 3 ).
  • import_name é um nome de pacote ou interface, qualificado conforme descrito em HIDL Versioning .
  • words minúsculas são tokens literais.

Exemplo:

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

Terminologia

Esta seção usa os seguintes termos relacionados ao HIDL:

encadernado Indica que o HIDL está sendo usado para chamadas de procedimentos remotos entre processos, implementados em um mecanismo semelhante ao Binder. Veja também passagem .
retorno de chamada, assíncrono Interface atendida por um usuário HAL, passada para o HAL (por meio de um método HIDL) e chamada pelo HAL para retornar dados a qualquer momento.
retorno de chamada, síncrono Retorna dados da implementação do método HIDL de um servidor para o cliente. Não utilizado para métodos que retornam nulo ou um único valor primitivo.
cliente Processo que chama métodos de uma interface específica. Um HAL ou processo de estrutura pode ser um cliente de uma interface e um servidor de outra. Veja também passagem .
estende Indica uma interface que adiciona métodos e / ou tipos a outra interface. Uma interface pode estender apenas uma outra interface. Pode ser usado para um incremento de versão menor no mesmo nome de pacote ou para um novo pacote (por exemplo, uma extensão de fornecedor) para criar um pacote mais antigo.
gera Indica um método de interface que retorna valores ao cliente. Para retornar um valor não primitivo ou mais de um valor, é gerada uma função de retorno de chamada síncrona.
interface Coleção de métodos e tipos. Traduzido para uma classe em C ++ ou Java. Todos os métodos em uma interface são chamados na mesma direção: um processo do cliente chama métodos implementados por um processo do servidor.
mão única Quando aplicado a um método HIDL, indica que o método não retorna valores e não bloqueia.
pacote Coleção de interfaces e tipos de dados que compartilham uma versão.
atravessar Modo de HIDL no qual o servidor é uma biblioteca compartilhada, dlopen pelo cliente. No modo de passagem, cliente e servidor são o mesmo processo, mas bases de código separadas. Usado apenas para trazer bases de código herdadas para o modelo HIDL. Veja também Binderized .
servidor Processo que implementa métodos de uma interface. Veja também passagem .
transporte Infraestrutura HIDL que move dados entre o servidor e o cliente.
versão Versão de um pacote. Consiste em dois números inteiros, maior e menor. Os incrementos de versões secundárias podem adicionar (mas não alterar) tipos e métodos.