HAL de sensores AIDL

A camada de abstração de hardware (HAL, na sigla em inglês) de sensores é a interface entre o framework de sensores do Android e os sensores de um dispositivo, como um acelerômetro ou giroscópio. A HAL de sensores define as funções que precisam ser implementadas para permitir que o framework controle os sensores.

A HAL de sensores AIDL está disponível no Android 13 e versões mais recentes para dispositivos novos e atualizados. A HAL de sensores AIDL, que é baseada em HAL de sensores 2.1, usa a interface HAL AIDL e expõe os tipos de sensor principal e de IMU de eixo limitado.

Interface HAL AIDL

A principal fonte de documentação da HAL de sensores AIDL está na definição da HAL em hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.

Implementar a HAL de sensores AIDL

Para implementar a HAL de sensores AIDL, um objeto precisa estender a ISensors interface e implementar todas as funções definidas em hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.

Inicializar a HAL

A HAL de sensores precisa ser inicializada pelo framework de sensores do Android antes de ser usada. O framework chama a função initialize() para fornecer três parâmetros à HAL de sensores: dois descritores de FMQ e um ponteiro para um objeto ISensorsCallback.

A HAL usa o primeiro descritor para criar a FMQ de eventos usada para gravar eventos de sensor no framework. A HAL usa o segundo descritor para criar o wake lock FMQ usado para sincronizar quando a HAL libera o wake lock para eventos de sensor WAKE_UP. A HAL precisa salvar um ponteiro para o objeto ISensorsCallback para que todas as funções de callback necessárias possam ser invocadas.

A função initialize() precisa ser a primeira chamada ao inicializar a HAL de sensores.

Expor sensores disponíveis

Para receber uma lista de todos os sensores estáticos disponíveis no dispositivo, use a função getSensorsList(). Essa função retorna uma lista de sensores, cada um identificado de maneira exclusiva pelo próprio identificador. O identificador de um determinado sensor não pode mudar quando o processo que hospeda a HAL de sensores é reiniciado. Os identificadores podem mudar em reinicializações de dispositivos e de servidores de sistema.

Se vários sensores compartilharem o mesmo tipo de sensor e a mesma propriedade de ativação, o primeiro sensor na lista será chamado de sensor padrão e será retornado aos apps que usam a função getDefaultSensor(int sensorType, bool wakeUp).

Estabilidade da lista de sensores

Após uma reinicialização da HAL de sensores, se os dados retornados por getSensorsList() indicarem uma mudança significativa em comparação com a lista de sensores recuperada antes da reinicialização, o framework vai acionar uma reinicialização do ambiente de execução do Android. Mudanças significativas na lista de sensores incluem casos em que um sensor com um determinado identificador está ausente ou teve atributos alterados ou em que novos sensores são introduzidos. Embora a reinicialização do ambiente de execução do Android seja prejudicial ao usuário, ela é necessária porque o framework do Android não pode mais atender ao contrato da API Android de que sensores estáticos (não dinâmicos) não mudam durante a vida útil de um app. Isso também pode impedir que o framework restabeleça solicitações de sensores ativos feitas por apps. Portanto, é recomendável que os fornecedores de HAL evitem mudanças desnecessárias na lista de sensores.

Para garantir identificadores de sensores estáveis, a HAL precisa mapear deterministicamente um determinado sensor físico no dispositivo para o identificador dele. Embora nenhuma implementação específica seja obrigatória pela interface HAL de sensores, os desenvolvedores têm várias opções disponíveis para atender a esse requisito.

Por exemplo, a lista de sensores pode ser classificada usando uma combinação dos atributos fixos de cada sensor, como fornecedor, modelo e tipo de sensor. Outra opção depende do fato de que o conjunto de sensores estáticos do dispositivo é fixo no hardware. Portanto, a HAL precisa saber quando todos os sensores esperados concluíram a inicialização antes de retornar de getSensorsList(). Essa lista de sensores esperados pode ser compilada no binário da HAL ou armazenada em um arquivo de configuração no sistema de arquivos, e a ordem de aparência pode ser usada para derivar identificadores estáveis. Embora a melhor solução dependa dos detalhes de implementação específicos da HAL, o requisito principal é que os identificadores de sensores não mudem nas reinicializações da HAL.

