Capteurs AIDL HAL

La couche d'abstraction matérielle des capteurs (HAL) est l'interface entre le cadre de capteurs Android et les capteurs d'un appareil, tels qu'un accéléromètre ou un gyroscope. Le Sensors HAL définit les fonctions qui doivent être implémentées pour permettre au framework de contrôler les capteurs.

Les capteurs AIDL HAL sont disponibles dans Android 13 et versions ultérieures pour les appareils nouveaux et mis à niveau. Les capteurs AIDL HAL, qui sont basés sur les capteurs HAL 2.1 , utilisent l' interface AIDL HAL et exposent les types de capteurs de suivi de tête et d'IMU à axe limité.

Interface AIDL-HAL

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

Implémenter les capteurs AIDL HAL

Pour implémenter les capteurs AIDL HAL, 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 le HAL

Le Sensors HAL 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 Sensors HAL : deux descripteurs FMQ et un pointeur vers un objet ISensorsCallback .

Le HAL utilise le premier descripteur pour créer l'événement FMQ utilisé pour écrire les événements de capteur dans le framework. Le HAL utilise le deuxième descripteur pour créer le Wake Lock FMQ utilisé pour se synchroniser lorsque le HAL libère son wakelock pour les événements du capteur WAKE_UP . La HAL doit enregistrer un pointeur vers l'objet ISensorsCallback afin que toutes les fonctions de rappel nécessaires puissent être invoquées.

La fonction initialize() doit être la première fonction appelée lors de l’initialisation du HAL des capteurs.

Exposer les capteurs disponibles

Pour obtenir une liste de tous les capteurs statiques disponibles dans l'appareil, utilisez la fonction getSensorsList() . Cette fonction renvoie une liste de capteurs, chacun identifié de manière unique par son handle. Le handle d’un capteur donné ne doit pas changer lorsque le processus hébergeant le Sensors HAL redémarre. Les handles peuvent changer lors des redémarrages de l’appareil et lors 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) .

Liste de stabilité des capteurs

Après un redémarrage Sensors HAL, si les données renvoyées par getSensorsList() indiquent un changement significatif 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 changements importants apportés à la liste des capteurs incluent les cas où un capteur avec une poignée donnée est manquant ou a modifié ses attributs, ou lorsque de nouveaux capteurs sont introduits. Bien que le redémarrage du runtime Android perturbe l'utilisateur, cela 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. Il est donc conseillé aux fournisseurs de HAL d’éviter les modifications évitables de la liste des capteurs.

Pour garantir des poignées de capteur stables, le HAL doit mapper de manière déterministe un capteur physique donné dans l'appareil à sa poignée. Bien qu'aucune implémentation spécifique ne soit exigée par l'interface Sensors HAL, 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 en utilisant 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 fixé matériellement, de sorte que le HAL doit savoir quand tous les capteurs attendus ont terminé leur 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 dans le système de fichiers, et 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 poignées des capteurs ne changent pas lors des redémarrages de HAL.

Configurer les capteurs

Avant qu'un capteur ne soit activé, celui-ci 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 batch() sans perte de données du capteur.

Période d'échantillonnage

La période d'échantillonnage a une signification différente en fonction du type de capteur configuré :

  • Continu : les événements du 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.
  • One-shot : la période d'échantillonnage est ignorée.
  • Spécial : Pour plus de détails, voir Types de capteurs .

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

Latence maximale des rapports

La latence maximale de rapport définit la durée maximale en nanosecondes pendant laquelle les événements peuvent être retardés et stockés dans la FIFO matérielle avant d'être écrits dans l'Event FMQ via le HAL pendant que le SoC est réveillé.

Une valeur de zéro signifie que les événements doivent être signalés dès qu'ils sont mesurés, soit en sautant 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éclencheur s'interrompt 50 fois par seconde lorsque le SoC est réveillé.

Lorsque la latence maximale de reporting est supérieure à zéro, les événements des capteurs 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 la FIFO matérielle et signalés par lots, à condition qu'aucun événement ne soit retardé de plus que la latence maximale de rapport. 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 permet au SoC de passer à un mode de consommation inférieure pendant que le capteur capture et regroupe les données.

Chaque événement est associé à un horodatage. Le retardement de l'heure à laquelle un événement est signalé ne doit pas avoir d'impact 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 plus d’informations et les exigences relatives à la création de rapports sur les événements de capteur avec une latence de rapport maximale non nulle, consultez Traitement par lots .

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 configurer le capteur à l'aide batch() .

Une fois qu'un capteur est désactivé, les événements de capteur supplémentaires provenant de ce capteur ne doivent pas être écrits dans le FMQ d'événements.

Capteurs de rinçage

Si un capteur est configuré pour regrouper les données du capteur, le framework peut forcer un vidage immédiat des événements de capteur groupés en appelant flush() . Cela entraîne l’écriture immédiate des événements de capteur par lots pour le handle de capteur spécifié dans l’événement FMQ. Le HAL des capteurs doit ajouter un événement de vidage complet à 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 être renvoyée immédiatement). Si l'implémentation utilise un seul FIFO pour plusieurs capteurs, ce FIFO est vidé et l'événement de vidage terminé est ajouté uniquement pour le capteur spécifié.

