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

Tipos de dados

As declarações de dados HIDL geram estruturas de dados de layout padrão C ++. Essas estruturas podem ser colocadas em qualquer lugar que pareça natural (na pilha, no arquivo ou no escopo global ou na pilha) e podem ser compostas da mesma maneira. O código do cliente chama o código do proxy HIDL passando referências const e tipos primitivos, enquanto o stub e o código do proxy ocultam os detalhes da serialização.

Nota: Em nenhum momento é o código escrito pelo desenvolvedor necessários para estruturas de dados deserialize explicitamente serialize ou.

A tabela abaixo mapeia primitivas HIDL para tipos de dados C ++:

Tipo HIDL Tipo C ++ Cabeçalho / Biblioteca
enum
enum class
uint8_t..uint64_t
uint8_t..uint64_t
<stdint.h>
int8_t..int64_t
int8_t..int64_t
<stdint.h>
float
float
double
double
vec<T>
hidl_vec<T>
libhidlbase
T[S1][S2]...[SN]
T[S1][S2]...[SN]
string
hidl_string
libhidlbase
handle
hidl_handle
libhidlbase
safe_union
(custom) struct
struct
struct
union
union
fmq_sync
MQDescriptorSync
libhidlbase
fmq_unsync
MQDescriptorUnsync
libhidlbase

As seções abaixo descrevem os tipos de dados com mais detalhes.

enum

Um enum em HIDL se torna um enum em C ++. Por exemplo:

enum Mode : uint8_t { WRITE = 1 << 0, READ = 1 << 1 };
enum SpecialMode : Mode { NONE = 0, COMPARE = 1 << 2 };

… torna-se:

enum class Mode : uint8_t { WRITE = 1, READ = 2 };
enum class SpecialMode : uint8_t { WRITE = 1, READ = 2, NONE = 0, COMPARE = 4 };

A partir de Android 10, uma enumeração pode ser iterada usando ::android::hardware::hidl_enum_range . Esse intervalo inclui cada enumerador na ordem em que aparece no código-fonte HIDL, começando do enum pai até o último filho. Por exemplo, este código itera sobre WRITE , READ , NONE , e COMPARE nessa ordem. Dada SpecialMode acima:

template <typename T>
using hidl_enum_range = ::android::hardware::hidl_enum_range<T>

for (SpecialMode mode : hidl_enum_range<SpecialMode>) {...}

hidl_enum_range também implementa inverter iterators e pode ser usado em constexpr contextos. Se um valor aparecer em uma enumeração várias vezes, o valor aparecerá no intervalo várias vezes.

bitfield <T>

bitfield<T> (onde T é uma enumeração definido pelo utilizador) torna-se o tipo de base de que a enumeração em C ++. No exemplo acima, bitfield<Mode> torna-se uint8_t .

vec <T>

O hidl_vec<T> modelo de classe é parte de libhidlbase e pode ser usado para passar um vetor de qualquer tipo HIDL com um tamanho arbitrário. O recipiente de tamanho fixo comparável é hidl_array . Um hidl_vec<T> também pode ser inicializado para apontar para um tampão de dados externos de tipo T , utilizando o hidl_vec::setToExternal() função.

Além de emissores / inserindo a estrutura adequadamente no cabeçalho gerado C ++, a utilização de vec<T> gera algumas funções de conveniência para traduzir de / para std::vector e nuas T ponteiros. Se o vec<T> é usado como um parâmetro, a função de usá-lo vai ser sobrecarregadas (serão gerados dois protótipos) para aceitar e passar tanto o struct HIDL e uma std::vector<T> digite para esse parâmetro.

variedade

Matrizes constantes em hidl são representados pelo hidl_array classe em libhidlbase . Um hidl_array<T, S1, S2, …, SN> representa um grupo N dimensional tamanho fixo matriz T[S1][S2]…[SN] .

fragmento

O hidl_string classe (parte de libhidlbase ) pode ser utilizado para passar as cadeias mais interfaces de HIDL e é definido em /system/libhidl/base/include/hidl/HidlSupport.h . O primeiro local de armazenamento na classe é um ponteiro para seu buffer de caracteres.

hidl_string sabe como converter de e para std::string and char* (string de estilo C) usando operator= , casts implícitas, e .c_str() função. Structs de string HIDL têm os construtores de cópia apropriados e operadores de atribuição para:

  • Carregar a corda HIDL de um std::string ou uma string C.
  • Criar um novo std::string de uma cadeia HIDL.

Além disso, as cordas HIDL ter construtores de conversão assim cordas C ( char * ) e cadeias de C ++ ( std::string ) podem ser usados em métodos que usam uma cadeia HIDL.

estrutura

