Реализация динамического завершения работы включает в себя подключение потоков данных и выполнение динамических процессов, как подробно описано в следующих разделах.
Изменения в определениях 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 решит выйти по какой-либо причине, он будет автоматически перезапущен, когда он снова понадобится, используя информацию, предоставленную в определении HAL, и инфраструктуру, предоставленную изменениями в init
и hwservicemanager
. Это может включать в себя несколько различных стратегий, в том числе:
- HAL может выбрать вызов выхода для себя, если кто-то вызывает для него близкий или аналогичный 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()
после удаления ссылки, чтобы гарантировать, что драйвер связывателя уведомлен о соответствующем счетчике ссылок. изменения.