Sensors HAL 2.0

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 des capteurs définit les fonctions qui doivent être implémentées pour permettre au framework de contrôler les capteurs.

Sensors HAL 2.0 est disponible dans Android 10 et versions ultérieures pour les appareils nouveaux et mis à niveau. Sensors HAL 2.0 est basé sur Sensors HAL 1.0, mais présente plusieurs différences clés qui l'empêchent d'être rétrocompatible. Sensors HAL 2.0 utilise des Fast Message Queues (FMQ) pour envoyer des événements de capteur du HAL au framework de capteur Android.

Le HAL 2.1 des capteurs est disponible dans Android 11 et versions ultérieures pour les appareils nouveaux et mis à niveau. Sensors HAL 2.1 est une itération de Sensors HAL 2.0 qui expose le type de capteur HINGE_ANGLE et met à jour différentes méthodes pour accepter le type HINGE_ANGLE.

Interface HAL 2.1

La principale source de documentation pour Sensors HAL 2.1 se trouve dans la définition HAL à l'adresse hardware/interfaces/sensors/2.1/ISensors.hal. En cas de conflit d'exigences entre cette page et ISensors.hal, utilisez l'exigence de ISensors.hal.

Interface HAL 2.0

La principale source de documentation pour Sensors HAL 2.0 se trouve dans la définition HAL à l'adresse hardware/interfaces/sensors/2.0/ISensors.hal. En cas de conflit d'exigences entre cette page et ISensors.hal, utilisez l'exigence de ISensors.hal.

Implémenter Sensors HAL 2.0 et HAL 2.1

Pour implémenter Sensors HAL 2.0 ou 2.1, un objet doit étendre l'interface ISensors et implémenter toutes les fonctions définies dans 2.0/ISensors.hal ou 2.1/ISensors.hal.

Initialiser le 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 HAL 2.0 et la fonction initialize_2_1() pour HAL 2.1 afin de fournir trois paramètres à Sensors HAL : 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 capteur dans le framework. Le HAL utilise le deuxième descripteur pour créer le FMQ Wake Lock utilisé pour la synchronisation lorsque le HAL libère son verrouillage de réveil pour les événements de capteur WAKE_UP. La 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() ou initialize_2_1() doit être la première fonction appelée lors de l'initialisation de Sensors HAL.

Exposer les capteurs disponibles

Pour obtenir la liste de tous les capteurs statiques disponibles sur l'appareil, utilisez la fonction getSensorsList() sur HAL 2.0 et la fonction getSensorsList_2_1() sur HAL 2.1. Cette fonction renvoie une liste de capteurs, chacun étant identifié de manière unique par son identifiant. Le handle d'un capteur donné ne doit pas changer lorsque le processus hébergeant le HAL des capteurs redémarre. Les identifiants peuvent changer lors du redémarrage de l'appareil et 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 de Sensors HAL, si les données renvoyées par getSensorsList() ou getSensorsList_2_1() indiquent un changement important par rapport à la liste de capteurs récupérée avant le redémarrage, le framework déclenche un redémarrage du runtime Android. Les modifications importantes apportées à la liste des capteurs incluent les cas où un capteur avec un identifiant donné est manquant ou a changé d'attributs, ou lorsque de nouveaux capteurs sont introduits. Bien que le redémarrage de l'environnement d'exécution Android soit perturbant pour l'utilisateur, il est nécessaire, car le framework Android ne peut plus respecter le contrat de l'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 demandes de capteurs actifs effectuées par les applications. Par conséquent, il est conseillé aux fournisseurs HAL d'éviter les modifications inutiles de la liste des capteurs.

Pour garantir des handles de capteur stables, la HAL doit mapper de manière déterministe un capteur physique donné de l'appareil à son handle. Bien que l'interface Sensors HAL n'impose aucune implémentation spécifique, les développeurs disposent de plusieurs options pour répondre à cette exigence.

Par exemple, la liste des capteurs peut être triée en combinant les 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 des capteurs statiques de l'appareil est fixe dans le matériel. Le HAL doit donc savoir quand tous les capteurs attendus ont terminé l'initialisation avant de revenir de getSensorsList() ou getSensorsList_2_1(). 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 obtenir des handles 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 identifiants de capteur ne changent pas lors des redémarrages du HAL.

Configurer les capteurs

Avant d'être activé, un capteur 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.

Période d'échantillonnage

La période d'échantillonnage a une signification différente selon le type de capteur configuré :

  • Continu : les événements de capteur sont générés à un taux continu.
  • "On-change" : les événements ne sont pas générés plus rapidement que la période d'échantillonnage et peuvent être générés à un rythme plus lent si la valeur mesurée ne change pas.
  • One-shot : la période d'échantillonnage est ignorée.
  • Spécial : pour en savoir plus, consultez Types de capteurs.

Pour en savoir plus sur l'interaction entre une période d'échantillonnage et les modes de rapport d'un capteur, consultez Modes de rapport.