Configurar sensores

Antes de um sensor ser ativado, ele precisa ser configurado com um período de amostragem e uma latência máxima de relatório usando a função batch().

Um sensor precisa poder ser reconfigurado a qualquer momento usando batch() sem perda de dados do sensor.

Período de amostragem

O período de amostragem tem um significado diferente com base no tipo de sensor que está sendo configurado:

  • Contínuo: os eventos do sensor são gerados em uma taxa contínua.
  • Na mudança: os eventos são gerados no máximo no período de amostragem e podem ser gerados em uma taxa mais lenta do que o período de amostragem se o valor medido não mudar.
  • Único: o período de amostragem é ignorado.
  • Especial: para mais detalhes, consulte Tipos de sensores.

Para saber mais sobre a interação entre um período de amostragem e os modos de relatório de um sensor, consulte Modos de relatório.

Latência máxima de relatório

A latência máxima de relatório define o tempo máximo em nanossegundos que os eventos podem ser atrasados e armazenados no FIFO de hardware antes de serem gravados na FMQ de eventos pela HAL enquanto o SoC está ativo.

Um valor zero significa que os eventos precisam ser informados assim que forem medidos, ignorando o FIFO ou esvaziando-o assim que um evento do sensor estiver presente no FIFO.

Por exemplo, um acelerômetro ativado a 50 Hz com uma latência máxima de relatório de zero aciona interrupções 50 vezes por segundo quando o SoC está ativo.

Quando a latência máxima de relatório é maior que zero, os eventos do sensor não precisam ser informados assim que forem detectados. Os eventos podem ser armazenados temporariamente no FIFO de hardware e informados em lotes, desde que nenhum evento seja atrasado em mais do que a latência máxima de relatório. Todos os eventos desde o lote anterior são gravados e retornados de uma só vez. Isso reduz o número de interrupções enviadas ao SoC e permite que ele mude para um modo de baixa energia enquanto o sensor está capturando e agrupando dados.

Cada evento tem um carimbo de data/hora associado a ele. Atrasar o momento em que um evento é informado não pode afetar o carimbo de data/hora do evento. O carimbo de data/hora precisa ser preciso e corresponder ao momento em que o evento ocorreu fisicamente, não ao momento em que foi informado.

Para mais informações e requisitos sobre como informar eventos de sensor com latência máxima de relatório diferente de zero, consulte Agrupamento.

Ativar sensores

O framework ativa e desativa sensores usando a função activate(). Antes de ativar um sensor, o framework precisa primeiro configurá-lo usando batch().

Depois que um sensor é desativado, outros eventos de sensor desse sensor não podem ser gravados na FMQ de eventos.

Limpar sensores

Se um sensor estiver configurado para agrupar dados de sensor, o framework poderá forçar uma limpeza imediata de eventos de sensor agrupados chamando flush(). Isso faz com que os eventos de sensor agrupados para o identificador de sensor especificado sejam gravados imediatamente na FMQ de eventos. A HAL de sensores precisa anexar um evento de limpeza concluída ao final dos eventos de sensor gravados como resultado de uma chamada para flush().

A limpeza acontece de forma assíncrona, ou seja, essa função precisa retornar imediatamente. Se a implementação usar um único FIFO para vários sensores, esse FIFO será limpo e o evento de limpeza concluída será adicionado apenas para o sensor especificado.

Se o sensor especificado não tiver FIFO (nenhum buffer possível) ou se o FIFO estiver vazio no momento da chamada, flush() ainda precisará ser bem-sucedido e enviar um evento de limpeza concluída para esse sensor. Isso se aplica a todos os sensores, exceto os de disparo único.

