Interfaces e pacotes

O HIDL é baseado em interfaces, um tipo abstrato usado em ambientes linguagens de programação para definir comportamentos. Cada interface faz parte de um pacote.

Pacotes

Os nomes de pacotes podem ter subníveis, como package.subpackage. A o diretório raiz dos pacotes HIDL publicados é hardware/interfaces ou vendor/vendorName (por exemplo, vendor/google para Pixel dispositivos). O nome do pacote forma um ou mais subdiretórios na raiz directory; todos os arquivos que definem um pacote estão no mesmo diretório. Por exemplo: Foi possível encontrar package android.hardware.example.extension.light@2.0 abaixo de hardware/interfaces/example/extension/light/2.0.

A tabela a seguir lista prefixos de pacotes e locais:

Prefixo do pacote Local Tipos de interface
android.hardware.* hardware/interfaces/* HAL
android.frameworks.* frameworks/hardware/interfaces/* frameworks/ relacionados
android.system.* system/hardware/interfaces/* sistema/ relacionado
android.hidl.* system/libhidl/transport/* core

O diretório do pacote contém arquivos com extensão .hal. Todas deve conter uma instrução package nomeando o pacote e do qual o arquivo faz parte. O arquivo types.hal, se presente, sem definir uma interface, mas sim tipos de dados acessíveis a todos no pacote.

Definição de interface

Além de types.hal, todos os outros arquivos .hal definem uma interface. Normalmente, uma interface é definida da seguinte maneira:

interface IBar extends IFoo { // IFoo is another interface
    // embedded types
    struct MyStruct {/*...*/};

    // interface methods
    create(int32_t id) generates (MyStruct s);
    close();
};

