A camada de abstração de hardware de sensores (HAL, na sigla em inglês) é a interface entre o framework de sensores do Android e os sensores de um dispositivo, como um acelerômetro ou giroscópio. O 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 na HAL de sensores 2.1, usa a HAL de interface AIDL e expõe o rastreador de cabeça e os tipos de sensor de IMU de eixo limitado.
Interface HAL da AIDL
A principal fonte de documentação da HAL de sensores AIDL está na definição 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 interface ISensors
e implementar todas as funções definidas em
hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.
Inicializar o HAL
A HAL de sensores precisa ser inicializada pelo Android Sensors Framework 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
do sensor no framework. A HAL usa o segundo descritor para criar a FMQ de trava de ativação
usada para sincronizar quando a HAL libera a trava de ativação para eventos do sensor
WAKE_UP
. O 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 função chamada ao inicializar
o HAL de sensores.
Expor os sensores disponíveis
Para conferir 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 forma exclusiva pelo handle. O identificador de um determinado sensor não pode mudar
quando o processo que hospeda a HAL de sensores é reiniciado. Os identificadores podem mudar entre
as reinicializações do dispositivo e as reinicializações do servidor do sistema.
Se vários sensores compartilharem o mesmo tipo de sensor e a mesma propriedade de ativação, o
primeiro sensor da lista será chamado de padrão e será retornado para
apps que usam a função
getDefaultSensor(int sensorType, bool wakeUp)
.
Estabilidade da lista de sensores
Após uma reinicialização do 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 do Android que sensores estáticos (não dinâmicos) não mudam durante a
duração de um app. Isso também pode impedir que o framework restabeleça
solicitações de sensores ativos feitas por apps. Portanto, os fornecedores de HAL são aconselhados a
evitar mudanças evitáveis na lista de sensores.
Para garantir identificadores de sensores estáveis, o HAL precisa mapear de forma determinística um determinado sensor físico no dispositivo para o identificador. 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, o
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 HAL ou armazenada em um
arquivo de configuração no sistema de arquivos, e a ordem de aparição pode ser usada
para extrair identificadores estáveis. Embora a melhor solução dependa dos detalhes específicos
de implementação da HAL, o principal requisito é que os identificadores de sensores
não mudem durante as reinicializações da HAL.
Configurar sensores
Antes de um sensor ser ativado, ele precisa ser configurado com um período
de amostragem e latência máxima de relatórios usando a função batch()
.
Um sensor precisa ser reconfigurado a qualquer momento usando batch()
sem a
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 a uma taxa contínua.
- On-change: os eventos são gerados no mesmo 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.
- One-shot: 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órios
A latência máxima de relatórios define o tempo máximo em nanossegundos que os eventos podem ser atrasados e armazenados no FIFO de hardware antes de serem gravados no FMQ de eventos pelo HAL enquanto o SoC está ativo.
Um valor de zero significa que os eventos precisam ser informados assim que forem medidos, pulando o FIFO completamente 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órios é maior que zero, os eventos do sensor não precisam ser informados assim que são detectados. Os eventos podem ser armazenados temporariamente no FIFO de hardware e informados em lotes, desde que nenhum evento seja atrasado por mais do que a latência máxima de relatórios. Todos os eventos desde o lote anterior são registrados 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 menor consumo de energia enquanto o sensor captura e agrupa dados.
Cada evento tem um carimbo de data/hora associado a ele. O atraso no horário 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 relatado.
Para mais informações e requisitos sobre como informar eventos do sensor com latência máxima diferente de zero, consulte Processamento em lote.
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 desse sensor não podem ser gravados no FMQ de eventos.
Sensores de descarga
Se um sensor estiver configurado para agrupar dados, o framework poderá forçar
um flush imediato de eventos de sensores 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. O HAL de sensores precisa anexar um evento de limpeza completo
ao final dos eventos de sensores que são 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 conclusão de limpeza será adicionado apenas para o sensor especificado.
Se o sensor especificado não tiver FIFO (sem buffer possível) ou se o FIFO estiver
vazio no momento da chamada, flush()
ainda precisa ter sucesso e enviar um evento de
limpeza completo para esse sensor. Isso se aplica a todos os sensores, exceto os de
um único disparo.
Se flush()
for chamado para um sensor único, flush()
precisará retornar
BAD_VALUE
e não gerar um evento de flush completo.
Gravar eventos de sensor no FMQ
A FMQ de eventos é usada pela HAL de sensores para enviar eventos de sensores 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 falha. Nesse caso, o HAL precisa determinar se vai gravar o conjunto atual de eventos como dois grupos menores ou se vai gravar todos os eventos juntos quando houver espaço suficiente.
Quando a HAL de sensores grava o número desejado de eventos do sensor na
FMQ de eventos, ela precisa 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. A flag de evento pode ser criada no FMQ de evento
usando EventFlag::createEventFlag
e a função getEventFlagWord()
do FMQ de evento.
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, a flag readNotification
precisa ser definida como
EventQueueFlagBits::EVENTS_READ
, que é definida pelo framework quando ele lê
eventos do FMQ de eventos. A flag de notificação de gravação precisa ser definida como
EventQueueFlagBits::READ_AND_PROCESS
, que notifica o framework de que os eventos
foram gravados no FMQ de eventos.
Eventos WAKE_UP
Os eventos WAKE_UP
são eventos de sensor que fazem com que o processador do aplicativo (AP, na sigla em inglês)
acorde e processe o evento imediatamente. Sempre que um evento WAKE_UP
é gravado
na FMQ de eventos, a HAL de sensores precisa proteger um bloqueio de ativação 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 o
HAL de sensores libere o wake lock. Para sincronizar quando a HAL de sensores
liberar a trava de ativação, use a FMQ de trava de ativação.
O HAL de sensores precisa ler o FMQ de bloqueio de ativação para determinar o número de eventos WAKE_UP
que o framework processou. O HAL só vai liberar o bloqueio de ativação
para eventos WAKE_UP
se o número total de eventos WAKE_UP
não processados for zero.
Depois de processar os eventos do sensor, o framework conta o número de eventos
marcados como WAKE_UP
e grava esse número no FMQ do Wake Lock.
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 física 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 pelo HAL de sensores. Isso notifica o
framework do novo sensor dinâmico e permite que ele 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
recebe 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 injetar dados nele. 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
em um sensor específico.
Validação
Para validar a implementação da HAL de sensores, execute os testes CTS e VTS de sensores.
Testes CTS
Os testes do sensor CTS existem nos testes automatizados do CTS e no app manual do 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 ativar sensores, agrupamento e taxas de eventos de sensores.
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 do CTS é essencial para garantir que o dispositivo em teste atenda a todos os requisitos do CDD.
Testes VTS
Os testes VTS da HAL de sensores AIDL estão localizados em
hardware/interfaces/sensors/aidl/vts/.
Esses testes garantem que o HAL de sensores seja implementado corretamente e que todos
os requisitos em ISensors.aidl
e ISensorsCallback.aidl
sejam atendidos corretamente.
Inicializar o HAL
A função initialize()
precisa ter suporte para estabelecer FMQs entre o
framework e a HAL.
Expor os sensores disponíveis
No HAL de sensores AIDL, a função getSensorsList()
precisa retornar o mesmo valor
durante uma única inicialização do dispositivo, mesmo em reinicializações do 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 do Sensors HAL. Isso permite que o
framework tente restabelecer as conexões do sensor se o servidor do sistema
for reinicializado. O valor retornado por getSensorsList()
pode mudar depois que o dispositivo
é reinicializado.
Gravar eventos de sensor no FMQ
Em vez de esperar que poll()
seja chamado, na HAL de sensores AIDL, a HAL
de sensores precisa gravar proativamente eventos do sensor na FMQ de eventos sempre que eles
estiverem disponíveis. O 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 bloqueio de ativação para qualquer evento WAKE_UP
em qualquer chamada subsequente para poll()
depois que uma WAKE_UP
foi postada para
poll()
, porque isso indicava que o framework havia processado todos os eventos
do sensor e recebido um bloqueio de ativação, se necessário. Como, na HAL do Sensors AIDL, a HAL não é mais notificada quando o framework processa eventos
gravados na FMQ, a FMQ do Wake Lock permite que o framework se comunique com a
HAL quando ela processa eventos WAKE_UP
.
Na HAL de sensores AIDL, a trava de ativação protegida 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 1.0 de sensores.
O Sensors AIDL HAL exige que onDynamicSensorsConnected
e
onDynamicSensorsDisconnected
em ISensorsCallback
sejam chamados sempre que as conexões
dinâmicas do sensor 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ários HALs
A HAL de sensores AIDL oferece suporte a vários HALs usando o framework de sensores multi-HAL. Para detalhes de implementação, consulte Portar da HAL 2.1 de sensores.