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 emtypes.hal
não são importados);
- Uma interface, o
- 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 emtypes.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.