Чтобы реализовать динамическое отключение, необходимо настроить потоки данных и выполнить динамические процессы, как описано в следующих разделах.
Изменения в определениях HAL
Для динамического завершения работы требуется информация о том, какие процессы обслуживают какие интерфейсы HAL (эта информация также может быть полезна позже в других контекстах), а также о том, что процессы не запускаются при загрузке и не перезапускаются (до повторного запроса) при их выходе.
# some init.rc script associated with the HAL service vendor.some-service-name /vendor/bin/hw/some-binary-service # init language extension, provides information of what service is served # if multiple interfaces are served, they can be specified one on each line interface android.hardware.light@2.0::ILight default # restarted if hwservicemanager dies # would also cause the hal to start early during boot if disabled wasn't set class hal # will not be restarted if it exits until it is requested to be restarted oneshot # will only be started when requested disabled # ... other properties
Изменения в init и hwservicemanager
Для динамического отключения также требуется, чтобы hwservicemanager сообщал init о необходимости запуска запрошенных сервисов. В Android 9 в init добавлены три дополнительных управляющих сообщения (например, ctl.start): ctl.interface_start, ctl.interface_stop и ctl.interface_restart.
Эти сообщения можно использовать, чтобы сигнализировать init о необходимости включить или отключить определенные аппаратные интерфейсы. Если сервис запрашивается, но не зарегистрирован, hwservicemanager запрашивает его запуск. Однако для динамических HAL не требуется использовать ни один из них.
Как определить выход из HAL
В Android 9 выход из HAL определяется вручную. На устройствах с Android 10 и более поздних версий это также можно сделать с помощью автоматических циклов жизни.
Для динамического отключения требуется несколько правил, определяющих, когда запускать и отключать HAL. Если HAL по какой-либо причине завершает работу, он автоматически перезапускается, когда это необходимо, с использованием информации, предоставленной в определении HAL, и инфраструктуры, предоставленной изменениями в init и hwservicemanager. Это можно сделать несколькими способами, в том числе:
- HAL может вызвать функцию выхода, если кто-то вызовет API закрытия или аналогичный API. Это поведение должно быть указано в соответствующем интерфейсе HAL.
- HAL могут завершать работу после выполнения задачи (это описано в файле HAL).
Автоматические жизненные циклы
В Android 10 добавлена поддержка ядра и hwservicemanager, что позволяет HAL автоматически отключаться, когда у них нет клиентов. Чтобы использовать эту функцию, выполните все шаги, описанные в разделе Изменения в определениях HAL, а также:
- Зарегистрируйте сервис в C++ с помощью
LazyServiceRegistrarвместо функции-членаregisterAsService, например:// only one instance of LazyServiceRegistrar per process LazyServiceRegistrar registrar; registrar.registerAsService(myHidlService /* , "default" */);
- Убедитесь, что клиент HAL сохраняет ссылку на HAL верхнего уровня (интерфейс, зарегистрированный с помощью
hwservicemanager), только когда он используется. Чтобы избежать задержек, если эта ссылка удаляется в потоке hwbinder, который продолжает выполняться, клиент также должен вызватьIPCThreadState::self()->flushCommands()после удаления ссылки, чтобы убедиться, что драйвер связывателя уведомлен о связанных изменениях количества ссылок.