UserService
UserService 在特权进程中运行应用代码,并返回自定义 AIDL 接口的 Binder。
定义 AIDL 接口
将销毁方法的 transaction code 设为 16777114:
interface IMyPrivilegeService {
void destroy() = 16777114;
String getUid() = 1;
}实现服务
class MyPrivilegeService private constructor(
private val context: Context?,
) : IMyPrivilegeService.Stub() {
@Keep
constructor() : this(context = null)
@Keep
constructor(context: Context) : this(context = context)
override fun getUid(): String {
return "uid=${android.os.Process.myUid()}"
}
override fun destroy() {
if (!PrivilegeUserServiceEnvironment.isEmbedded) {
exitProcess(0)
}
}
}运行时支持无参构造器或 Context 构造器。独立进程优先初始化 Application, 失败后改用 package Context。嵌入式服务获得 package Context。
使用独立进程
这是默认模式。服务运行在单独的 app_process 子进程中:
lifecycleScope.launch {
val spec = PrivilegeUserServiceSpec(
serviceClassName = MyPrivilegeService::class.java.name,
tag = "main",
version = 1,
)
Privilege.startUserService(spec)
val connection = Privilege.bindUserService(spec)
try {
val service = IMyPrivilegeService.Stub.asInterface(connection.binder)
service.getUid()
} finally {
connection.unbind()
}
Privilege.stopUserService(spec)
}startUserService、bindUserService 和 stopUserService 是可取消的挂起函数。取消会移除待处理任务及尚未接收的资源。connection.unbind() 幂等,并在不可取消上下文完成清理。
每个实例由 serviceClassName + tag 标识。version 表达同一实例能否复用;实现不再 兼容时修改该值,运行时会替换实例。
使用嵌入式服务
设置 embedded = true,让服务直接运行在 Privileged Server 中,无需额外进程,节省进程启动和内存开销:
val spec = PrivilegeUserServiceSpec(
serviceClassName = MyPrivilegeService::class.java.name,
tag = "embedded",
version = 1,
embedded = true,
)嵌入式服务共享服务端进程,构造异步且可取消。
UserService 状态无效或操作返回失败时使用 IllegalStateException。 服务不可用、Binder 传输错误和协程取消保留各自的异常类型。 管理器或服务端点死亡时直接传播 DeadObjectException。内部响应协议跨进程保留 连接失效分类,因此 PrivilegeBinderCall.orElse(...) 无需检查嵌套 cause 即可处理。
判断运行环境
PrivilegeUserServiceEnvironment.isEmbedded 在共享服务端进程中为 true,在独立子进程中为 false,进程存活期间不变。
退出进程前先检查该值:嵌入式服务只能清理自己的资源,不能调用 exitProcess,否则会结束整个特权进程。通过 PrivilegeUserServiceSpec.embedded 选择模式。