Sensores com várias HAL

O Sensor de várias HALs é um framework que permite que as HALs dos sensores funcionem com outras HALs do sensor. O recurso Sensores Multi-HAL carrega dinamicamente as sub-HALs de sensores armazenadas como bibliotecas dinâmicas na partição do fornecedor e fornece a elas um objeto de callback que pode processar a publicação de eventos e adquirir e liberar o wake lock. Uma sub-HAL de sensores é uma HAL de sensores integrada a um objeto compartilhado na partição do fornecedor. Ela é usada pelo framework de várias HALs. Essas sub-HALs não dependem umas das outras ou do código multi-HAL que contém a função principal do processo.

A Sensors Multi-HAL 2.1, disponível em dispositivos com o Android 11 ou versões mais recentes, é uma iteração da Sensors Multi-HAL 2.0 que oferece suporte ao carregamento de sub-HALs que podem expor o tipo de sensor de ângulo de dobradiça. Para oferecer suporte a esse tipo de sensor, os sub-HALs precisam usar as APIs sub-HAL definidas no cabeçalho SubHal 2.1.

Para dispositivos com o Android 13 ou versões mais recentes que usam a HAL de sensores AIDL, use a camada de paliativo multi-HAL para permitir a funcionalidade de várias HAL. Para detalhes de implementação, consulte Como usar os sensores multi-HAL com a HAL de sensores AIDL.

Diferença entre os sensores Multi-HAL 2 e os sensores HAL 2

A Sensores Multi-HAL 2, disponível em dispositivos com o Android 10 ou versões mais recentes, apresenta várias abstrações sobre a Sensors HAL 2 para facilitar a interação com as APIs HAL. A Sensors Multi-HAL 2 introduz a classe HalProxy para processar a implementação da interface Sensors HAL 2 e a V2_1/SubHal (ou V2_0/SubHal) para permitir que HalProxy interaja com sub-HALs.

A interface ISensorsSubHal é diferente da interface 2.1/ISensors.hal (ou 2.0/ISensors.hal) das seguintes maneiras:

  • O método de inicialização transmite uma classe IHalProxyCallback em vez de duas FMQs e ISensorsCallback.
  • As sub-HALs precisam implementar uma função de depuração para fornecer informações de depuração em relatórios de bugs.
  • As sub-HALs precisam implementar uma função de nome para que a sub-HAL carregada possa ser distinguida de outras sub-HALs.

A principal diferença entre o Sensors Multi-HAL 2 e o Sensors HAL 2 está nas funções de inicialização. Em vez de fornecer FMQs, a interface IHalProxyCallback oferece dois métodos: um para postar eventos do sensor no framework e um para criar wake locks. Por trás dos panos, a Sensor Multi-HAL gerencia todas as interações com as FMQs para garantir a entrega oportuna de eventos do sensor para todas as sub-HALs. É altamente recomendável que as sub-HALs usem o método createScopedWakelock para delegar o ônus de esgotar os bloqueios de ativação para o Sensores Multi-HAL e centralizar o uso de um bloqueio de ativação comum para todo o Sensores Multi-HAL, o que minimiza as chamadas de bloqueio e desbloqueio.

O Sensors Multi-HAL 2 também tem alguns recursos de segurança integrados. Ele lida com situações em que a FMQ do sensor está cheia ou em que o framework do sensor do Android é reiniciado e o estado do sensor precisa ser redefinido. Além disso, quando os eventos são enviados para a classe HalProxy, mas o framework do sensor não consegue aceitar os eventos imediatamente, o Sensores Multi-HAL pode mover os eventos para uma linha de execução em segundo plano para permitir que o trabalho continue em todos os sub-HALs enquanto aguarda que os eventos sejam postados.

Código-fonte e implementação de referência

