iT邦幫忙

2025 iThome 鐵人賽

DAY 28
0

PermissionManagerService:權限模型與運行時檢查

intro

Android 系統自問世以來,就以「應用隔離」與「權限管控」為核心安全設計。每個應用都執行在自己獨立的 UID 與 sandbox 中,想要存取敏感資源(如相機、定位、通訊錄)都必須透過權限系統授權。
而在整個權限體系中,PermissionManagerService(PMSv2) 是 framework 層的關鍵角色,負責:

  • 管理系統中所有權限的定義與狀態;
  • 驗證應用請求權限是否合法;
  • 處理動態權限請求與撤銷;
  • 與 PackageManagerService (PMS)、ActivityManagerService (AMS)、AppOpsService 協同工作,完成整個授權決策鏈。

Android 權限系統總覽

在深入 PermissionManagerService 之前,先看整體權限架構:

+-----------------------------------------------------------+
|                     Application 層                        |
|   (App 請求權限、顯示 runtime dialog、存取受保護 API)         |
+-----------------------------------------------------------+
|                 Framework Service 層                      |
|   PermissionManagerService、AppOpsService、AMS、PMS        |
+-----------------------------------------------------------+
|                    Native 層 (JNI)                        |
|     libbinder, libcutils, SELinux policy, system_server   |
+-----------------------------------------------------------+
|                      Kernel 層                             |
|              UID/GID, SELinux, capabilities               |
+-----------------------------------------------------------+

權限管理的四大核心概念:

  • 宣告 (Manifest Declaration):
    • 在 AndroidManifest.xml 中使用 <uses-permission> 宣告所需權限。
  • 授權 (Grant):
    • 由系統決定是否授予該應用此權限。授權來源可能是使用者互動(runtime permission dialog)或預設策略(如 system app)。
  • 檢查 (Enforce):
    • 在系統 API(如 CameraManager、LocationManager)執行時,透過 checkPermission() 驗證。
  • 撤銷 (Revoke):
    • 使用者可於「設定 → 應用 → 權限」中手動撤銷授權。

PermissionManagerService 架構與工作流程

服務註冊與啟動

在 SystemServer.java 啟動階段:

t.traceBegin("StartPermissionManagerService");
mSystemServiceManager.startService(PermissionManagerService.class);
t.traceEnd();

這使得 PermissionManagerService 成為系統服務之一,透過 Binder 暴露給其他 framework 元件。

關鍵成員

public final class PermissionManagerService extends SystemService {
    private final PermissionRegistry mRegistry;
    private final DefaultPermissionGrantPolicy mDefaultGrantPolicy;
    private final PermissionSettings mSettings;
}
  • PermissionRegistry:儲存所有權限的定義(名稱、保護等級、授權狀態)。
  • PermissionSettings:維護當前系統中「哪些 App 拿到了哪些權限」。
  • DefaultPermissionGrantPolicy:定義哪些 system app 可自動取得權限。

權限授予與檢查流程

App 請求權限 (Runtime Flow)

當應用呼叫:

ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQ_CODE)

系統會經過以下流程:

[App層] requestPermissions()
       ↓
[AMS] -> startActivityForResult() 啟動 PermissionDialog Activity
       ↓
[PermissionController Service] 顯示授權對話框
       ↓
[PermissionManagerService] 接收結果、更新授權記錄
       ↓
[PackageManagerService] 更新 packages.xml

若使用者點選「允許」,PermissionManagerService 將:

  • 在記錄中將該權限標記為 granted;
  • 通知 AppOpsService 更新 operation 狀態;
  • 寫入 /data/system/packages.xml;
  • 發送 ACTION_PERMISSION_CHANGED 廣播。

權限檢查 (Enforcement Flow)

當 App 呼叫需要權限的 API,例如:

val location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)

Framework 流程如下:

App 呼叫 → LocationManagerService
       ↓
LocationManagerService.checkPermission()
       ↓
PermissionManagerService.checkUidPermission(uid, permission)
       ↓