Uma interface sem uma declaração extends explícita implicitamente se estende de android.hidl.base@1.0::IBase (semelhante a java.lang.Object em Java. A interface IBase, implicitamente importado, declara vários métodos reservados que não podem e não podem ser redeclaradas em interfaces definidas pelo usuário ou usadas de outra forma. Esses métodos incluem:

  • ping
  • interfaceChain
  • interfaceDescriptor
  • notifySyspropsChanged
  • linkToDeath
  • unlinkToDeath
  • setHALInstrumentation
  • getDebugInfo
  • debug
  • getHashChain

Processo de importação

A instrução import é um mecanismo HIDL para acessar o pacote interfaces e tipos em outro pacote. uma instrução import; se preocupa com duas entidades:

  • A entidade de importação, que pode ser um pacote ou um interface
  • A entidade importada, que pode ser um pacote ou um interface

A entidade de importação é determinada pelo local do Instrução import. Quando a instrução está dentro do types.hal, o que está sendo importado fica visível para todo o pacote. essa é uma importação no nível do pacote. Quando a instrução está dentro de a entidade de importação é a própria interface; este é um interface.

A entidade importada é determinada pelo valor após o import palavra-chave. O valor não precisa ser um nome totalmente qualificado. se um componente for omitido, ele é preenchido automaticamente com informações do pacote atual. Para valores totalmente qualificados, os seguintes casos de importação são aceitos:

  • Importações de pacotes inteiros. Se o valor for um nome de pacote e uma (sintaxe descrita abaixo), todo o pacote será importado para o entidade de importação.
  • Importações parciais. Se o valor for:
    • Uma interface, o types.hal do pacote e essa interface são importado para a entidade de importação.
    • Um UDT definido em types.hal, então apenas essa UDT é importada para a entidade que está fazendo a importação (outros tipos em types.hal não são importados);
  • Importações somente de tipos. Se o valor usa a sintaxe de uma importação parcial descrita acima, mas com a palavra-chave types de um nome de interface, apenas os UDTs em types.hal dos são importados.

A entidade de importação tem acesso a uma combinação de:

  • UDTs comuns do pacote importado definidos em types.hal.
  • As interfaces do pacote importado (para uma importação de pacote inteiro) ou o do Terraform (para importação parcial) com a finalidade de invocá-los, passando para eles e/ou herdar deles.

A instrução de importação usa a sintaxe de nome de tipo totalmente qualificado para fornecer o nome e versão do pacote ou interface que está sendo importado:

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

Herança de interface

Uma interface pode ser uma extensão de uma interface definida anteriormente. As extensões podem ser de três tipos:

  • A interface pode acrescentar funcionalidade a outra, incorporando a API sem alterações.
  • O pacote pode adicionar funcionalidade a outro, incorporando a API sem alterações.
  • A interface pode importar tipos de um pacote ou de uma interface específica.

Uma interface pode estender somente uma outra interface (sem herança múltipla). Cada interface em um pacote com um número de versão secundária diferente de zero deve estender um na versão anterior do pacote. Por exemplo, se uma interface O IBar na versão 4.0 do pacote derivative é baseado em (estende) uma interface IFoo na versão 1.2 do pacote original, e uma versão 1.3 do pacote original está criado, o IBar versão 4.1 não pode estender a versão 1.3 do IFoo Em vez disso, a versão 4.1 do IBar precisa estender IBar versão 4.0, que está vinculada ao IFoo versão 1.2. A versão 5.0 do IBar poderá estender a versão 1.3 do IFoo se quiser.

Extensões de interface não implicam dependência da biblioteca ou inclusão entre HAL no código gerado — eles simplesmente importam a estrutura de dados e o método definições no nível do HIDL. Cada método em uma HAL precisa ser implementado HAL

Extensões do fornecedor

Em alguns casos, as extensões de fornecedor são implementadas como uma subclasse da objeto base que representa a interface principal que eles estendem. O mesmo objeto é registrada sob o nome e a versão base da HAL e no nome nome e versão da HAL (fornecedor).

Controle de versões

Os pacotes são controlados por versão, e as interfaces têm a versão deles. As versões são expressas em dois números inteiros: principal.secundária.

  • As versões principais não são compatíveis com versões anteriores. Incrementando o número da versão principal redefine o número da versão secundária para 0.
  • As versões secundárias são compatíveis com versões anteriores. Incrementar o número menor indica que a versão mais recente é totalmente compatível com as para a versão anterior. É possível adicionar novas estruturas de dados e métodos, mas nenhum estruturas de dados ou assinaturas de método podem ser alteradas.

Várias versões principais ou secundárias de uma HAL podem estar presentes em um dispositivo ao mesmo tempo. No entanto, é preferível usar uma versão secundária em vez de uma grande porque o código do cliente funciona com uma interface de versão secundária anterior também funciona com versões secundárias posteriores dessa mesma interface. Para mais detalhes sobre controle de versões e extensões de fornecedor, consulte Controle de versões de HIDL.

Resumo do layout da interface

Esta seção resume como gerenciar um pacote de interface HIDL (como hardware/interfaces) e consolida as informações apresentadas em toda a seção do HIDL. Antes de ler, você precisa conhecer Controle de versões de HIDL hash com conceitos do hidl-gen, os detalhes de como trabalhar com HIDL em geral e as seguintes definições:

Termo Definição
Interface binária do aplicativo (ABI) Interface de programação do aplicativo mais as vinculações binárias necessárias.
nome totalmente qualificado (fqName) Nome para distinguir um tipo do Hidl. Exemplo: android.hardware.foo@1.0::IFoo:
pacote Pacote que contém uma interface e tipos de HIDL. Exemplo: android.hardware.foo@1.0:
raiz do pacote Pacote raiz que contém as interfaces HIDL. Exemplo: a interface HIDL android.hardware está na raiz do pacote android.hardware.foo@1.0.
caminho raiz do pacote É a localização na árvore de origem do Android para onde a raiz de um pacote é mapeada.

Para mais definições, consulte o HIDL Terminologia.

Todos os arquivos podem ser encontrados no mapeamento raiz do pacote e seu nome totalmente qualificado

As raízes do pacote são especificadas para hidl-gen como o argumento. -r android.hardware:hardware/interfaces. Por exemplo, se o O pacote é vendor.awesome.foo@1.0::IFoo e hidl-gen. recebe -r vendor.awesome:some/device/independent/path/interfaces, o arquivo de interface deve estar localizado em $ANDROID_BUILD_TOP/some/device/independent/path/interfaces/foo/1.0/IFoo.hal.

Na prática, é recomendado para um fornecedor ou OEM chamado awesome. colocar as interfaces padrão em vendor.awesome. Após um pacote for selecionado, ele não poderá ser alterado, já que é incorporado à ABI de na interface.

O mapeamento do caminho do pacote precisa ser exclusivo

Por exemplo, se você tiver -rsome.package:$PATH_A e -rsome.package:$PATH_B, $PATH_A precisa ser igual a $PATH_B para um diretório de interface consistente. Isso também facilita interfaces com controle de versão mais fácil).

A raiz do pacote precisa ter um arquivo de controle de versão

Se você criar um caminho de pacote como -r vendor.awesome:vendor/awesome/interfaces, você também precisa criar o arquivo $ANDROID_BUILD_TOP/vendor/awesome/interfaces/current.txt, que precisa conter hashes de interfaces feitas usando a opção -Lhash no hidl-gen (isso é discutido amplamente em Hash com hidl-gen).

As interfaces são independentes de dispositivo localizações

Na prática, recomendamos compartilhar interfaces entre ramificações. Isso permite a reutilização e os testes máximos do código em diferentes dispositivos e casos de uso.