Google is committed to advancing racial equity for Black communities. See how.
Esta página foi traduzida pela API Cloud Translation.
Switch to English

HIDL C ++

O Android O reprojeta o sistema operacional Android para definir interfaces claras entre a plataforma Android independente do dispositivo e o código específico do dispositivo e do fornecedor. O Android já define muitas dessas interfaces na forma de interfaces HAL, definidas como cabeçalhos C em hardware/libhardware . HIDL substitui essas interfaces HAL por interfaces estáveis ​​com versão, que podem ser interfaces HIDL do lado do cliente e do servidor em C ++ (descrito abaixo) ou Java .

As páginas nesta seção descrevem as implementações C ++ de interfaces HIDL, incluindo detalhes sobre os arquivos gerados automaticamente a partir dos arquivos HIDL .hal pelo compilador hidl-gen , como esses arquivos são empacotados e como integrar esses arquivos ao código C ++ que os usa.

Implementações de cliente e servidor

As interfaces HIDL têm implementações de cliente e servidor:

  • Um cliente de uma interface HIDL é o código que usa a interface chamando métodos nela.
  • Um servidor é uma implementação de uma interface HIDL que recebe chamadas de clientes e retorna resultados (se necessário).

Na transição de libhardware HALs para HIDL HALs, a implementação HAL se torna o servidor e o processo que chama o HAL se torna o cliente. Implementações padrão podem servir tanto HALs passthrough quanto binderized e podem mudar com o tempo:

Figura 1. Progressão de desenvolvimento para HALs legados.

Criação do cliente HAL

Comece incluindo as bibliotecas HAL no makefile:

  • Marca: LOCAL_SHARED_LIBRARIES += android.hardware.nfc@1.0
  • Soong: shared_libs: [ …, android.hardware.nfc@1.0 ]

Em seguida, inclua os arquivos de cabeçalho HAL:

#include <android/hardware/nfc/1.0/IFoo.h>
…
// in code:
sp<IFoo> client = IFoo::getService();
client->doThing();

Criação do servidor HAL

Para criar a implementação HAL, você deve ter os arquivos .hal que representam seu HAL e já gerou makefiles para seu HAL usando -Lmakefile ou -Landroidbp em hidl-gen ( ./hardware/interfaces/update-makefiles.sh faz isso para arquivos HAL internos e é uma boa referência). Ao transferir HALs do libhardware , você pode fazer muito desse trabalho facilmente usando c2hal.

Para criar os arquivos necessários para implementar seu HAL:

PACKAGE=android.hardware.nfc@1.0
LOC=hardware/interfaces/nfc/1.0/default/
m -j hidl-gen
hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces \
    -randroid.hidl:system/libhidl/transport $PACKAGE
hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces \
    -randroid.hidl:system/libhidl/transport $PACKAGE

Para que o HAL funcione no modo passthrough, você deve ter a função HIDL_FETCH_IModuleName residindo em /(system|vendor|...)/lib(64)?/hw/android.hardware.package@3.0-impl( OPTIONAL_IDENTIFIER ).so onde OPTIONAL_IDENTIFIER é uma string que identifica a implementação do passthrough. Os requisitos do modo de passagem são atendidos automaticamente pelos comandos acima, que também criam o destino android.hardware.nfc@1.0-impl , mas qualquer extensão pode ser usada. Por exemplo, android.hardware.nfc@1.0-impl-foo usa -foo para se diferenciar.

Se um HAL for uma versão secundária ou uma extensão de outro HAL, o HAL de base deve ser usado para nomear esse binário. Por exemplo, as implementações de android.hardware.graphics.mapper@2.1 ainda devem estar em um binário chamado android.hardware.graphics.mapper@2.0-impl( OPTIONAL_IDENTIFIER ) . Normalmente, o OPTIONAL_IDENTIFIER aqui incluiria a versão real do HAL. Nomeando o binário dessa forma, os clientes 2.0 podem recuperá-lo diretamente e os clientes 2.1 podem atualizar a implementação.

Em seguida, preencha os stubs com a funcionalidade e configure um daemon. Exemplo de código daemon (compatível com passthrough):

#include <hidl/LegacySupport.h>

int main(int /* argc */, char* /* argv */ []) {
    return defaultPassthroughServiceImplementation<INfc>("nfc");
}

defaultPassthroughServiceImplementation irá dlopen() a biblioteca -impl fornecida e fornecê-la como um serviço encadernado. Exemplo de código daemon (para serviço binderized puro):

int main(int /* argc */, char* /* argv */ []) {
    // This function must be called before you join to ensure the proper
    // number of threads are created. The threadpool will never exceed
    // size one because of this call.
    ::android::hardware::configureRpcThreadpool(1 /*threads*/, true /*willJoin*/);

    sp<INfc> nfc = new Nfc();
    const status_t status = nfc->registerAsService();
    if (status != ::android::OK) {
        return 1; // or handle error
    }

    // Adds this thread to the threadpool, resulting in one total
    // thread in the threadpool. We could also do other things, but
    // would have to specify 'false' to willJoin in configureRpcThreadpool.
    ::android::hardware::joinRpcThreadpool();
    return 1; // joinRpcThreadpool should never return
}

Este daemon geralmente reside em $PACKAGE + "-service-suffix" (por exemplo, android.hardware.nfc@1.0-service ), mas pode estar em qualquer lugar. A sepolicy para uma classe específica de HALs é o atributo hal_<module> (por exemplo, hal_nfc) . Este atributo deve ser aplicado ao daemon que executa um HAL específico (se o mesmo processo servir a vários HALs, vários atributos podem ser aplicados a ele).