Todos os códigos multi-HAL de sensores estão disponíveis em hardware/interfaces/sensors/common/default/2.X/multihal/. Confira alguns recursos.

  • HalProxy.h: o objeto HalProxy é instanciado pelo Sensors Multi-HAL e processa a transmissão de dados das sub-HALs para o framework de sensores.
  • HalProxy.cpp: a implementação de HalProxy contém toda a lógica necessária para a comunicação multiplexada entre sub-HALs e o framework do sensor.
  • SubHal.h: a interface ISensorsSubHal define a interface que as sub-HALs precisam seguir para serem compatíveis com HalProxy. A sub-HAL implementa o método de inicialização para que o objeto HalProxyCallback possa ser usado para postEvents e createScopedWakelock.

    Para implementações multi-HAL 2.0, use a versão 2.0 de SubHal.h.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/: esses testes de unidade verificam a implementação de HalProxy.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/: este exemplo de implementação de sub-HAL usa sensores falsos para gerar dados falsos. Útil para testar como várias sub-HALs interagem em um dispositivo.

Implementação

Esta seção descreve como implementar o Sensor Multi-HAL nas seguintes situações:

Usar a HAL de sensores com a HAL de sensores AIDL

Para permitir o recurso de várias HALs com a HAL de sensores AIDL, importe o módulo de camada de shim de várias HALs AIDL, que está em hardware/interfaces/sensors/aidl/default/multihal/. O módulo processa a conversão entre os tipos de definição da HAL de sensores AIDL e HIDL e define um wrapper ao redor da interface multi-HAL descrita em Como implementar sensores Multi-HAL 2.1. A camada de shim multi-HAL da AIDL é compatível com dispositivos que implementam a Sensors Multi-HAL 2.1.

A camada de shim multi-HAL da AIDL permite expor o rastreador de cabeça e os tipos de sensor de IMU de eixo limitado na HAL de sensores AIDL. Para usar esses tipos de sensor definidos pela interface HAL da AIDL, defina o campo type na estrutura SensorInfo na implementação getSensorsList_2_1(). Isso é seguro porque os campos de tipo de sensor com base em números inteiros da HAL de sensores AIDL e HIDL não se sobrepõem.

Implementar a Sensores Multi-HAL 2.1

Para implementar os sensores Multi-HAL 2.1 em um novo dispositivo, siga estas etapas:

  1. Implemente a interface ISensorsSubHal, conforme descrito em SubHal.h.
  2. Implemente o método sensorsHalGetSubHal_2_1 em SubHal.h.
  3. Adicione um destino cc_library_shared para criar o sub-HAL recém-implementado. Ao adicionar o destino:

    1. Verifique se o destino foi enviado para algum lugar na partição do fornecedor do dispositivo.
    2. No arquivo de configuração localizado em /vendor/etc/sensors/hals.conf, adicione o caminho para a biblioteca em uma nova linha. Se necessário, crie o arquivo hals.conf.

    Para conferir um exemplo de entrada Android.bp para criar uma biblioteca sub-HAL, consulte hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp.

  4. Remova todas as entradas android.hardware.sensors do arquivo manifest.xml, que contém a lista de HALs com suporte no dispositivo.

  5. Remova todos os arquivos android.hardware.sensors e service.rc do serviço do arquivo device.mk e adicione android.hardware.sensors@2.1-service.multihal e android.hardware.sensors@2.1-service.multihal.rc a PRODUCT_PACKAGES.

Na inicialização, HalProxy é iniciado, procura a sub-HAL recém-implementada e inicializa-a chamando sensorsHalGetSubHal_2_1.

Porta dos sensores Multi-HAL 2.0 para Multi-HAL 2.1

Para portar da Multi-HAL 2.0 para a Multi-HAL 2.1, implemente a interface SubHal e recompila o sub-HAL.

Estas são as diferenças entre as interfaces SubHal 2.0 e 2.1:

  • O IHalProxyCallback usa os tipos criados na versão 2.1 da especificação ISensors.hal.
  • A função initialize() transmite um novo IHalProxyCallback em vez daquele da interface SubHal 2.0
  • As sub-HALs precisam implementar getSensorsList_2_1 e injectSensorData_2_1 em vez de getSensorsList e injectSensorData, já que esses métodos usam os novos tipos adicionados na versão 2.1 da especificação ISensors.hal.
  • Os sub-HALs precisam expor sensorsHalGetSubHal_2_1 em vez de sensorsHalGetSubHal para que o Multi-HAL os trate como sub-HALs da versão 2.1.

