从 Android 11 开始,在系统分区中运行的原生 AIDL 服务可以在需要时动态启动和停止。动态服务在首次请求时启动,并在不再使用时自动停止。
可以动态运行的服务
此功能仅适用于生命周期可由 init
和 servicemanager
控制的原生服务。应用软件包中的服务不受支持,应改为使用绑定服务。
动态关停的工作原理是关停运行服务的进程。如果同一进程中存在多个服务,则所有服务都必须注册为动态服务才能与此功能兼容。当所有服务都未使用时,该进程将随后关停。
配置服务的 init .rc 文件
要动态运行服务,请在服务的 init .rc
文件中的前导 service <name> <cmd>
行后添加以下选项。
interface aidl serviceName
disabled
oneshot
这些选项的作用如下:
interface aidl serviceName
:允许servicemanager
查找服务。如果服务使用多个接口,请在单独的行中声明每个接口。这些名称必须与servicemanager
期望的名称完全一致,并且可能与进程名称不同。disabled
:阻止服务在启动时自动启动。oneshot
:阻止服务在每次停止时自动重启。
如需了解详情,请参阅 AOSP 中的Android Init Language Readme。
示例
注册服务
每个服务都使用 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