La couche d'abstraction matérielle (HAL) des capteurs est l'interface entre le framework de capteur Android et les capteurs d'un appareil, tels qu'un accéléromètre ou un gyroscope. Le HAL Sensors définit les fonctions qui doivent être implémentées pour permettre au framework de contrôler les capteurs.
Le HAL AIDL Sensors est disponible dans Android 13 et versions ultérieures pour les appareils neufs et mis à niveau. Le HAL AIDL Sensors, basé sur le HAL Sensors 2.1, utilise l'interface HAL AIDL et expose les types de capteurs IMU à axe limité et de suivi de la tête.
Interface HAL AIDL
La principale source de documentation sur le HAL des capteurs AIDL se trouve dans la définition HAL disponible sur hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.
Implémenter le HAL Sensors AIDL
Pour implémenter le HAL AIDL Sensors, un objet doit étendre l'interface ISensors
et implémenter toutes les fonctions définies dans hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.
Initialiser l'HAL
Le HAL des capteurs doit être initialisé par le framework de capteurs Android avant de pouvoir être utilisé. Le framework appelle la fonction initialize()
pour fournir trois paramètres au HAL Sensors: deux descripteurs FMQ et un pointeur vers un objet ISensorsCallback
.
Le HAL utilise le premier descripteur pour créer le FMQ d'événement utilisé pour écrire les événements de capteurs dans le framework. Le HAL utilise le deuxième descripteur pour créer le FMQ de wakelock utilisé pour la synchronisation lorsque le HAL libère son wakelock pour les événements de capteurs WAKE_UP
. Le HAL doit enregistrer un pointeur vers l'objet ISensorsCallback
afin que toutes les fonctions de rappel nécessaires puissent être appelées.
La fonction initialize()
doit être la première fonction appelée lors de l'initialisation du HAL Sensors.
Exposer les capteurs disponibles
Pour obtenir la liste de tous les capteurs statiques disponibles dans l'appareil, utilisez la fonction getSensorsList()
. Cette fonction renvoie une liste de capteurs, chacun étant identifié de manière unique par son handle. La poignée d'un capteur donné ne doit pas changer lorsque le processus hébergeant le HAL Sensors redémarre. Les poignées peuvent changer lors des redémarrages de l'appareil et des redémarrages du serveur système.
Si plusieurs capteurs partagent le même type de capteur et la même propriété de réveil, le premier capteur de la liste est appelé capteur par défaut et est renvoyé aux applications qui utilisent la fonction getDefaultSensor(int sensorType, bool wakeUp)
.
Stabilité de la liste des capteurs
Après un redémarrage du HAL Sensors, si les données renvoyées par getSensorsList()
indiquent un changement important par rapport à la liste des capteurs récupérée avant le redémarrage, le framework déclenche un redémarrage de l'environnement d'exécution Android. Les modifications importantes apportées à la liste des capteurs incluent les cas où un capteur avec un gestionnaire donné est manquant ou a modifié ses attributs, ou où de nouveaux capteurs sont introduits. Bien que le redémarrage de l'environnement d'exécution Android perturbe l'utilisateur, il est nécessaire, car le framework Android ne peut plus respecter le contrat d'API Android selon lequel les capteurs statiques (non dynamiques) ne changent pas pendant la durée de vie d'une application. Cela peut également empêcher le framework de rétablir les requêtes de capteurs actives effectuées par les applications. Par conséquent, les fournisseurs HAL sont invités à éviter les modifications de la liste des capteurs évitables.
Pour garantir des poignées de capteurs stables, le HAL doit mapper de manière déterministe un capteur physique donné de l'appareil sur sa poignée. Bien qu'aucune implémentation spécifique ne soit requise par l'interface HAL des capteurs, les développeurs disposent d'un certain nombre d'options pour répondre à cette exigence.
Par exemple, la liste des capteurs peut être triée à l'aide d'une combinaison des attributs fixes de chaque capteur, tels que le fournisseur, le modèle et le type de capteur. Une autre option repose sur le fait que l'ensemble de capteurs statiques de l'appareil est fixé en matériel. Le HAL doit donc savoir quand tous les capteurs attendus ont terminé l'initialisation avant de revenir de getSensorsList()
. Cette liste de capteurs attendus peut être compilée dans le binaire HAL ou stockée dans un fichier de configuration du système de fichiers. L'ordre d'apparition peut être utilisé pour dériver des poignées stables. Bien que la meilleure solution dépende des détails d'implémentation spécifiques de votre HAL, l'exigence clé est que les poignées de capteur ne changent pas lors des redémarrages du HAL.
Configurer les capteurs
Avant qu'un capteur ne soit activé, il doit être configuré avec une période d'échantillonnage et une latence de signalement maximale à l'aide de la fonction batch()
.
Un capteur doit pouvoir être reconfiguré à tout moment à l'aide de batch()
sans perte de données du capteur.
Période d'échantillonnage
La période d'échantillonnage a une signification différente selon le type de capteur configuré:
- Continu: les événements du capteur sont générés à un débit continu.
- Lors d'une modification: les événements ne sont pas générés plus tôt que la période d'échantillonnage et peuvent être générés à un rythme plus lent que la période d'échantillonnage si la valeur mesurée ne change pas.
- "One-shot" (à un seul coup) : la période d'échantillonnage est ignorée.
- Spécial: Pour en savoir plus, consultez la section Types de capteurs.
Pour en savoir plus sur l'interaction entre une période d'échantillonnage et les modes de création de rapports d'un capteur, consultez la section Modes de création de rapports.
Latence maximale des rapports
La latence de signalement maximale définit la durée maximale (en nanosecondes) pendant laquelle les événements peuvent être retardés et stockés dans le FIFO matériel avant d'être écrits dans le FMQ d'événements via le HAL lorsque le SoC est actif.
Une valeur de zéro signifie que les événements doivent être signalés dès qu'ils sont mesurés, soit en ignorant complètement le FIFO, soit en vidant le FIFO dès qu'un événement provenant du capteur y est présent.
Par exemple, un accéléromètre activé à 50 Hz avec une latence de signalement maximale de zéro déclenche des interruptions 50 fois par seconde lorsque le SoC est actif.
Lorsque la latence de signalement maximale est supérieure à zéro, les événements de capteur n'ont pas besoin d'être signalés dès qu'ils sont détectés. Les événements peuvent être temporairement stockés dans le fichier FIFO du matériel et consignés par lots, à condition qu'aucun événement ne soit retardé de plus que la latence de création de rapports maximale. Tous les événements depuis le lot précédent sont enregistrés et renvoyés en même temps. Cela réduit le nombre d'interruptions envoyées au SoC et lui permet de basculer vers un mode d'économie d'énergie pendant que le capteur capture et regroupe les données.
Chaque événement est associé à un code temporel. Le fait de retarder l'heure à laquelle un événement est signalé ne doit pas avoir d'incidence sur l'horodatage de l'événement. L'horodatage doit être précis et correspondre à l'heure à laquelle l'événement s'est produit physiquement, et non à l'heure à laquelle il a été signalé.
Pour en savoir plus et connaître les exigences concernant la création de rapports sur les événements de capteur avec une latence maximale de création de rapports non nulle, consultez la section Groupement.
Activer les capteurs
Le framework active et désactive les capteurs à l'aide de la fonction activate()
.
Avant d'activer un capteur, le framework doit d'abord le configurer à l'aide de batch()
.
Une fois qu'un capteur est désactivé, aucun événement de capteur supplémentaire de ce capteur ne doit être écrit dans la file de messages de premier plan d'événements.
Capteurs de chasse d'eau
Si un capteur est configuré pour regrouper les données de capteur, le framework peut forcer un vidage immédiat des événements de capteur groupés en appelant flush()
. Ainsi, les événements de capteurs par lot pour le handle de capteur spécifié sont immédiatement écrits dans le FMQ d'événement. Le HAL des capteurs doit ajouter un événement de vidage complet à la fin des événements de capteurs écrits à la suite d'un appel à flush()
.
Le vidage s'effectue de manière asynchrone, c'est-à-dire que cette fonction doit être renvoyée immédiatement. Si l'implémentation utilise un seul FIFO pour plusieurs capteurs, ce FIFO est effacé et l'événement d'effacement complet n'est ajouté que pour le capteur spécifié.
Si le capteur spécifié ne dispose pas de FIFO (pas de mise en tampon possible) ou si le FIFO était vide au moment de l'appel, flush()
doit toujours réussir et envoyer un événement de vidage complet pour ce capteur. Cela s'applique à tous les capteurs, à l'exception des capteurs à déclenchement unique.
Si flush()
est appelé pour un capteur one-shot, flush()
doit renvoyer BAD_VALUE
et ne pas générer d'événement de vidage complet.
Écrire des événements de capteur dans la file de messages FMQ
Le FMQ d'événements est utilisé par le HAL des capteurs pour transmettre des événements de capteur dans le framework de capteurs Android.
Le FMQ d'événement est un FMQ synchronisé, ce qui signifie que toute tentative d'écriture d'un plus grand nombre d'événements dans le FMQ que l'espace disponible ne permet d'échouer l'écriture. Dans ce cas, le HAL doit déterminer s'il doit écrire l'ensemble actuel d'événements en deux groupes d'événements plus petits ou s'il doit écrire tous les événements ensemble lorsque suffisamment d'espace est disponible.
Lorsque le HAL des capteurs a écrit le nombre d'événements de capteur souhaité dans la file de messages de premier plan d'événements, il doit informer le framework que les événements sont prêts en écrivant le bit EventQueueFlagBits::READ_AND_PROCESS
dans la fonction EventFlag::wake
de la file de messages de premier plan d'événements. L'EventFlag peut être créé à partir de l'Event FMQ à l'aide de EventFlag::createEventFlag
et de la fonction getEventFlagWord()
de l'Event FMQ.
Le HAL AIDL Sensors est compatible avec write
et writeBlocking
sur le FMQ d'événements.
L'implémentation par défaut fournit une référence pour l'utilisation de write
. Si la fonction writeBlocking
est utilisée, l'option readNotification
doit être définie sur EventQueueFlagBits::EVENTS_READ
, qui est définie par le framework lorsqu'il lit les événements de la file de messages de premier plan d'événements. L'indicateur de notification d'écriture doit être défini sur EventQueueFlagBits::READ_AND_PROCESS
, ce qui informe le framework que des événements ont été écrits dans le FMQ d'événements.
Événements WAKE_UP
Les événements WAKE_UP
sont des événements de capteur qui provoquent le réveil du processeur d'application (PA) et la gestion immédiate de l'événement. Chaque fois qu'un événement WAKE_UP
est écrit dans le FMQ d'événements, le HAL Sensors doit sécuriser un verrouillage de réveil pour s'assurer que le système reste actif jusqu'à ce que le framework puisse gérer l'événement. À la réception d'un événement WAKE_UP
, le framework sécurise son propre verrouillage de réveil, ce qui permet au HAL des capteurs de libérer son verrouillage de réveil. Pour synchroniser lorsque le HAL des capteurs libère son verrouillage de réveil, utilisez le FMQ de verrouillage de réveil.
Le HAL des capteurs doit lire le FMQ de wakelock pour déterminer le nombre d'événements WAKE_UP
traités par le framework. Le HAL ne doit libérer son verrouillage de réveil que pour les événements WAKE_UP
si le nombre total d'événements WAKE_UP
non gérés est nul.
Après avoir traité les événements de capteur, le framework compte le nombre d'événements marqués comme événements WAKE_UP
et réécrit ce nombre dans la file de messages FMQ Wake Lock.
Le framework définit la notification d'écriture WakeLockQueueFlagBits::DATA_WRITTEN
sur le FMQ Wake Lock chaque fois qu'il écrit des données dans le FMQ Wake Lock.
Capteurs dynamiques
Les capteurs dynamiques sont des capteurs qui ne font pas physiquement partie de l'appareil, mais qui peuvent être utilisés comme entrée de l'appareil, par exemple une manette de jeu avec un accéléromètre.
Lorsqu'un capteur dynamique est connecté, la fonction onDynamicSensorConnected
dans ISensorsCallback
doit être appelée à partir du HAL Sensors. Cela informe le framework du nouveau capteur dynamique et permet de le contrôler via le framework et de permettre aux clients de consommer les événements du capteur.
De même, lorsqu'un capteur dynamique est déconnecté, la fonction onDynamicSensorDisconnected
dans ISensorsCallback
doit être appelée afin que le framework puisse supprimer tout capteur qui n'est plus disponible.
Canal direct
Le canal direct est une méthode d'opération où les événements de capteurs sont écrits dans une mémoire spécifique au lieu d'être écrits dans l'Event FMQ qui contourne le framework des capteurs Android. Un client qui enregistre un canal direct doit lire les événements de capteur directement à partir de la mémoire utilisée pour créer le canal direct et ne recevra pas ces événements via le framework. La fonction configDirectReport()
est semblable à batch()
pour le fonctionnement normal et configure le canal de rapport direct.
Les fonctions registerDirectChannel()
et unregisterDirectChannel()
créent ou détruisent un canal direct.
Modes de fonctionnement
La fonction setOperationMode()
permet au framework de configurer un capteur afin qu'il puisse injecter des données de capteur dans le capteur. Cela est utile pour les tests, en particulier pour les algorithmes qui existent en dessous du framework.
La fonction injectSensorData()
est généralement utilisée pour transmettre des paramètres opérationnels dans le HAL Sensors. La fonction peut également être utilisée pour injecter des événements de capteur dans un capteur spécifique.
Validation
Pour valider votre implémentation du HAL des capteurs, exécutez les tests CTS et VTS des capteurs.
Tests CTS
Les tests CTS des capteurs existent à la fois dans les tests CTS automatisés et dans l'application manuelle CTS Verifier.
Les tests automatisés se trouvent dans cts/tests/sensor/src/android/hardware/cts. Ces tests vérifient le fonctionnement standard des capteurs, comme l'activation des capteurs, le traitement par lot et les taux d'événements des capteurs.
Les tests CTS Verifier se trouvent dans cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors. Ces tests nécessitent une saisie manuelle de la part de l'opérateur de test et garantissent que les capteurs indiquent des valeurs précises.
Il est essentiel que les tests CTS soient réussis pour s'assurer que l'appareil testé répond à toutes les exigences du CDD.
Tests VTS
Les tests VTS pour le HAL Sensors AIDL se trouvent dans hardware/interfaces/sensors/aidl/vts/.
Ces tests garantissent que le HAL des capteurs est implémenté correctement et que toutes les exigences de ISensors.aidl
et ISensorsCallback.aidl
sont correctement respectées.
Initialiser le HAL
La fonction initialize()
doit être prise en charge pour établir des FMQ entre le framework et le HAL.
Exposer les capteurs disponibles
Dans le HAL AIDL Sensors, la fonction getSensorsList()
doit renvoyer la même valeur lors d'un seul démarrage de l'appareil, même lors des redémarrages du HAL Sensors. La fonction getSensorsList()
doit désormais renvoyer la même valeur lors du démarrage d'un seul appareil, même lors des redémarrages du HAL Sensors. Cela permet au framework de tenter de rétablir les connexions des capteurs si le serveur système redémarre. La valeur renvoyée par getSensorsList()
peut changer après un redémarrage de l'appareil.
Écrire des événements de capteur dans la file de messages FMQ
Au lieu d'attendre l'appel de poll()
, dans le HAL Sensors AIDL, le HAL Sensors doit écrire de manière proactive des événements de capteur dans le FMQ d'événements chaque fois qu'ils sont disponibles. Le HAL est également chargé d'écrire les bits appropriés dans EventFlag
pour provoquer une lecture FMQ dans le framework.
Événements WAKE_UP
Dans Sensors HAL 1.0, le HAL pouvait libérer son verrouillage de réveil pour tout événement WAKE_UP
lors de tout appel ultérieur à poll()
après qu'un WAKE_UP
a été publié sur poll()
, car cela indiquait que le framework avait traité tous les événements de capteur et obtenu un verrouillage de réveil, si nécessaire. Dans le HAL Sensors AIDL, le HAL n'est plus informé lorsque le framework a traité les événements écrits dans la file de messages FMQ. Par conséquent, la file de messages FMQ Wake Lock permet au framework de communiquer avec le HAL lorsqu'il a traité des événements WAKE_UP
.
Dans le HAL AIDL Sensors, le verrouillage de réveil sécurisé par le HAL Sensors pour les événements WAKE_UP
doit commencer par SensorsHAL_WAKEUP
.
Capteurs dynamiques
Les capteurs dynamiques étaient renvoyés à l'aide de la fonction poll()
dans Sensors HAL 1.0.
Le HAL AIDL Sensors exige que onDynamicSensorsConnected
et onDynamicSensorsDisconnected
dans ISensorsCallback
soient appelés chaque fois que les connexions de capteurs dynamiques changent. Ces rappels sont disponibles dans le pointeur ISensorsCallback
fourni via la fonction initialize()
.
Modes de fonctionnement
Le mode DATA_INJECTION
des capteurs WAKE_UP
doit être compatible.
Compatibilité multi-HAL
Le HAL AIDL Sensors est compatible avec le multi-HAL à l'aide du framework multi-HAL Sensors. Pour en savoir plus sur l'implémentation, consultez la section Portage à partir de Sensors HAL 2.1.