Portabilidade da HAL 2.0 de sensores

Ao fazer upgrade para o Sensors Multi-HAL 2.0 da HAL 2.0 de sensores, verifique se a implementação da HAL atende aos requisitos a seguir.

Inicializar a HAL

A Sensors HAL 2.0 tem uma função de inicialização que permite que o serviço de sensor transmita FMQs e um callback dinâmico de sensor. Nos Sensores Multi-HAL 2.0, a função initialize() transmite um único callback que precisa ser usado para postar eventos do sensor, receber wake locks e notificar sobre desconexões e conexões dinâmicas do sensor.

Publicar eventos do sensor na implementação de várias HALs

Em vez de postar eventos de sensor pela FMQ, a sub-HAL precisa gravar eventos de sensor na IHalProxyCallback quando eles estiverem disponíveis.

Eventos WAKE_UP

Na HAL de sensores 2.0, a HAL pode gerenciar o wake lock para a implementação. Nos Sensores Multi-HAL 2.0, as sub-HALs permitem que a implementação da Multi-HAL gerencie wake locks e podem solicitar que um wake lock seja adquirido invocando createScopedWakelock. Uma trava de ativação de escopo bloqueada precisa ser adquirida e transmitida para postEvents ao publicar eventos de ativação para a implementação de vários HALs.

Sensores dinâmicos

O Sensors Multi-HAL 2.0 exige que onDynamicSensorsConnected e onDynamicSensorsDisconnected em IHalProxyCallback sejam chamados sempre que as conexões dinâmicas de sensores mudarem. Esses callbacks estão disponíveis como parte do ponteiro IHalProxyCallback fornecido pela função initialize().

Porta da HAL 1.0 de sensores

Ao fazer upgrade da HAL 1.0 de sensores para Sensores Multi-HAL 2.0, confira se a implementação da HAL atende aos requisitos a seguir.

Inicializar a HAL

A função initialize() precisa ter suporte para estabelecer o callback entre a sub-HAL e a implementação da Multi-HAL.

Expor os sensores disponíveis

Nos Sensores Multi-HAL 2.0, a função getSensorsList() precisa retornar o mesmo valor durante a inicialização de um único dispositivo, mesmo quando a HAL dos sensores é reiniciada. Isso permite que o framework tente restabelecer as conexões do sensor se o servidor do sistema for reiniciado. O valor retornado por getSensorsList() pode mudar depois que o dispositivo é reinicializado.

Publicar eventos do sensor na implementação Multi-HAL

Na HAL 2.0 de sensores, em vez de esperar que poll() seja chamada, a sub-HAL precisa gravar proativamente eventos do sensor em IHalProxyCallback sempre que os eventos do sensor estiverem disponíveis.

Eventos WAKE_UP

Na HAL 1.0 de sensores, a HAL pode gerenciar o bloqueio de ativação para a implementação. No Sensors Multi-HAL 2.0, os sub-HALs permitem que a implementação de Sensors Multi-HAL gerencie wake locks e solicite que um wake lock seja adquirido chamando createScopedWakelock. Uma trava de ativação de escopo bloqueada precisa ser adquirida e transmitida para postEvents ao publicar eventos de ativação para a implementação de vários HALs.

Sensores dinâmicos

Na HAL 1.0 de sensores, os sensores dinâmicos são retornados pela função poll(). Os sensores Multi-HAL 2.0 exigem que onDynamicSensorsConnected e onDynamicSensorsDisconnected em IHalProxyCallback sejam chamados sempre que as conexões dinâmicas do sensor mudam. Esses callbacks estão disponíveis como parte do ponteiro IHalProxyCallback fornecido pela função initialize().

Porta de Sensores Multi-HAL 1.0

Para fazer a portabilidade de uma implementação já existente de Sensores Multi-HAL 1.0, siga estas etapas.

  1. Verifique se a configuração do HAL de sensores está localizada em /vendor/etc/sensors/hals.conf. Isso pode envolver mover o arquivo localizado em /system/etc/sensors/hals.conf.
  2. Remova todas as referências a hardware/hardware.h e hardware/sensors.h, já que elas não têm suporte à HAL 2.0.
  3. Portas sub-HALs, conforme descrito em Portabilidade de sensores Hal 1.0.
  4. Defina o Sensors Multi-HAL 2.0 como o HAL designado seguindo as etapas 3 e 4 na seção Como implementar o Sensors Multi-HAL 2.0.

