动态运行 AIDL 服务

从 Android 11 开始,系统分区中运行的原生 AIDL 服务可根据需要动态启动和停止。动态服务会在首次收到请求时启动,在不再处于使用状态时自动停止。

可动态运行的服务

此功能仅适用于生命周期可由 initservicemanager 控制的原生服务。应用软件包内的服务无法使用此功能,而应改用绑定服务

动态关闭是通过关闭进程(服务在其中运行)来实现的。如果同一进程中存在多项服务,那么所有这些服务都必须注册为动态服务,才能与此功能兼容。当所有这些服务都处于未使用状态时,该进程随即关闭。

配置服务的 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::publishBinderService::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