Se flush() for chamado para um sensor de disparo único, flush() precisará retornar BAD_VALUE e não gerar um evento de limpeza concluída.

Gravar eventos de sensor na FMQ

A FMQ de eventos é usada pela HAL de sensores para enviar eventos de sensor para o framework de sensores do Android.

A FMQ de eventos é uma FMQ sincronizada, o que significa que qualquer tentativa de gravar mais eventos na FMQ do que o espaço disponível permite resulta em uma gravação com falha. Nesse caso, a HAL precisa determinar se vai gravar o conjunto atual de eventos como dois grupos menores de eventos ou gravar todos os eventos juntos quando houver espaço suficiente.

Quando a HAL de sensores tiver gravado o número desejado de eventos de sensor na FMQ de eventos, ela precisará notificar o framework de que os eventos estão prontos gravando o bit EventQueueFlagBits::READ_AND_PROCESS na função EventFlag::wake da FMQ de eventos. O EventFlag pode ser criado na FMQ de eventos usando EventFlag::createEventFlag e a função getEventFlagWord() da FMQ de eventos.

A HAL de sensores AIDL oferece suporte a write e writeBlocking na FMQ de eventos. A implementação padrão fornece uma referência para usar write. Se a função writeBlocking for usada, o flag readNotification precisará ser definido como EventQueueFlagBits::EVENTS_READ, que é definido pelo framework quando ele lê eventos da FMQ de eventos. O flag de notificação de gravação precisa ser definido como EventQueueFlagBits::READ_AND_PROCESS, que notifica o framework de que os eventos foram gravados na FMQ de eventos.

Eventos WAKE_UP

Os eventos WAKE_UP são eventos de sensor que fazem com que o processador de aplicativos (AP) seja ativado e processe o evento imediatamente. Sempre que um evento WAKE_UP é gravado na FMQ de eventos, a HAL de sensores precisa proteger um wake lock para garantir que o sistema permaneça ativo até que o framework possa processar o evento. Ao receber um evento WAKE_UP, o framework protege o próprio wake lock, permitindo que a HAL de sensores libere o wake lock. Para sincronizar quando a HAL de sensores libera o wake lock, use a FMQ de wake lock.

A HAL de sensores precisa ler a FMQ de bloqueio de ativação para determinar o número de eventos WAKE_UP que o framework processou. A HAL só poderá liberar o wake lock para eventos WAKE_UP se o número total de eventos WAKE_UP não processados for zero. Depois de processar eventos de sensor, o framework conta o número de eventos marcados como WAKE_UP e grava esse número de volta na FMQ de bloqueio de ativação.

O framework define a notificação de gravação WakeLockQueueFlagBits::DATA_WRITTEN na FMQ de bloqueio de ativação sempre que grava dados nela.

Sensores dinâmicos

Sensores dinâmicos são sensores que não fazem parte fisicamente do dispositivo, mas podem ser usados como entrada para o dispositivo, como um gamepad com um acelerômetro.

Quando um sensor dinâmico é conectado, a função onDynamicSensorConnected em ISensorsCallback precisa ser chamada na HAL de sensores. Isso notifica o framework do novo sensor dinâmico e permite que o sensor seja controlado pelo framework e que os eventos do sensor sejam consumidos pelos clientes.

Da mesma forma, quando um sensor dinâmico é desconectado, a função onDynamicSensorDisconnected em ISensorsCallback precisa ser chamada para que o framework possa remover qualquer sensor que não esteja mais disponível.

Canal direto

O canal direto é um método de operação em que os eventos do sensor são gravados em uma memória específica em vez de na FMQ de eventos, ignorando o framework de sensores do Android. Um cliente que registra um canal direto precisa ler os eventos do sensor diretamente da memória usada para criar o canal direto e não vai receber os eventos do sensor pelo framework. A função configDirectReport() é semelhante a batch() para operação normal e configura o canal de relatório direto.

