Начиная с Android 11, нативные службы AIDL, работающие в системном разделе, могут запускаться и останавливаться динамически по мере необходимости. Динамические службы запускаются при первом запросе и автоматически останавливаются, когда они больше не используются.
Службы, которые могут работать динамически
Эта функция доступна только для собственных служб, жизненным циклом которых можно управлять с помощью init и servicemanager . Службы в пакетах приложений не поддерживаются и должны использовать связанные службы .
Динамическое завершение работы происходит путём завершения процесса, в котором запущена служба. Если в одном процессе существует несколько служб, все они должны быть зарегистрированы как динамические для совместимости с этой функцией. Этот процесс будет завершен, когда все службы перестанут использоваться.
Настройте файл init .rc службы
Для динамического запуска службы добавьте следующие параметры в файл .rc службы после первой строки service <name> <cmd> .
interface aidl serviceName
disabled
oneshot
Эти параметры выполняют следующие функции:
-
interface aidl serviceName: позволяетservicemanagerнайти службу. Если служба использует несколько интерфейсов, объявите каждый интерфейс в отдельной строке. Эти имена должны точно соответствовать тому, что ожидаетservicemanager, и могут отличаться от имени процесса. -
disabled: предотвращает автоматический запуск службы при загрузке. -
oneshot: предотвращает автоматический перезапуск службы после каждой остановки.
Более подробную информацию см. в файле Readme по языку инициализации Android в AOSP.
Примеры:
Зарегистрировать услугу
Каждая служба создаётся и регистрируется с помощью servicemanager . Регистрация часто происходит в файле main.cpp , но реализация может различаться. Регистрация обычно выглядит примерно так:
using android::defaultServiceManager;
defaultServiceManager()->addService(serviceName, service);
Регистрация иногда абстрагируется с помощью BinderService::publish или BinderService::instantiate , которые вызывают приведенный выше код.
Чтобы зарегистрировать службу как динамическую, замените ее регистрационный код следующим:
#include <binder/LazyServiceRegistrar.h>
using android::binder::LazyServiceRegistrar;
auto lazyRegistrar = LazyServiceRegistrar::getInstance();
lazyRegistrar.registerService(service, serviceName);
servicemanager взаимодействует с LazyServiceRegistrar для завершения работы служб на основе количества их ссылок.
Примеры:
Настройка клиентов службы AIDL
Получить услугу
Чтобы получить отложенную службу, её необходимо запустить, а затем получить. Вызов метода getService в диспетчере служб запустит службу, но обычно требуется получить службу сразу после её появления, поэтому следует использовать варианты waitForService . Подробнее об их использовании см. в документации по конкретной бэкенд-системе .
Выпуск службы
Динамическое отключение основано на подсчете ссылок, поэтому клиенты не должны удерживать службу, когда она не используется.
Примеры:
Временно отключить выключение
Если вы хотите, чтобы служба работала независимо до завершения определённых задач, а затем переключилась на динамическое поведение, вы можете использовать LazyServiceRegistrar::forcePersist для включения и выключения динамического завершения работы. Если эта функция вызывается со стороны сервера, её следует вызывать до registerService .
Пример: apexservice