HAL Sensors AIDL

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 AIDL des capteurs est disponible dans Android 13 et versions ultérieures pour les appareils nouveaux et mis à niveau. La HAL AIDL des capteurs, basée sur la HAL des capteurs 2.1, utilise l' interface HAL AIDL et expose les types de capteurs de suivi de la tête et d'IMU à axe limité.

Interface HAL AIDL

La principale source de documentation pour la HAL AIDL des capteurs se trouve dans la définition HAL à l'adresse hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.

Implémenter la HAL AIDL des capteurs

Pour implémenter la HAL AIDL des capteurs, un objet doit étendre l'ISensors interface et implémenter toutes les fonctions définies dans hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.

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 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 l'Event FMQ utilisé pour écrire les événements de capteur dans le framework. La HAL utilise le deuxième descripteur pour créer le Wake Lock FMQ utilisé pour synchroniser le moment où la 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() 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(). Cette fonction renvoie une liste de capteurs, chacun étant identifié de manière unique par son handle. Le handle d'un capteur donné ne doit pas changer lorsque le processus hébergeant la HAL des capteurs redémarre. Les handles 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 de la HAL des capteurs, 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 handle 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 handles de capteur, la HAL doit mapper de manière déterministe un capteur physique donné de l'appareil à son handle. 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 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 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 handles 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 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 l'Event FMQ 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 lots, à 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 code temporel. Le fait de retarder le moment où un événement est signalé ne doit pas avoir d'incidence sur le code temporel de l'événement. Le code temporel 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 le signalement des événements de capteur avec une latence de rapport maximale non nulle, consultez la section Regroupement.

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 l'Event FMQ.

Vider les capteurs

Si un capteur est configuré pour regrouper les données des capteurs, le framework peut forcer une vidange immédiate des événements de capteur regroupés en appelant flush(). Les événements de capteur regroupés pour le handle de capteur spécifié sont alors immédiatement écrits dans l'Event FMQ. La HAL des capteurs doit ajouter un événement de vidange terminée à la fin des événements de capteur écrits à la suite d'un appel à flush().

La vidange se produit de manière asynchrone (c'est-à-dire que cette fonction doit renvoyer immédiatement). Si l'implémentation utilise un seul FIFO pour plusieurs capteurs, ce FIFO est vidé et l'événement de vidange terminée 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 vidange terminée 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 vidange terminée.

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

L'Event FMQ est utilisé par la HAL des capteurs pour envoyer des événements de capteur au framework de capteur Android.

L'Event FMQ est un FMQ synchronisé, ce qui signifie que toute tentative d'écriture d'un nombre d'événements supérieur à l'espace disponible dans le 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 l'Event FMQ, 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 l'Event FMQ. L'EventFlag peut être créé à partir de l'Event FMQ à l'aide de EventFlag::createEventFlag et de la fonction getEventFlagWord() de l'Event FMQ.

La HAL AIDL des capteurs est compatible avec write et writeBlocking sur l'Event FMQ. 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 l'Event FMQ. 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 l'Event FMQ.

Événements WAKE_UP

Les événements WAKE_UP sont des événements de capteur qui entraînent l'activation 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 l'Event FMQ, 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 le Wake Lock FMQ.

La HAL des capteurs doit lire le Wake Lock FMQ pour déterminer le nombre d'événements WAKE_UP gérés par le framework. La 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 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 le Wake Lock FMQ.

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

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 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 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 l'Event FMQ, 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() est normalement utilisée 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 regroupement 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 AIDL des capteurs se trouvent dans hardware/interfaces/sensors/aidl/vts/. Ces tests garantissent que la HAL des capteurs est implémentée correctement et que toutes les exigences de ISensors.aidl et ISensorsCallback.aidl sont respectées.

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 AIDL des capteurs, 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 le FMQ

Au lieu d'attendre l'appel de poll(), dans la HAL AIDL des capteurs, la HAL des capteurs 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. 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 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 AIDL des capteurs, la HAL n'est plus avertie lorsque le framework a traité les événements écrits dans le FMQ, le Wake Lock FMQ permet au framework de communiquer avec la HAL lorsqu'il a géré les événements WAKE_UP.

Dans la HAL AIDL des capteurs, 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 AIDL des capteurs 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.

Compatibilité multi-HAL

La HAL AIDL des capteurs 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 depuis la HAL des capteurs 2.1.