Binder
Priv Kit 可以连接 Binder 服务和系统服务。通过它执行 Binder transaction 时, 原有的调用格式不会改变。应用提供对应的系统接口,并负责实现自己的业务逻辑。
访问系统服务
通过已连接的 Privileged Server,按服务名获取系统服务:
val activityBinder = PrivilegeBinderWrapper.fromSystemService("activity")
val activityManager = IActivityManager.Stub.asInterface(activityBinder)
Log.d(
"activity",
activityManager.getTasks(1).toString(),
)部分服务只能在 shell 或 Root 服务端进程中获取:
val binder = PrivilegeBinderWrapper.fromSystemService(
serviceName = "miui.mqsas.IMQSNative",
source = PrivilegeSystemServiceSource.SERVER_PROCESS,
)应用需要提供对应的系统接口,并定义每个 transaction 的调用格式和含义。
将资源绑定到服务端生命周期
部分 Binder API 接收 owner 或 death token,以便远端进程在 owner 退出时释放资源。 如果资源应当跟随当前 Privileged Server 进程,可以使用专用的服务端生命周期 Binder:
val serverInfo = Privilege.getServerInfo()
val serverLifecycle = serverInfo.lifecycleBinder
serverLifecycle.linkToDeath(
{ Log.d("server", "Privileged Server 已退出") },
0,
)这个 token 不提供特权操作或自定义 transaction。同一个服务端进程内,它的 Binder identity 保持不变;服务端被替换后,新服务端会返回不同的 token。它与 PrivilegeServerInfo 的其他字段属于同一个服务端快照。每次 Privilege.serverState 变化后更新这个值。服务端不存在或已经死亡时, Privilege.getServerInfo() 会抛出 PrivilegeServerUnavailableException。
处理调用失败
Priv Kit 自己的控制调用在服务端未连接或已经死亡时,都会抛出 PrivilegeServerUnavailableException。通过 PrivilegeBinderWrapper 转发的 调用会保留 Binder 原本的异常。调用失败时,应用可能无法确定是目标 Binder 还是 Privileged Server 已经死亡,需要根据自身情况决定是否改用其他方式。
如果服务端或 UserService 的 Binder 调用失败后可以安全地改用其他方式,可以使用 PrivilegeBinderCall.orElse(...):
PrivilegeBinderCallFailure.ServerUnavailable表示 Privileged Server 不可用。PrivilegeBinderCallFailure.BinderDied表示直接调用的 Binder 已经死亡。- 其他异常保持不变。
orElse(...) 适合原调用结果未知时仍可安全恢复的场景。服务进程可能已经完成修改后 才死亡。