O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

HIDL

A linguagem de definição de interface HAL ou HIDL (pronuncia-se "hide-l") é uma linguagem de descrição de interface (IDL) para especificar a interface entre um HAL e seus usuários. Ele permite especificar tipos e chamadas de métodos, coletados em interfaces e pacotes. De forma mais ampla, HIDL é um sistema de comunicação entre bases de código que podem ser compiladas de forma independente. A partir do Android 10, o HIDL está obsoleto e o Android está migrando para usar AIDL em todos os lugares.

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

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

Design HIDL

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

O projeto HIDL equilibra as seguintes preocupações:

  • Interoperabilidade. Crie interfaces confiáveis ​​e interoperáveis ​​entre processos que podem ser compilados com várias arquiteturas, conjuntos de ferramentas e configurações de construção. As interfaces HIDL têm controle de versão e não podem ser alteradas depois de publicadas.
  • Eficiência. HIDL tenta minimizar o número de operações de cópia. Os dados definidos por HIDL são entregues ao código C ++ em estruturas de dados de layout padrão C ++ que podem ser usadas sem descompactação. O HIDL também fornece interfaces de memória compartilhada e, como os RPCs são inerentemente lentos, o HIDL oferece suporte a duas maneiras de transferir dados sem usar uma chamada RPC: memória compartilhada e Fast Message Queue (FMQ).
  • Intuitiva. HIDL evita espinhosa questões de propriedade de memória usando somente in parâmetros para RPC (ver interface Android Definition Language (AIDL) ); os 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 sempre permanece 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 passthrough

Para atualizar dispositivos que executam versões anteriores do Android para o Android O, você pode envolver os HALs convencionais (e legados) em uma nova interface HIDL que atende o HAL nos modos binderized e mesmo processo (passthrough). Esse empacotamento é transparente para a estrutura HAL e Android.

O modo Passthrough está disponível apenas para clientes e implementações C ++. Os dispositivos que executam versões anteriores do Android não têm HALs escritos em Java, portanto, os HALs Java são inerentemente agrupados.

Quando um .hal arquivo é compilado, hidl-gen produz um ficheiro de cabeçalho de passagem adicional BsFoo.h além dos cabeçalhos usados para comunicação ligante; Isto define cabeçalho funções a ser dlopen ed. 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 executar em seu próprio segmento, pois não têm a intenção de esperar o HAL para processá-los (isto significa qualquer HAL que usos oneway métodos no modo passthrough deve ser thread-safe).

Dado um IFoo.hal , BsFoo.h envolve os métodos gerados por HIDL para fornecer características adicionais (tal como fazendo oneway transacções executadas no outro segmento). Este arquivo é semelhante ao BpFoo.h , no entanto, em vez de passar chamadas IPC usando ligante, as funções desejadas estão diretamente invocado. Implementações futuras de HALS podem fornecer várias implementações, tais como FooFast HAL e um HAL FooAccurate. Em tais casos, um arquivo para cada aplicação adicional seria criado (por exemplo, PTFooFast.cpp e PTFooAccurate.cpp ).

Binderizing passthrough HALs

Você pode vincular as implementações HAL que oferecem suporte ao modo de passagem. Dada uma HAL interface do abcd@MN::IFoo , dois pacotes são criados:

  • abcd@MN::IFoo-impl . Contém a implementação do HAL e expõe funcionar IFoo* HIDL_FETCH_IFoo(const char* name) . Em dispositivos de legado, este pacote é dlopen ed ea implementação é instanciado 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 vinculado, permitindo que a mesma implementação de HAL seja usada como passagem e vinculativa.

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 é verdade, getService tentativas para abrir o HAL apenas no modo passthrough. Se getStub é falso, getService tentativas de encontrar um serviço binderized; se isso falhar, ele tentará encontrar o serviço de passagem. O getStub parâmetro nunca deve ser usado exceto em defaultPassthroughServiceImplementation . (Os dispositivos que iniciam com o Android O são dispositivos totalmente encadernados, 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 a pontuação não descritos abaixo (além da óbvia utilização de = e | ) é parte da gramática.

Nota: Para mais detalhes sobre estilo de código HIDL, consulte o Guia de Estilo Código .

  • /** */ indica um comentário de documentação. Eles podem ser aplicados apenas a declarações de tipo, método, campo e valor enum.
  • /* */ Indica um comentário de várias linhas.
  • // indica um comentário para o final da linha. Além de // , novas linhas são as mesmas que qualquer outro espaço em branco.
  • No exemplo abaixo gramática, texto de // até o fim da linha não faz parte da gramática, mas em vez disso é um comentário sobre a gramática.
  • [empty] significa que o termo pode estar vazio.
  • ? seguir um literal ou termo significa que é opcional.
  • ... indica a sequência contendo zero ou mais itens com separação de pontuação tal como indicado. Não há argumentos variáveis ​​no HIDL.
  • As vírgulas separam os elementos da sequência.
  • Os pontos-e-vírgulas encerram cada elemento, incluindo o último elemento.
  • MAIÚSCULAS é um não terminal.
  • italics é uma família de token, tal como integer ou identifier (regras C padrão de análise).
  • constexpr é uma expressão constante de estilo C (tal como 1 + 1 e 1L << 3 ).
  • import_name é um nome de pacote ou de interface, qualificada como descrito no HIDL de versão .
  • Minúsculas words são símbolos 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 procedimento remoto entre processos, implementado em um mecanismo semelhante ao Binder. Veja também passthrough.
retorno de chamada, assíncrono Interface servida 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.
callback, síncrono Retorna dados da implementação do método HIDL de um servidor para o cliente. Não usado para métodos que retornam void 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 passthrough.
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 secundária no mesmo nome de pacote ou para um novo pacote (por exemplo, uma extensão de fornecedor) para construir em 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, uma função de retorno de chamada síncrona é gerada.
interface Coleção de métodos e tipos. Traduzido em uma classe em C ++ ou Java. Todos os métodos em uma interface são chamados na mesma direção: um processo cliente invoca métodos implementados por um processo 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 ed pelo cliente. No modo passthrough, cliente e servidor são o mesmo processo, mas bases de código separadas. Usado apenas para trazer bases de código legadas para o modelo HIDL. Veja também Binderized.
servidor Processo que implementa métodos de uma interface. Veja também passthrough.
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, maiores e menores. Incrementos de versão menores podem adicionar (mas não alterar) tipos e métodos.