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

La HAL des capteurs 2.0 est disponible dans Android 10 et versions ultérieures pour les appareils nouveaux et mis à niveau. La HAL des capteurs 2.0 est basée sur la HAL des capteurs 1.0 mais présente plusieurs différences clés qui l'empêchent d'être rétrocompatible. La HAL des capteurs 2.0 utilise des files d'attente de messages rapides (FMQ) pour envoyer des événements de capteur de la HAL au framework de capteur Android.

La HAL des capteurs 2.1 est disponible dans Android 11 et versions ultérieures pour les appareils nouveaux et mis à niveau. La HAL des capteurs 2.1 est une itération de la HAL des capteurs 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 la HAL des capteurs 2.1 se trouve dans la HAL définition à l'adresse hardware/interfaces/sensors/2.1/ISensors.hal. En cas de conflit entre les exigences de cette page et ISensors.hal, utilisez l'exigence dans ISensors.hal.

Interface HAL 2.0

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

Implémenter la HAL des capteurs 2.0 et 2.1

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

Initialiser la HAL

La HAL des capteurs doit être initialisée par le framework de capteur Android avant de pouvoir être utilisée. Le framework appelle la fonction initialize() pour la HAL 2.0 et la fonction initialize_2_1() pour la HAL 2.1 afin de fournir trois paramètres à la HAL des capteurs : deux descripteurs FMQ et un pointeur vers un objet ISensorsCallback.

La HAL utilise le premier descripteur pour créer la FMQ d'événement utilisée pour écrire des événements de capteur dans le framework. La HAL utilise le deuxième descripteur pour créer la FMQ de wakelock utilisée pour synchroniser le moment où la HAL libère son wakelock 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 la HAL des capteurs.

Exposer les capteurs disponibles

Pour obtenir la liste de tous les capteurs statiques disponibles sur l'appareil, utilisez la fonction getSensorsList() sur la HAL 2.0 et la fonction getSensorsList_2_1() sur la HAL 2.1. Cette fonction renvoie une liste de capteurs, chacun étant identifié de manière unique par son descripteur. Le descripteur d'un capteur donné ne doit pas changer lorsque le processus hébergeant la HAL des capteurs redémarre. Les descripteurs 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 le redémarrage d'une HAL des capteurs, si les données renvoyées par getSensorsList() ou getSensorsList_2_1() 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 descripteur donné est manquant ou a changé d'attribut, ou lorsque 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 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 requêtes de capteur actives effectuées par les applications. Par conséquent, il est conseillé aux fournisseurs de HAL d'éviter les modifications inutiles de la liste des capteurs.

Pour garantir la stabilité des descripteurs de capteur, la HAL doit mapper de manière déterministe un capteur physique donné de l'appareil à son descripteur. Bien qu'aucune implémentation spécifique ne soit imposée par l'interface HAL des capteurs, les développeurs disposent de plusieurs 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 des capteurs statiques de l'appareil est fixe dans le matériel. La HAL doit donc savoir quand tous les capteurs attendus ont terminé l'initialisation avant de renvoyer des données à partir 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 dériver des descripteurs 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 descripteurs de capteur ne changent pas lors des redémarrages de la HAL.

Configurer les capteurs

Avant d'être activé, un capteur doit être configuré avec une période d'échantillonnage et une latence de rapport 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 rythme continu.
  • En cas de changement : 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 que la période d'échantillonnage si la valeur mesurée ne change pas.
  • Unique : 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 rapport d'un capteur, consultez la section Modes de rapport.

Latence de rapport maximale

La latence de rapport 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 la FMQ d'événement via la 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 du capteur est présent dans le FIFO.

Par exemple, un accéléromètre activé à 50 Hz avec une latence de rapport maximale de zéro déclenche des interruptions 50 fois par seconde lorsque le SoC est actif.

Lorsque la latence de rapport 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 stockés temporairement dans le FIFO matériel et signalés par lot, à condition qu'aucun événement ne soit retardé de plus que la latence de rapport maximale. Tous les événements 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 permet au SoC de passer en mode basse consommation pendant que le capteur capture et regroupe les données.

Chaque événement est associé à un horodatage. Le fait de retarder le moment où 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 au moment où l'événement s'est produit physiquement, et non au moment où il a été signalé.

Pour obtenir des informations et des exigences supplémentaires sur la signalisation des événements de capteur avec une latence de rapport maximale non nulle, consultez la section Traitement 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 de ce capteur ne doivent pas être écrits dans la FMQ d'événement.

Vider les capteurs

Si un capteur est configuré pour regrouper les données des capteurs, le framework peut forcer un vidage immédiat des événements de capteur regroupés en appelant flush(). Les événements de capteur regroupés pour le descripteur de capteur spécifié sont alors immédiatement écrits dans la FMQ d'événement. La 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 autres que les capteurs uniques.

Si flush() est appelé pour un capteur unique, flush() doit renvoyer BAD_VALUE et ne pas générer d'événement de vidage terminé.

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

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

La FMQ d'événement est une FMQ synchronisée, ce qui signifie que toute tentative d'écriture d'un nombre d'événements supérieur à l'espace disponible dans la FMQ 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 forme de deux groupes d'événements plus petits ou écrire tous les événements ensemble lorsque suffisamment d'espace est disponible.

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