AppOpsService.noteOp() → 檢查是否被暫時封鎖
       ↓
若通過 → 執行 API
否則 → 拋出 SecurityException

PMS 實際檢查的核心程式碼:

int checkUidPermission(String permName, int uid) {
    synchronized (mLock) {
        Permission permission = mRegistry.getPermission(permName);
        return permission.isGranted(uid) ? PERMISSION_GRANTED : PERMISSION_DENIED;
    }
}

權限分類與保護等級

Android 權限主要分為四種保護等級:

類型 範例 授權機制 使用者互動
normal INTERNET 自動授權
dangerous CAMERA、LOCATION 需 runtime 授權
signature READ_LOGS、MANAGE_USERS 必須同簽章
signatureOrSystem (舊版已棄用) 由系統預設授權

此外,自 Android 12 起,又引入了 permission group 與 one-time permission 概念,使授權更精細化與動態化。

與其他系統服務的互動

PermissionManagerService 不獨立運作,它與其他三個關鍵服務緊密合作:

服務名稱 職責 與 PMS 的互動
PackageManagerService (PMS) 管理 App 安裝與 metadata 安裝 App 時載入 uses-permission
ActivityManagerService (AMS) 控制應用執行 啟動授權 dialog、更新運行狀態
AppOpsService 控制 App 實際存取操作 補充權限層不足的情境控制
PermissionController Service 提供 UI 層授權界面 與 PMS 溝通 runtime 結果
        +-------------------------+
        |   PermissionController  |
        |   (Dialog UI, UX Flow) |
        +-----------+-------------+
                    |
                    v
        +-------------------------+
        |  PermissionManagerService|
        +-----------+--------------+
                    |
        +-----------+--------------+
        |   AppOpsService          |
        |   ActivityManagerService |
        |   PackageManagerService  |
        +-----------+--------------+
                    |
                    v
        +-------------------------+
        |   System Server / Binder|
        +-------------------------+

安全機制與 SELinux

PermissionManagerService 並非唯一的安全守門員。
在 kernel 層,還有 UID sandboxing 與 SELinux policy 兩層防護:

  • 每個 App 都有獨立的 UID,防止跨進程資料存取。
  • SELinux 規則限制 system server、HAL 與 App 的交互範圍。
    這使得即便 PMS 錯誤授權,也不會突破 kernel 的安全邊界。

權限的持久化與儲存

授權資訊儲存在:
/data/system/packages.xml

Ex.

<package name="com.example.camera" codePath="/data/app/com.example.camera">
    <perms>
        <item name="android.permission.CAMERA" granted="true" />
    </perms>
</package>

當系統重新啟動時,PermissionManagerService 會重新載入這些紀錄,確保授權狀態一致。

Android 13+ 權限變革重點

  • 通知權限 (POST_NOTIFICATIONS):首次需要 runtime 授權。
  • 精確/模糊定位分離:ACCESS_FINE_LOCATION vs ACCESS_COARSE_LOCATION。
  • 照片與影片選取權限:Android 14 引入 READ_MEDIA_VISUAL_USER_SELECTED。
  • 自動撤銷機制:長期未使用的 App 其權限會被自動收回。

best pratice

在使用前動態檢查:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
    != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 0)
}

正確處理 callback:

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
    if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // granted
    }
}

避免過度要求敏感權限,特別是在 Google Play 發布政策中,需有明確用途說明。

Summary

PermissionManagerService 是 Android 權限體系的核心組件之一,它串連了從 App 層的授權請求、系統層的狀態記錄 到 安全層的防護策略。
透過與 PMS、AMS、AppOpsService 的協同合作,它確保了:

  • 權限授予的合法性;
  • 權限檢查的即時性;
  • 使用者能清楚掌握應用存取行為。

上一篇
#26
下一篇
#28
系列文
安豬複習31
  1. 27
    #26
  2. 28
    #27
  3. 29
    #28
  4. 30
    #29
  5. 31
    #30
完整目錄
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言