Exécuter des services AIDL de manière dynamique

À partir d'Android 11, les services AIDL natifs s'exécutant dans la partition système peuvent être démarrés et arrêtés de manière dynamique selon les besoins. Les services dynamiques démarrent lorsqu'ils sont demandés pour la première fois et s'arrêtent automatiquement lorsqu'ils ne sont plus utilisés.

Services pouvant s'exécuter de manière dynamique

Cette fonctionnalité n'est disponible que pour les services natifs dont les cycles de vie peuvent être contrôlés par init et servicemanager. Les services dans les packages d'application ne sont pas compatibles et doivent utiliser des services liés à la place.

L'arrêt dynamique consiste à arrêter le processus dans lequel le service s'exécute. Si plusieurs services existent dans le même processus, ils doivent tous être enregistrés comme dynamiques pour être compatibles avec cette fonctionnalité. Ce processus s'arrêtera lorsque tous les services seront inutilisés.

Configurer le fichier .rc d'initialisation d'un service

Pour exécuter un service de manière dynamique, ajoutez les options suivantes au fichier init .rc du service après la ligne service <name> <cmd> de début.

interface aidl serviceName
disabled
oneshot

Ces options permettent d'effectuer les opérations suivantes :

  • interface aidl serviceName : permet à servicemanager de trouver le service. Si le service utilise plusieurs interfaces, déclarez chaque interface sur sa propre ligne. Ces noms doivent correspondre exactement à ce que servicemanager attend et peuvent différer du nom du processus.
  • disabled : empêche le service de démarrer automatiquement au démarrage.
  • oneshot : empêche le service de redémarrer automatiquement chaque fois qu'il est arrêté.

Pour en savoir plus, consultez le fichier README du langage Init Android dans AOSP.

Exemples :

Enregistrer un service

Chaque service est créé et enregistré avec servicemanager. L'enregistrement a souvent lieu dans un fichier nommé main.cpp, mais l'implémentation peut varier. L'enregistrement se présente généralement comme suit :

using android::defaultServiceManager;

defaultServiceManager()->addService(serviceName, service);

L'enregistrement est parfois abstrait par BinderService::publish ou BinderService::instantiate, qui appellent le code ci-dessus.

Pour enregistrer un service comme dynamique, remplacez son code d'enregistrement par le code suivant :

#include <binder/LazyServiceRegistrar.h>

using android::binder::LazyServiceRegistrar;

auto lazyRegistrar = LazyServiceRegistrar::getInstance();
lazyRegistrar.registerService(service, serviceName);

servicemanager communique avec LazyServiceRegistrar pour arrêter les services en fonction de leur nombre de références.

Exemples :

Configurer les clients de service AIDL

Obtenir le service

Pour récupérer un service différé, il doit être démarré, puis récupéré. L'appel de getService sur le gestionnaire de services démarrera le service, mais en général, vous souhaitez obtenir le service dès qu'il est disponible, et les variantes waitForService doivent être utilisées. Pour savoir comment les utiliser, consultez la documentation spécifique au backend.

Publier le service

L'arrêt dynamique est basé sur le décompte des références. Les clients ne doivent donc pas conserver le service lorsqu'il n'est pas utilisé.

Exemples :

Désactiver temporairement l'arrêt

Si vous souhaitez qu'un service s'exécute de manière indépendante jusqu'à ce que certaines tâches soient terminées, puis qu'il passe à un comportement dynamique, vous pouvez utiliser LazyServiceRegistrar::forcePersist pour activer et désactiver l'arrêt dynamique. Si cette méthode est appelée côté serveur, elle doit l'être avant registerService.

Exemple : apexservice