动态运行 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 Language Readme

示例

注册服务

每个服务都使用 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);

servicemanagerLazyServiceRegistrar 通信,以根据服务的引用计数关停服务。

示例

配置 AIDL 服务客户端

获取服务

要检索延迟服务,必须先启动服务,然后再检索。在服务管理器上调用 getService 将启动服务,但通常情况下,您希望在服务可用后立即获取服务,应使用 waitForService 变体。请参阅关于如何使用这些变体的后端专用文档

释放服务

动态关停基于引用计数,因此客户端不应在服务不使用时持有服务。

示例

暂时停用关停

如果您希望服务独立运行直到完成某些任务,然后再切换到动态行为,则可以使用 LazyServiceRegistrar::forcePersist 来切换动态关停的开启和关闭状态。如果从服务器端调用此方法,则应在 registerService 之前调用。

示例:apexservice