实现动态关停涉及连接数据流以及执行动态进程,下文对此进行了详细介绍。
对 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 可在任务完成后关停(记录在 HAL 文件中)。
自动生命周期
Android 10 为内核和 hwservicemanager
添加了更多支持,可让 HAL 在没有任何客户端时自动关停。如需使用此功能,请根据“对 HAL 定义所做的更改”这一部分完成其中所有步骤,并执行以下操作:
- 使用
LazyServiceRegistrar
而不是成员函数registerAsService
通过 C++ 注册服务,例如:// only one instance of LazyServiceRegistrar per process LazyServiceRegistrar registrar; registrar.registerAsService(myHidlService /* , "default" */);
- 验证 HAL 客户端是否仅在使用时保留对顶级 HAL(通过
hwservicemanager
注册的接口)的引用。为了避免出现延迟,如果该引用在继续执行的 hwbinder 线程上被丢弃,客户端还应该在丢弃引用后调用IPCThreadState::self()->flushCommands()
,以确保 binder 驱动程序在相关引用计数发生变化时收到通知。