Uma struct em HIDL pode conter apenas os tipos de dados de tamanho fixo e não há funções. Definições de struct HIDL mapear diretamente para layout padrão struct s em C ++, garantindo que struct s ter um layout de memória consistente. A estrutura pode incluir tipos HIDL, incluindo a handle , string , e vec<T> , que aponte para tampões de comprimento variável separados.

lidar

AVISO: Os endereços de qualquer tipo (até mesmo endereços de dispositivo físico) não deve ser parte de uma alça nativa. Passar essas informações entre processos é perigoso e os torna suscetíveis a ataques. Quaisquer valores passados ​​entre processos devem ser validados antes de serem usados ​​para pesquisar a memória alocada em um processo. Caso contrário, identificadores incorretos podem causar mau acesso à memória ou corrupção de memória.

O handle tipo é representado pelo hidl_handle estrutura em C ++, que é um invólucro simples em torno de um ponteiro para uma const native_handle_t objecto (este tem estado presente em Android para um longo período de tempo).

typedef struct native_handle
{
    int version;        /* sizeof(native_handle_t) */
    int numFds;         /* number of file descriptors at &data[0] */
    int numInts;        /* number of ints at &data[numFds] */
    int data[0];        /* numFds + numInts ints */
} native_handle_t;

Por padrão, hidl_handle não apropriar-se do native_handle_t ponteiro-quebra. Limita-se existe para armazenar de forma segura um ponteiro para uma native_handle_t de tal modo que ele pode ser utilizado em ambos os processos de 32 e 64 bits.

Cenários em que o hidl_handle não possuem seus descritores de arquivos fechados incluem:

  • Após uma chamada para o setTo(native_handle_t* handle, bool shouldOwn) método com o shouldOwn conjunto de parâmetros a true
  • Quando o hidl_handle objeto é criado pela construção cópia de outro hidl_handle objeto
  • Quando o hidl_handle objeto é copy-designado de outro hidl_handle objeto

hidl_handle fornece ambas conversões implícitas e explícitas de / para native_handle_t* objetos. O uso principal para a handle tipo em HIDL é passar descritores de arquivo através de interfaces HIDL. Um descritor de arquivo único é, portanto, representado por um native_handle_t sem int s e um único fd . Se o cliente e o servidor residirem em um processo diferente, a implementação RPC cuidará automaticamente do descritor de arquivo para garantir que ambos os processos possam operar no mesmo arquivo.

Apesar de um descritor de arquivo recebido em um hidl_handle por um processo será válida nesse processo, não irá persistir para além da função de recepção (ela será fechada uma vez que a função retorna). Um processo que quer manter o acesso persistente para o descritor de arquivo deve dup() os descritores de arquivos fechados, ou copiar todo o hidl_handle objeto.

memória

O HIDL memory tipo mapeia para o hidl_memory classe em libhidlbase , que representa a memória compartilhada não mapeado. Este é o objeto que deve ser passado entre processos para compartilhar memória em HIDL. Para usar a memória compartilhada:

  1. Obter uma instância de IAllocator (atualmente só instância "ashmem" está disponível) e usá-lo para alocar a memória compartilhada.
  2. IAllocator::allocate() retorna uma hidl_memory objecto que pode ser passada através de HIDL RPC e ser mapeada num processo usando libhidlmemory 's mapMemory função.
  3. mapMemory retorna uma referência a um sp<IMemory> objeto que pode ser usado para acessar a memória. ( IMemory e IAllocator são definidos em android.hidl.memory@1.0 .)

Uma instância de IAllocator pode ser usado para alocar a memória:

#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include <hidlmemory/mapping.h>
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::android::hardware::hidl_memory;
....
  sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
  ashmemAllocator->allocate(2048, [&](bool success, const hidl_memory& mem) {
        if (!success) { /* error */ }
        // now you can use the hidl_memory object 'mem' or pass it around
  }));

Mudanças reais para a memória deve ser feito através de um IMemory objeto, quer do lado que criou mem ou no lado que recebe mais de HIDL RPC.

// Same includes as above

sp<IMemory> memory = mapMemory(mem);
void* data = memory->getPointer();
memory->update();
// update memory however you wish after calling update and before calling commit
data[0] = 42;
memory->commit();
// …
memory->update(); // the same memory can be updated multiple times
// …
memory->commit();

interface

As interfaces podem ser passadas como objetos. A interface palavra pode ser usada como açúcar sintático para o tipo android.hidl.base@1.0::IBase ; além disso, a interface atual e quaisquer interfaces importadas serão definidas como um tipo.

Variáveis que Interfaces de retenção devem ser ponteiros fortes: sp<IName> . As funções HIDL que usam parâmetros de interface converterão ponteiros brutos em ponteiros fortes, causando comportamento não intuitivo (o ponteiro pode ser limpo inesperadamente). Para evitar problemas, sempre armazenar as interfaces HIDL como um sp<> .