Latence maximale des rapports

La latence maximale des rapports 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 le vidant dès qu'un événement du capteur est présent dans le FIFO.

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 en veille.

Lorsque la latence maximale des rapports 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 stockés temporairement dans le FIFO matériel et signalés par lots, à condition qu'aucun événement ne soit retardé de plus que la latence de signalement maximale. Tous les événements survenus depuis le lot précédent sont enregistrés et renvoyés en une seule fois. Cela réduit le nombre d'interruptions envoyées au SoC et lui permet de passer en mode basse consommation pendant que le capteur capture et regroupe les données.

Chaque événement est associé à un code temporel. Le fait de retarder le moment où un événement est signalé ne doit pas avoir d'incidence sur son code temporel. 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 sur les exigences concernant le signalement d'événements de capteur avec une latence de signalement maximale non nulle, consultez Regroupement par lot.

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 un capteur désactivé, les événements de capteur supplémentaires provenant de ce capteur ne doivent pas être écrits dans la FMQ d'événements.

Capteurs encastrés

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 regroupés en appelant flush(). Cela entraîne l'écriture immédiate des événements de capteur par lot pour le handle de capteur spécifié dans la FMQ d'événements. Le HAL des capteurs doit ajouter un événement de vidage terminé à la fin des événements de capteur écrits à la suite d'un appel à flush().