Si le capteur spécifié n'a pas de FIFO (pas de 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 complet pour ce capteur. Ceci s'applique à tous les capteurs autres que les capteurs ponctuels.

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

Écrire les événements du capteur dans le FMQ

L'Event FMQ est utilisé par Sensors HAL pour pousser les événements de capteur dans le cadre de capteur Android.

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

Lorsque le Sensors HAL a écrit le nombre souhaité d'événements de capteur dans l'Event FMQ, le Sensors HAL doit informer l'infrastructure 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 EventFlag::createEventFlag et de la fonction getEventFlagWord() de l'Event FMQ.

Les capteurs AIDL HAL prennent en charge à la fois write et writeBlocking sur l'événement FMQ. L'implémentation par défaut fournit une référence pour l'utilisation 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 les événements de l'Event FMQ. L’indicateur de notification d’écriture doit être défini sur EventQueueFlagBits::READ_AND_PROCESS , qui informe l’infrastructure que les événements ont été écrits dans Event FMQ.

Événements WAKE_UP

Les événements WAKE_UP sont des événements de capteur qui provoquent 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 l'événement FMQ, le Sensors HAL doit sécuriser un wakelock pour garantir que le système reste éveillé 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 wakelock, permettant au Sensors HAL de libérer son wakelock. Pour synchroniser lorsque les capteurs HAL libèrent son wakelock, utilisez le Wake Lock FMQ.

Le Sensors HAL doit lire le Wake Lock FMQ pour déterminer le nombre d’événements WAKE_UP que le framework a gérés. Le 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 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 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 sur le Wake Lock FMQ.

Capteurs dynamiques

Les capteurs dynamiques sont des capteurs qui ne font pas physiquement partie de l'appareil mais peuvent être utilisés comme entrée dans 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 depuis le HAL Sensors. Cela notifie le framework du nouveau capteur dynamique et permet au capteur d'être contrôlé via le framework et de faire en sorte que les événements du capteur soient consommé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 plutôt que dans l'Event FMQ en contournant le framework de capteurs Android. 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 similaire à 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 injecter des données de capteur dans le capteur. Ceci est utile pour les tests, en particulier pour les algorithmes qui existent sous le framework.

La fonction injectSensorData() est normalement utilisée pour insérer les 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 des capteurs HAL, exécutez les tests des capteurs CTS et VTS.

Essais CTS

Les tests Sensor CTS 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 standard des capteurs, telles que l'activation des capteurs, le traitement par lots 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 rapportent des valeurs précises.

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

Essais VTS

Les tests VTS pour les capteurs AIDL HAL se trouvent dans hardware/interfaces/sensors/aidl/vts/ . Ces tests garantissent que le Sensors HAL est correctement implémenté et que toutes les exigences de ISensors.aidl et ISensorsCallback.aidl sont correctement remplies.

Initialiser le HAL

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

Exposer les capteurs disponibles

Dans Sensors AIDL HAL, la fonction getSensorsList() doit renvoyer la même valeur lors du démarrage d’un seul périphérique, même lors des redémarrages de Sensors HAL. Une nouvelle exigence de la fonction getSensorsList() est qu'elle doit renvoyer la même valeur lors du démarrage d'un seul périphérique, même lors des redémarrages des capteurs HAL. Cela permet à l'infrastructure 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 les événements du capteur dans le FMQ

Au lieu d'attendre que poll() soit appelé, dans le HAL AIDL des capteurs, le HAL des capteurs doit écrire de manière proactive les événements du capteur dans l'événement 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 cadre.

Événements WAKE_UP

Dans Sensors HAL 1.0, HAL était capable de libérer son wakelock pour tout événement WAKE_UP lors de tout appel ultérieur à poll() après qu'un WAKE_UP ait été publié sur poll() car cela indiquait que le framework avait traité tous les événements de capteur et avait obtenu un wakelock, si nécessaire. Parce que, dans les capteurs AIDL HAL, le HAL n'est plus averti lorsque le framework a traité des événements écrits dans le FMQ, le Wake Lock FMQ permet au framework de communiquer avec le HAL lorsqu'il a traité les événements WAKE_UP .

Dans le Sensors AIDL HAL, le wakelock sécurisé par le 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. Le Sensors AIDL HAL nécessite que onDynamicSensorsConnected et onDynamicSensorsDisconnected dans ISensorsCallback soient appelés chaque fois que les connexions des capteurs dynamiques 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 pris en charge.

Prise en charge multi-HAL

Les capteurs AIDL HAL prennent en charge le multi-HAL en utilisant le framework Sensors Multi-HAL . Pour plus de détails sur la mise en œuvre, voir Portage à partir des capteurs HAL 2.1 .