As funções registerDirectChannel() e unregisterDirectChannel() criam ou destroem um novo canal direto.

Modos de operação

A função setOperationMode() permite que o framework configure um sensor para que ele possa injetar dados do sensor no sensor. Isso é útil para testes, especialmente para algoritmos que existem abaixo do framework.

A função injectSensorData() é normalmente usada para enviar parâmetros operacionais para a HAL de sensores. A função também pode ser usada para injetar eventos de sensor em um sensor específico.

Validação

Para validar a implementação da HAL de sensores, execute os testes de sensor CTS e VTS.

Testes CTS

Os testes de sensor CTS existem em testes CTS automatizados e no app manual CTS Verifier.

Os testes automatizados estão localizados em cts/tests/sensor/src/android/hardware/cts. Esses testes verificam a funcionalidade padrão dos sensores, como ativação, agrupamento e taxas de eventos de sensor.

Os testes do CTS Verifier estão localizados em cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors. Esses testes exigem entrada manual do operador de teste e garantem que os sensores informem valores precisos.

A aprovação nos testes CTS é fundamental para garantir que o dispositivo em teste atenda a todos os requisitos do CDD.

Testes VTS

Os testes VTS para a HAL de sensores AIDL estão localizados em hardware/interfaces/sensors/aidl/vts/. Esses testes garantem que a HAL de sensores seja implementada corretamente e que todos os requisitos em ISensors.aidl e ISensorsCallback.aidl sejam atendidos corretamente.

Inicializar a HAL

A função initialize() precisa ser compatível para estabelecer FMQs entre o framework e a HAL.

Expor sensores disponíveis

Na HAL de sensores AIDL, a função getSensorsList() precisa retornar o mesmo valor durante uma única inicialização do dispositivo, mesmo em reinicializações da HAL de sensores. Um novo requisito da função getSensorsList() é que ela precisa retornar o mesmo valor durante uma única inicialização do dispositivo, mesmo em reinicializações da HAL de sensores. 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.

Gravar eventos de sensor na FMQ

Em vez de esperar que poll() seja chamado, na HAL de sensores AIDL, a HAL de sensores precisa gravar proativamente eventos de sensor na FMQ de eventos sempre que eles estiverem disponíveis. A HAL também é responsável por gravar os bits corretos em EventFlag para causar uma leitura de FMQ no framework.

Eventos WAKE_UP

Na HAL de sensores 1.0, a HAL podia liberar o wake lock para qualquer evento WAKE_UP em qualquer chamada subsequente para poll() depois que um WAKE_UP era postado em poll(), porque isso indicava que o framework havia processado todos os eventos de sensor e obtido um wake lock, se necessário. Como, na HAL de sensores AIDL, a HAL não é mais notificada quando o framework processa eventos gravados na FMQ, a FMQ de bloqueio de ativação permite que o framework se comunique com a HAL quando processa eventos WAKE_UP.

Na HAL de sensores AIDL, o wake lock protegido pela HAL de sensores para eventos WAKE_UP precisa começar com SensorsHAL_WAKEUP.

Sensores dinâmicos

Os sensores dinâmicos foram retornados usando a função poll() na HAL de sensores 1.0. A HAL de sensores AIDL exige que onDynamicSensorsConnected e onDynamicSensorsDisconnected em ISensorsCallback sejam chamados sempre que as conexões de sensores dinâmicos mudarem. Esses callbacks estão disponíveis como parte do ponteiro ISensorsCallback fornecido pela função initialize().

Modos de operação

O modo DATA_INJECTION para sensores WAKE_UP precisa ser compatível.

Suporte a várias HALs

A HAL de sensores AIDL oferece suporte a várias HALs usando o framework de várias HALs de sensores. Para detalhes de implementação, consulte Como migrar da HAL de sensores 2.1.