À partir d'Android 11, les services AIDL natifs exécutés dans la partition système peuvent être démarrés et arrêtés de manière dynamique en fonction des 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 le cycle de vie peut être contrôlé par init
et servicemanager
. Les services inclus dans les packages d'applications 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 ne seront pas utilisés.
Configurer le fichier init .rc d'un service
Pour exécuter un service de manière dynamique, ajoutez les options suivantes au fichier d'initialisation .rc
du service après la ligne service <name> <cmd>
initiale.
interface aidl serviceName
disabled
oneshot
Ces options permettent d'effectuer les opérations suivantes:
interface aidl serviceName
: autoriseservicemanager
à trouver le service. Si le service utilise plusieurs interfaces, déclarez chacune d'elles sur une ligne distincte. Ces noms doivent correspondre exactement à ce qu'attendservicemanager
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 arrêt.
Pour en savoir plus, consultez le fichier README d'Android Init Language dans AOSP.
Exemples :
Enregistrer un service
Chaque service est créé et enregistré auprès de servicemanager
. L'enregistrement s'effectue souvent dans un fichier nommé main.cpp
, mais l'implémentation peut varier. L'enregistrement ressemble généralement à ceci:
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é, vous devez le démarrer, puis le récupérer.
Appeler getService
sur le gestionnaire de services lance le service, mais en règle générale, vous souhaitez obtenir le service dès qu'il est disponible. Vous devez utiliser des variantes waitForService
. Consultez la documentation spécifique au backend pour découvrir comment les utiliser.
Libérer le service
L'arrêt dynamique est basé sur le comptage des références. Par conséquent, les clients ne doivent 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 que vous souhaitez passer à un comportement dynamique, vous pouvez utiliser LazyServiceRegistrar::forcePersist
pour activer ou désactiver l'arrêt dynamique. Si vous l'appelez côté serveur, il doit être appelé avant registerService
.
Exemple: apexservice