# 不同 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 的東西,這樣做是沒有意義的,並且也將帶來無意義的資源使用。