# 不同 Android 版本下的不同

每个 op 都有两种 mode,分别为 package modeuid modeuid mode 有更高优先级,即只有当 uid mode 为默认值时才会使用 package mode

以下表格展示了从系统修改权限设定时,uid mode 会被如何设定。

表格

星号(*)表示相对之前的系统放生变化。

# Android 6 - Android 9

系统设定页面 uid mode
允许 allow
拒绝 ignore(只对 target 23 以下的应用设定)
(尚未设定) (allow)

# Android 10

系统设定页面 uid mode
仅在使用期间允许 * foreground
允许 allow
拒绝 * ignore
(尚未设定) (allow)

# Android 11

系统设定页面 uid mode
每次都询问 * ignore
仅在使用期间允许 * foreground
允许 allow
拒绝 ignore
(尚未设定)* ignore

# Android 11 中的其他行为

  • 设置 package mode 无效
  • 设置 uid mode 时,若设定值不符合运行时权限状态则无效
  • 在特定的情况下(比如安装应用后),系统将重设全部应用的 appops 设定到与运行时权限符合的状态

# 旧版本 App Ops 没做对

旧版本的 App Ops(v5.0.0 以前)只会读取和修改 package mode,这显然是不对的。

在 Android 9 及之前,对 target 23 以下的应用在 App Ops 中设定“允许”是无效的;在 Android 10,一旦用户在系统中设置“拒绝”或“仅在使用时允许”,则在 App Ops 中的设置永远无法生效(因为此时系统设置的 uid mode 被优先使用)。

由于从低版本升级时系统的权限设定是被保留的,这个巨大的问题在 Android 10 发布的一年后才慢慢地暴露出来。

# 新版本(v5.0.0)App Ops 所做出的变化

除了完全跟随系统行为以外别无选择。

另外,因为 Android 11 会重置 appops 设定(所有“运行时权限允许,ops 忽略”会被重设为“运行时权限拒绝”),所以除了在系统之后再次重设以外别无选择。

# 新版本(v5.0.0)App Ops 需要更多能力

想要正确跟随系统行为,App Ops 必须具备取得和设置 runtime permissionpermission flagsappops 的能力。但是,并不是所有工作模式都能做到。

Shizuku 模式 托管设备管理员模式 root 模式(已被移除)
appops ✔️ ✔️ ✔️
runtime permission ✔️ 仅可设置〔1〕
permission flags ✔️

〔1〕需要 Island v5.0+ 或其他具有 Delegated Scopes Manager (opens new window) v3 支持的管理员应用

# “托管设备管理员模式”的缺陷

  • “无法确认”
  • 无法备份全部设置
  • 在 Android 11,无法设定新增的“每次都询问”(需要“设置 permission flags”)
技术信息

被设为 profile ownerdevice owner 的管理员应用享有一些特权,但是只有它们自身可以使用。因此,不同的管理员应用提供了不同的 API,使其他应用得以“借用”其特权。

只有提供 Delegation API 的 Island v5.0+ 支持“设置 runtime permission”。

对于“无法确认”,举个例子,在 Android 10 中:

appops runtime permission permission flags
忽略 ignore true
拒绝 (任何值) false 任意 "FIXED"
(尚未设置) (任何值) false 无 "FIXED"

只看 appops 设置显然不够。

# 为什么必须移除“root 模式”

纯 root(执行指令)的能力十分有限,没有可以修改 permission flags 的指令。想要正确修改 runtime permission 必须保证 permission flags 也被正确地修改(设备管理员所使用的更高层级的 Java API 不需要考虑这个问题)。

因此,root 模式已被移除。

技术信息

很多人会认为 root 无所不能,但实际上 root 只提供了一个 uid 0 的 shell。想要进入 Android 世界(直接使用 Java API),通过 app_process 运行 dex 几乎是唯一选择。

“root 模式”的替代——“Shizuku 模式”使用 Shizuku(GitHub (opens new window))做这一部分的工作。如果不使用 Shizuku,则仍然需要运行类似 Shizuku 的东西,这样做是没有意义的,并且也将带来无意义的资源使用。