Le vidage se produit de manière asynchrone (c'est-à-dire que cette fonction doit renvoyer immédiatement un résultat). Si l'implémentation utilise un seul FIFO pour plusieurs capteurs, ce FIFO est vidé et l'événement de vidage terminé n'est ajouté que pour le capteur spécifié.

Si le capteur spécifié n'a pas de FIFO (aucune mise en mémoire tampon possible) ou si le FIFO était vide au moment de l'appel, flush() doit quand même réussir et envoyer un événement de vidage terminé pour ce capteur. Cela s'applique à tous les capteurs, à l'exception des capteurs à usage unique.

Si flush() est appelé pour un capteur ponctuel, 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 FMQ

La FMQ d'événements est utilisée par la HAL des capteurs pour envoyer des événements de capteur dans le framework de capteurs Android.

La FMQ d'événements est une FMQ synchronisée, ce qui signifie que toute tentative d'écrire plus d'événements dans la FMQ que l'espace disponible ne le permet entraîne un échec de l'écriture. Dans ce cas, la HAL doit déterminer s'il faut écrire l'ensemble actuel d'événements sous la forme de deux groupes d'événements plus petits ou écrire tous les événements ensemble lorsqu'il y a suffisamment d'espace.

Lorsque la HAL des capteurs a écrit le nombre souhaité d'événements de capteur dans la FMQ d'événements, elle 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 FMQ d'événements. EventFlag peut être créé à partir de l'Event FMQ à l'aide de EventFlag::createEventFlag et de la fonction getEventFlagWord() de l'Event FMQ.

Les HAL de capteurs 2.0/2.1 sont compatibles avec write et writeBlocking sur la 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, ce qui est défini par le framework lorsqu'il lit les événements à partir de la FMQ d'événements. L'indicateur de notification d'écriture doit être défini sur EventQueueFlagBits::READ_AND_PROCESS, ce qui indique au framework que des événements ont été écrits dans la FMQ d'événements.

Événements WAKE_UP

Les événements WAKE_UP sont des événements de capteur qui entraînent le réveil du processeur d'application (AP) et la gestion immédiate de l'événement. Chaque fois qu'un événement WAKE_UP est écrit dans la FMQ d'événements, la couche HAL des capteurs doit sécuriser un verrouillage de réveil pour s'assurer que le système reste éveillé jusqu'à ce que le framework puisse gérer l'événement. Lorsqu'il reçoit un événement WAKE_UP, le framework sécurise son propre verrouillage de réveil, ce qui permet à la couche d'abstraction matérielle des capteurs de libérer son verrouillage de réveil. Pour synchroniser le moment où la HAL des capteurs libère son verrouillage de réveil, utilisez le FMQ Wake Lock.

Le HAL des capteurs doit lire le FMQ Wake Lock pour déterminer le nombre d'événements WAKE_UP gérés par le framework. Le HAL ne doit libérer son verrouillage de réveil pour les événements WAKE_UP que si le nombre total d'événements WAKE_UP non traités est nul. Après avoir géré 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 FMQ de verrouillage de réveil.

Le framework définit la notification d'écriture WakeLockQueueFlagBits::DATA_WRITTEN sur la FMQ Wake Lock chaque fois qu'il écrit des données dans la FMQ Wake Lock.

Capteurs dynamiques

Les capteurs dynamiques ne font pas physiquement partie de l'appareil, mais peuvent être utilisés comme entrée pour l'appareil, comme 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 de Sensors HAL. Cela permet d'informer le framework du nouveau capteur dynamique et de contrôler le capteur 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 pour que le framework puisse supprimer tout capteur qui n'est plus disponible.

Canal direct

Le canal direct est une méthode de fonctionnement dans laquelle les événements de capteur sont écrits dans une mémoire spécifique au lieu de l'être dans le FMQ d'événement, en contournant le framework Android Sensors. Un client qui enregistre un canal direct doit lire les événements du capteur directement à partir de la mémoire utilisée pour créer le canal direct et ne recevra pas les événements du capteur 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 suppriment un canal direct.

Modes de fonctionnement

La fonction setOperationMode() permet au framework de configurer un capteur afin qu'il puisse y injecter des données. Cela est utile pour les tests, en particulier pour les algorithmes qui existent en dessous du framework.

La fonction injectSensorData() dans HAL 2.0 et la fonction injectSensorsData_2_1() dans HAL 2.0 sont normalement utilisées pour transmettre des paramètres opérationnels dans le HAL des capteurs. 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 de la couche 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 permettent de vérifier les fonctionnalités standards 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 l'opérateur de test et garantissent que les capteurs signalent des valeurs précises.

Il est essentiel de réussir les tests CTS pour s'assurer que l'appareil testé répond à toutes les exigences du CDD.

Tests VTS

Les tests VTS pour Sensors HAL 2.0 se trouvent dans hardware/interfaces/sensors/2.0/vts. Les tests VTS pour Sensors HAL 2.1 se trouvent dans hardware/interfaces/sensors/2.1/vts. Ces tests permettent de s'assurer que la HAL des capteurs est correctement implémentée et que toutes les exigences de ISensors.hal et ISensorsCallback.hal sont respectées.

Mettre à niveau Sensors HAL 2.0 vers 2.1

Lorsque vous passez de Sensors HAL 2.0 à Sensors HAL 2.1, votre implémentation HAL doit inclure les méthodes initialize_2_1(), getSensorsList_2_1() et injectSensorsData_2_1(), ainsi que les types HAL 2.1. Ces méthodes doivent répondre aux mêmes exigences que celles décrites ci-dessus pour HAL 2.0.

Étant donné que les HAL de version mineure doivent prendre en charge toutes les fonctions des HAL précédentes, les HAL 2.1 doivent pouvoir être initialisés en tant que HAL 2.0. Pour éviter la complexité liée à la prise en charge des deux versions HAL, il est fortement recommandé d'utiliser Multi-HAL 2.1.

Pour obtenir un exemple d'implémentation de votre propre HAL Sensors 2.1, consultez Sensors.h.

Mettre à niveau Sensors HAL 1.0 vers 2.0

Lorsque vous passez de Sensors HAL 1.0 à 2.0, assurez-vous que votre implémentation HAL répond aux exigences suivantes.

Initialiser le HAL

La fonction initialize() doit être compatible pour établir des FMQ entre le framework et HAL.

Exposer les capteurs disponibles

Dans Sensors HAL 2.0, la fonction getSensorsList() doit renvoyer la même valeur lors d'un même démarrage de l'appareil, même en cas de redémarrage de Sensors HAL. Une nouvelle exigence de la fonction getSensorsList() est qu'elle doit renvoyer la même valeur lors d'un même démarrage de l'appareil, même en cas de redémarrage de Sensors HAL. 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 le redémarrage de l'appareil.

Écrire des événements de capteur dans la FMQ

Au lieu d'attendre que poll() soit appelé, dans Sensors HAL 2.0, le Sensors HAL doit écrire de manière proactive les événements de capteur dans l'Event FMQ chaque fois que des événements de capteur sont disponibles. Le HAL est également responsable de l'écriture des bits corrects 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 la publication d'un WAKE_UP sur poll(), car cela indiquait que le framework avait traité tous les événements de capteur et avait obtenu un verrouillage de réveil, si nécessaire. Dans Sensors HAL 2.0, le HAL ne sait plus quand le framework a traité les événements écrits dans la FMQ. La FMQ Wake Lock permet au framework de communiquer avec le HAL lorsqu'il a géré les événements WAKE_UP.

Dans Sensors HAL 2.0, le verrouillage de réveil sécurisé par Sensors HAL pour les événements WAKE_UP doit commencer par SensorsHAL_WAKEUP.

Capteurs dynamiques

Les capteurs dynamiques ont été renvoyés à l'aide de la fonction poll() dans Sensors HAL 1.0. Sensors HAL 2.0 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 par la fonction initialize().

Modes de fonctionnement

Le mode DATA_INJECTION pour les capteurs WAKE_UP doit être pris en charge dans Sensors HAL 2.0.

Compatibilité avec Multi-HAL

Les HAL de capteurs 2.0 et 2.1 sont compatibles avec le multi-HAL à l'aide du framework Sensors Multi-HAL. Pour en savoir plus sur l'implémentation, consultez Portage depuis Sensors HAL 1.0.