Validação

Executar VTS

Quando você integrar uma ou mais sub-HALs aos sensores Multi-Hal 2.1, use o Teste de fornecedor (VTS, na sigla em inglês) para garantir que as implementações de sub-HAL atendam a todos os requisitos definidos pela interface da HAL de sensores.

Para executar apenas os testes de VTS dos sensores quando o VTS estiver configurado em uma máquina host, execute os seguintes comandos:

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_0Target && \
  vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_1Target

Se você estiver executando a camada de shim de vários HAL do AIDL, execute VtsAidlHalSensorsTargetTest.

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsAidlHalSensorsTargetTest

Executar testes de unidade

Os testes de unidade no HalProxy_test.cpp testam HalProxy usando sub-HALs falsas que são instanciadas no teste de unidade e não são carregadas dinamicamente. Ao criar uma nova sub-HAL, esses testes precisam servir como um guia sobre como adicionar testes de unidade que verificam se a nova sub-HAL está implementada corretamente.

Para realizar os testes, execute os seguintes comandos:

cd $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests
atest

Testar com sub-HALs falsas

Os sub-HALs falsos são implementações fictícias da interface ISensorsSubHal. As sub-HALs expõem diferentes listas de sensores. Quando os sensores são ativados, eles publicam periodicamente eventos de sensores gerados automaticamente para HalProxy com base nos intervalos especificados em uma determinada solicitação de sensor.

As sub-HALs falsas podem ser usadas para testar como o código Multi-HAL completo funciona com outras sub-HALs carregadas no sistema e para estressar vários aspectos do código da Multi-HAL dos sensores.

Duas sub-HALs falsas estão disponíveis em hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/.

Para criar e enviar as sub-HALs falsas para um dispositivo, siga estas etapas:

  1. Execute os comandos abaixo para criar e enviar os três sub-HALs falsos ao dispositivo:

    $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests/
    mma
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
  2. Atualize a configuração da HAL de sensores em /vendor/etc/sensors/hals.conf com os caminhos das sub-HALs falsas.

    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  3. Reinicie o HalProxy e carregue as novas sub-HALs listadas na configuração.

    adb shell stop
    adb shell start

Depuração

Os desenvolvedores podem depurar o framework usando o comando lshal. Para solicitar a saída de depuração da HAL de sensores, execute o seguinte comando:

adb root
adb shell lshal debug android.hardware.sensors@2.1::ISensors/default

As informações sobre o estado atual da HalProxy e das sub-HALs são saídas para o terminal. Confira abaixo um exemplo da resposta ao comando para o objeto HalProxy e sub-HALs fictícias.

Internal values:
  Threads are running: true
  Wakelock timeout start time: 200 ms ago
  Wakelock timeout reset time: 73208 ms ago
  Wakelock ref count: 0
  # of events on pending write queue: 0
  # of non-dynamic sensors across all subhals: 8
  # of dynamic sensors across all subhals: 0
SubHals (2):
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2

Se o número especificado para # of events on pending write queue for um número grande (1.000 ou mais), isso indica que há muitos eventos pendentes para serem gravados no framework de sensores. Isso indica que o serviço do sensor está bloqueado, falhou e não está processando eventos do sensor ou que um grande lote de eventos do sensor foi publicado recentemente em uma sub-HAL.

Se a contagem de referência de wake lock for maior que 0, isso significa que HalProxy adquiriu um wake lock. Esse valor só será maior que 0 se um ScopedWakelock estiver sendo mantido intencionalmente ou se os eventos de ativação tiverem sido enviados para HalProxy e não tiverem sido processados pelo framework do sensor.

O descritor de arquivos transmitido ao método de depuração HalProxy é transmitido a cada sub-HAL. Os desenvolvedores precisam implementar o método de depuração como parte da interface ISensorsSubHal.