La HAL des capteurs 2.0/2.1 est compatible avec write et writeBlocking sur la FMQ d'événement. L'implémentation par défaut fournit une référence pour l'utilisation de write. Si la fonction writeBlocking est utilisée, l'indicateur readNotification doit être défini sur EventQueueFlagBits::EVENTS_READ, qui est défini par le framework lorsqu'il lit des événements à partir de la FMQ d'événement. 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 la FMQ d'événement.

É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 le traitement immédiat de l'événement. Chaque fois qu'un événement WAKE_UP est écrit dans la FMQ d'événement, la HAL des capteurs doit sécuriser un wakelock pour s'assurer que le système reste actif 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 wakelock, ce qui permet à la HAL des capteurs de libérer son wakelock. Pour synchroniser le moment où la HAL des capteurs libère son wakelock, utilisez la FMQ de wakelock.

La HAL des capteurs doit lire la FMQ de verrouillage de réveil pour déterminer le nombre d'événements WAKE_UP gérés par le framework. La HAL ne doit libérer son wakelock pour les événements WAKE_UP que si le nombre total d'événements WAKE_UP non géré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 de verrouillage de réveil chaque fois qu'il écrit des données dans la FMQ de verrouillage de réveil.

Capteurs dynamiques

Les capteurs dynamiques ne font pas physiquement partie de l'appareil, mais peuvent être utilisés comme entrée pour 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 de la HAL des capteurs. Cela informe le framework du nouveau capteur dynamique et permet de le contrôler via le framework et de faire en sorte que les événements du capteur soient utilisés par les clients.

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 de fonctionnement dans laquelle les événements de capteur sont écrits dans une mémoire spécifique au lieu de la FMQ d'événement, en contournant le framework de capteur 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 les événements de capteur via le framework. La fonction configDirectReport() est semblable à batch() pour un fonctionnement normal et configure le canal de rapport direct.

Les fonctions registerDirectChannel() et unregisterDirectChannel() créent ou détruisent un nouveau canal direct.

Modes de fonctionnement

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

La fonction injectSensorData() dans la HAL 2.0 et la fonction injectSensorsData_2_1() dans la HAL 2.0 sont normalement utilisées pour envoyer des paramètres opérationnels à la 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 HAL des capteurs, exécutez les tests CTS et VTS du capteur.

Tests CTS

Les tests CTS du capteur 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 les fonctionnalités standards des capteurs, telles que l'activation des capteurs, le traitement par lot et les taux d'événements de capteur.

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.

La réussite des tests CTS est essentielle pour s'assurer que l'appareil testé répond à toutes les exigences du CDD.

Tests VTS

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

Passer de la HAL des capteurs 2.0 à la 2.1

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

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

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

Passer de la HAL des capteurs 1.0 à la 2.0

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

Initialiser la HAL

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

Exposer les capteurs disponibles

Dans la HAL des capteurs 2.0, la fonction getSensorsList() doit renvoyer la même valeur lors d'un seul démarrage de l'appareil, même lors des redémarrages de la HAL des capteurs. Une nouvelle exigence de la fonction getSensorsList() est qu'elle doit renvoyer la même valeur lors d'un seul démarrage de l'appareil, même lors des redémarrages de la HAL des capteurs. Cela permet au framework de tenter de rétablir les connexions de capteur 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 l'appel de poll(), dans la HAL des capteurs 2.0, la HAL des capteurs doit écrire de manière proactive des événements de capteur dans la FMQ d'événement chaque fois que des événements de capteur sont disponibles. La HAL est également chargée d'écrire les bits corrects dans EventFlag pour provoquer une lecture FMQ dans le framework.

Événements WAKE_UP

Dans la HAL des capteurs 1.0, la HAL pouvait libérer son wakelock pour tout événement WAKE_UP lors de tout appel ultérieur à poll() après la publication d'un événement WAKE_UP dans poll(), car cela indiquait que le framework avait traité tous les événements de capteur et avait obtenu un wakelock, si nécessaire. Étant donné que, dans la HAL des capteurs 2.0, la HAL ne sait plus quand le framework a traité les événements écrits dans la FMQ, la FMQ de verrouillage de réveil permet au framework de communiquer avec la HAL lorsqu'il a géré des événements WAKE_UP.

Dans la HAL des capteurs 2.0, le wakelock sécurisé par la HAL des capteurs 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 la HAL des capteurs 1.0. La HAL des capteurs 2.0 exige que onDynamicSensorsConnected et onDynamicSensorsDisconnected dans ISensorsCallback soient appelés chaque fois que les connexions de capteur dynamique changent. Ces rappels sont disponibles dans le cadre du pointeur ISensorsCallback fourni via la fonction initialize().

Modes de fonctionnement

Le mode DATA_INJECTION pour les capteurs WAKE_UP doit être compatible avec la HAL des capteurs 2.0.

Compatibilité avec la Multi-HAL

La HAL des capteurs 2.0 et 2.1 est compatible avec la Multi-HAL à l'aide du framework Multi-HAL des capteurs. Pour en savoir plus sur l'implémentation, consultez la section Migration à partir de la HAL des capteurs 1.0.