从 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 语言自述文件。
示例:
注册服务
每项服务都是通过 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