Динамически доступные HAL

Android 9 поддерживает динамическое отключение аппаратных подсистем Android, когда они не используются или не нужны. Например, если пользователь не подключен к Wi-Fi, подсистемы Wi-Fi не должны занимать память, расходовать заряд батареи или другие системные ресурсы. В более ранних версиях Android HAL/драйверы оставались открытыми на устройствах Android в течение всего времени, пока телефон был загружен.

Чтобы реализовать динамическое отключение, необходимо настроить потоки данных и выполнить динамические процессы, как описано в следующих разделах.

Изменения в определениях 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() после удаления ссылки, чтобы убедиться, что драйвер связывателя уведомлен о связанных изменениях количества ссылок.