Skip to content

权限框架

建立 Android 17 权限定义、安装初始化、运行时授权、检查、AppOps 和持久化的源码全景。

基于android-17.0.0_r1
AndroidPackageManagerServicePermissionManagerServiceAppOps源码阅读

权限框架 ​

本文面向已经读过 安装权限处理 和 包设置状态 的读者。目标不是背诵权限常量,而是建立 Android 17 的源码地图:Manifest 权限定义由谁接收,安装回调如何进入权限状态事务,checkPermission 到底读取哪份状态,运行时 grant/revoke 如何修改并持久化,以及带 AppOps 的权限为什么还需要第二层判定。读完后,读者应能从 API 入口定位到真实状态 owner,而不会把 PackageManager、PermissionController、PermissionManagerService 和 AppOps 当成同一个组件。

1. 架构迁移 ​

1.1 Binder 门面 ​

源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java

java
public class PermissionManagerService extends IPermissionManager.Stub {
    private final Object mLock = new Object();
    private final PackageManagerInternal mPackageManagerInt;
    private final AppOpsManager mAppOpsManager;
    private final Context mContext;
    private final PermissionManagerServiceInterface
            mPermissionManagerServiceImpl;

    PermissionManagerService(Context context,
            ArrayMap<String, FeatureInfo> availableFeatures) {
        mContext = context;
        mPackageManagerInt = LocalServices.getService(
                PackageManagerInternal.class);
        mAppOpsManager = context.getSystemService(AppOpsManager.class);

        final PermissionManagerServiceInternalImpl localService =
                new PermissionManagerServiceInternalImpl();
        LocalServices.addService(
                PermissionManagerServiceInternal.class, localService);
        LocalServices.addService(
                PermissionManagerInternal.class, localService);

        mPermissionManagerServiceImpl = LocalServices.getService(
                PermissionManagerServiceInterface.class);
    }
}

PermissionManagerService 对外实现 IPermissionManager,对 system_server 内部注册两个 LocalServices,但核心操作委托给 PermissionManagerServiceInterface。因此看到 grantRuntimePermission() 的 Java Binder 方法时,还没有到达真正的状态算法。

1.2 现代实现 ​

源码文件:

  • frameworks/base/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt
  • frameworks/base/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
kotlin
class AccessCheckingService(context: Context) : SystemService(context) {
    @Volatile private lateinit var state: AccessState
    private val stateLock = Any()
    private val policy = AccessPolicy()
    private val persistence = AccessPersistence(policy)

    private lateinit var appOpService: AppOpService
    lateinit var permissionService: PermissionService

    override fun onStart() {
        appOpService = AppOpService(this)
        permissionService = PermissionService(this)

        LocalServices.addService(
            AppOpsCheckingServiceInterface::class.java,
            appOpService,
        )
        LocalServices.addService(
            PermissionManagerServiceInterface::class.java,
            permissionService,
        )
    }
}

Android 17 的真实状态 owner 是 AccessCheckingService 中的 AccessState。PermissionService 与 AppOpService 共享访问策略和持久化框架,再分别实现 permission 与 app-op 接口。旧式 Java PermissionManagerService 是兼容门面和 attribution/one-time permission 等协调层。

2. 服务启动 ​

2.1 注册入口 ​

源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java

java
public static PermissionManagerServiceInternal create(
        Context context,
        ArrayMap<String, FeatureInfo> availableFeatures) {
    PermissionManagerService permissionService =
            (PermissionManagerService) ServiceManager.getService(
                    "permissionmgr");
    if (permissionService == null) {
        permissionService = new PermissionManagerService(
                context, availableFeatures);
        ServiceManager.addService(
                "permissionmgr", permissionService);
        ServiceManager.addService(
                "permission_checker",
                new PermissionCheckerService(context));
    }
    return LocalServices.getService(
            PermissionManagerServiceInternal.class);
}

系统注册两个 Binder service:permissionmgr 负责权限管理 API,permission_checker 负责带 attribution 和数据访问语义的检查。system_server 内部组件通常使用 PermissionManagerServiceInternal,减少 Binder 往返。

2.2 状态初始化 ​

源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt

kotlin
fun initialize() {
    packageManagerInternal =
        LocalServices.getService(PackageManagerInternal::class.java)
    packageManagerLocal =
        LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java)
    userManagerService = UserManagerService.getInstance()
    systemConfig = SystemConfig.getInstance()

    val userIds = MutableIntSet(
        userManagerService.userIdsIncludingPreCreated
    )
    val (packageStates, disabledSystemPackageStates) =
        packageManagerLocal.allPackageStates

    val mutableState = MutableAccessState()
    policy.initialize(
        mutableState,
        userIds,
        packageStates,
        disabledSystemPackageStates,
        packageManagerInternal.knownPackages,
        systemConfig.isLeanback,
        systemConfig.permissions,
        systemConfig.privilegedPermissionAllowlistPackages,
        systemConfig.permissionAllowlist,
        systemConfig.implicitToSourcePermissions,
    )
    persistence.initialize()
    persistence.read(mutableState)
    state = mutableState
}

初始化同时读取用户、当前包、disabled system 包、known packages、系统配置权限、特权 allowlist 和持久化状态。权限结果不是只从 APK Manifest 推导,也不是只读一个 runtime-permissions 文件;它是包事实、系统策略和历史授权状态的合成。

3. 权限分类 ​

3.1 基础保护级别 ​

源码文件:frameworks/base/core/java/android/content/pm/PermissionInfo.java

java
public static final int PROTECTION_NORMAL = 0;
public static final int PROTECTION_DANGEROUS = 1;
public static final int PROTECTION_SIGNATURE = 2;
@Deprecated
public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3;
public static final int PROTECTION_INTERNAL = 4;

public static final int PROTECTION_MASK_BASE = 0xf;

normal 权限通常随安装状态计算;dangerous 权限需要运行时用户决策;signature 权限要求签名或 lineage 能力;internal 用于系统内部边界。基础级别只占低位,额外 flags 会叠加更具体的授予条件。

3.2 保护 flags ​

java
public static final int PROTECTION_FLAG_PRIVILEGED = 0x10;
public static final int PROTECTION_FLAG_DEVELOPMENT = 0x20;
public static final int PROTECTION_FLAG_APPOP = 0x40;
public static final int PROTECTION_FLAG_PRE23 = 0x80;
public static final int PROTECTION_FLAG_INSTALLER = 0x100;
public static final int PROTECTION_FLAG_ROLE = 0x04000000;
public static final int PROTECTION_FLAG_KNOWN_SIGNER = 0x08000000;

flags 不是新的基础类型。例如 signature|privileged 允许符合特权 allowlist 的预装应用获得权限;dangerous|appop 表示权限 grant 通过后,真实数据访问还可能受 AppOps mode 限制。具体授予矩阵由 PermissionService/Policy 结合包身份计算。

3.3 三类使用方式 ​

类别典型入口状态 owner最终消费者
安装权限包扫描/安装回调AccessState 的 appId permission flags系统服务的权限检查
运行时权限requestPermissions 后的 grant/revoke每用户、每 appId、每 permission flagsAPI 调用与 PermissionChecker
特殊访问Settings/专用 manager/AppOps对应服务或 AppOps modeWindow、存储、通知等服务

“特殊权限”不是统一保护级别。例如 overlay、write settings、安装未知应用等由不同服务和 AppOps/设置页控制,不能仅查询 checkPermission 就断定最终访问一定允许。

4. 包生命周期 ​

4.1 包新增 ​

源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt

kotlin
override fun onPackageAdded(
    packageState: PackageState,
    isInstantApp: Boolean,
    oldPackage: AndroidPackage?,
) {
    if (packageState.isApex) {
        return
    }

    synchronized(storageVolumeLock) {
        storageVolumePackageNames
            .getOrPut(packageState.volumeUuid) { mutableListOf() }
            .add(packageState.packageName)
        if (packageState.volumeUuid !in mountedStorageVolumes) {
            return
        }
    }
    service.onPackageAdded(packageState.packageName)
}

PMS 提交包后调用 onPackageAdded。未挂载 volume 的包先登记顺序,等 volume mount 后批量进入状态事务;这样权限定义 owner 的选择保持确定顺序。APEX 本体不按普通 APK 权限包处理。

4.2 安装参数 ​

源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java

java
public void onPackageInstalled(AndroidPackage pkg,
        int previousAppId,
        PackageInstalledParams params,
        int rawUserId) {
    mPermissionManagerServiceImpl.onPackageInstalled(
            pkg, previousAppId, params, rawUserId);

    final int[] userIds = rawUserId == UserHandle.USER_ALL
            ? getAllUserIds() : new int[] { rawUserId };
    for (int userId : userIds) {
        final int mode = params.getAutoRevokePermissionsMode();
        if (mode == AppOpsManager.MODE_ALLOWED
                || mode == AppOpsManager.MODE_IGNORED) {
            setAutoRevokeExemptedInternal(
                    pkg, mode == AppOpsManager.MODE_IGNORED, userId);
        }
    }
}

安装回调除了权限 states 和 restricted allowlist,还把 auto-revoke exemption 映射到 AppOps mode。权限初始化与 AppOps 策略因此在同一安装事件中协作,但仍由不同状态域消费。

4.3 现代安装处理 ​

源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt

kotlin
override fun onPackageInstalled(
    androidPackage: AndroidPackage,
    previousAppId: Int,
    params: PackageInstalledParams,
    userId: Int,
) {
    if (androidPackage.isApex) return
    if (params === PackageInstalledParams.DEFAULT) return

    val userIds = if (userId == UserHandle.USER_ALL) {
        userManagerService.userIdsIncludingPreCreated
    } else {
        intArrayOf(userId)
    }
    userIds.forEach {
        service.onPackageInstalled(androidPackage.packageName, it)
    }
    userIds.forEach {
        val packageState = packageManagerInternal
            .getPackageStateInternal(androidPackage.packageName)!!
        addAllowlistedRestrictedPermissionsUnchecked(
            androidPackage,
            packageState.appId,
            params.allowlistedRestrictedPermissions,
            it,
        )
        setRequestedPermissionStates(
            packageState, it, params.permissionStates
        )
    }
}

USER_ALL 展开到包含预创建用户的用户集合。默认参数路径在现代实现中直接返回,因为基础权限状态已在 onPackageAdded 初始化;显式 installer 参数才追加受限权限 allowlist 和逐权限请求。

5. 状态事务 ​

5.1 Copy-on-write ​

源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt

kotlin
internal inline fun <T> getState(
    action: GetStateScope.() -> T
): T {
    return GetStateScope(state).action()
}

internal inline fun mutateState(
    crossinline action: MutateStateScope.() -> Unit
) {
    synchronized(stateLock) {
        val oldState = state
        val newState = oldState.toMutable()
        MutateStateScope(oldState, newState).action()
        persistence.write(newState)
        state = newState
        with(policy) {
            GetStateScope(newState).onStateMutated()
        }
    }
}

读操作使用当前 volatile AccessState 快照;写操作在 stateLock 下复制旧状态、执行 policy 变更、请求持久化、原子替换引用,最后通知策略消费者。读者不会看到正在半途修改的 mutable state。这是 Android 17 权限状态并发模型的核心,而不是旧式“所有读取都锁住 PermissionRegistry”。

5.2 生命周期事件 ​

kotlin
internal fun onPackageAdded(packageName: String) {
    val (packageStates, disabledSystemPackageStates) =
        packageManagerLocal.allPackageStates
    mutateState {
        with(policy) {
            onPackageAdded(
                packageStates,
                disabledSystemPackageStates,
                packageManagerInternal.knownPackages,
                packageName,
            )
        }
    }
}

包、用户和 volume 生命周期事件都会先取得 PackageManagerLocal 快照,再在单个权限状态事务中应用。PackageManager 提供包事实,AccessPolicy 决定状态变化,AccessPersistence 保存结果;三者职责不可互换。

6. 权限检查 ​

6.1 Binder 入口 ​

源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java

java
public int checkPermission(String packageName,
        String permissionName,
        String persistentDeviceId,
        int userId) {
    if (packageName == null || permissionName == null) {
        return PackageManager.PERMISSION_DENIED;
    }

    final CheckPermissionDelegate delegate;
    synchronized (mLock) {
        delegate = mCheckPermissionDelegate;
    }
    if (delegate == null) {
        return mPermissionManagerServiceImpl.checkPermission(
                packageName, permissionName,
                persistentDeviceId, userId);
    }
    return delegate.checkPermission(
            packageName, permissionName, persistentDeviceId,
            userId, mPermissionManagerServiceImpl::checkPermission);
}

null 参数按兼容行为直接 denied。测试、shell delegation 或权限代理存在时,CheckPermissionDelegate 可以包装真实检查;正常路径进入 PermissionService。

6.2 状态读取 ​

源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt

kotlin
override fun checkPermission(
    packageName: String,
    permissionName: String,
    deviceId: String,
    userId: Int,
): Int {
    if (!userManagerInternal.exists(userId)) {
        return PackageManager.PERMISSION_DENIED
    }

    val packageState = packageManagerLocal
        .withFilteredSnapshot(Binder.getCallingUid(), userId)
        .use { it.getPackageState(packageName) }
        ?: return PackageManager.PERMISSION_DENIED

    val granted = service.getState {
        isPermissionGranted(
            packageState, userId, permissionName, deviceId
        )
    }
    return if (granted) {
        PackageManager.PERMISSION_GRANTED
    } else {
        PackageManager.PERMISSION_DENIED
    }
}

检查先验证用户,再通过调用者过滤后的 PackageManagerLocal snapshot 查包,最后从 AccessState 读取 appId/user/permission/device 组合的 flags。包不可见或不存在时直接 denied;权限检查不会因调用者知道包名就绕过包可见性。

6.3 权限包含 ​

isPermissionGranted 还会查询 FULLER_PERMISSIONS 映射:若目标 permission 未授予,但其更完整权限已授予,也可能返回 granted。真正的单权限检查集中在 isSinglePermissionGranted,其中 permission flags、instant-app 限制和 device context 共同参与。

7. AppOps 协作 ​

7.1 数据访问检查 ​

源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java

java
private static final class PermissionCheckerService
        extends IPermissionChecker.Stub {
    public int checkPermission(String permission,
            AttributionSourceState sourceState,
            String message,
            boolean forDataDelivery,
            boolean startDataDelivery,
            boolean fromDatasource,
            int attributedOp) {
        final int result = checkPermission(
                mContext,
                mPermissionManagerServiceInternal,
                permission,
                new AttributionSource(sourceState),
                message,
                forDataDelivery,
                startDataDelivery,
                fromDatasource,
                attributedOp);

        if (startDataDelivery
                && result != PermissionChecker.PERMISSION_GRANTED
                && result != PermissionChecker.PERMISSION_SOFT_DENIED) {
            finishDataDelivery(...);
        }
        return result;
    }
}

checkPermission 回答静态 grant;PermissionCheckerService 还检查 attribution chain、AppOps 和数据访问开始/结束。带 PROTECTION_FLAG_APPOP 的权限可能 permission granted 但 AppOps ignored,从而得到 soft denied 或 hard denied。系统 API 若涉及真实数据访问,应使用对应的 PermissionChecker/AppOps 模式,而不是只调用 PackageManager.checkPermission。

8. Grant 与 revoke ​

8.1 门面委托 ​

java
public void grantRuntimePermission(String packageName,
        String permissionName, String persistentDeviceId,
        int userId) {
    mPermissionManagerServiceImpl.grantRuntimePermission(
            packageName, permissionName,
            persistentDeviceId, userId);
}

public void revokeRuntimePermission(String packageName,
        String permissionName, String persistentDeviceId,
        int userId, String reason) {
    mPermissionManagerServiceImpl.revokeRuntimePermission(
            packageName, permissionName,
            persistentDeviceId, userId, reason);
}

8.2 统一写入函数 ​

源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt

kotlin
override fun grantRuntimePermission(
    packageName: String,
    permissionName: String,
    deviceId: String,
    userId: Int,
) {
    setRuntimePermissionGranted(
        packageName, userId, permissionName,
        deviceId, isGranted = true,
    )
}

override fun revokeRuntimePermission(
    packageName: String,
    permissionName: String,
    deviceId: String,
    userId: Int,
    reason: String?,
) {
    setRuntimePermissionGranted(
        packageName, userId, permissionName,
        deviceId, isGranted = false,
        revokeReason = reason,
    )
}

grant/revoke 共用 setRuntimePermissionGranted,后者检查用户存在、跨用户权限、shell restriction、包和权限类型,再在 AccessState 事务中修改 flags。revoke 通常还会杀 UID,使进程不能继续使用撤销前缓存的能力;测试专用 notification revoke 路径可以显式跳过 kill。

9. 权限生命周期 ​

10. 失败边界 ​

10.1 包与用户不存在 ​

checkPermission 对不存在用户、不可见包或未知包直接 denied;grant/revoke 对未知用户记录警告并返回或抛出权限相关异常。不存在对象不是 granted 的默认状态。

10.2 Volume 未挂载 ​

包位于未挂载 volume 时,onPackageAdded 只记录顺序并等待 mount;安装参数也可能延迟应用。此时 PMS 有 PackageSetting 不代表 PermissionService 已完成该 volume 的状态变更。

10.3 AppOps 分歧 ​

permission granted、AppOps ignored 是合法组合,常用于前台限制、用户隐私开关和兼容行为。故障排查必须同时读取 permission flags 和 app-op mode,不能用一个结果替代另一个。

10.4 shared UID ​

单用户卸载和 shared UID 删除需要保留其他包/用户仍使用的权限状态;PermissionService 的 onPackageUninstalled 接收 package、appId、shared user packages 和 userId 来判断清理范围。删除一个包不必然删除整个 appId 的 permission flags。

11. 验证方法 ​

11.1 安装初始化 ​

准备包含 normal、dangerous 和 signature 权限请求的 APK。安装后使用 dumpsys package 和 pm list permissions 比较定义与 grant:normal 可随安装获得,dangerous 默认不等于用户已授权,signature 取决于证书关系。该实验验证保护级别分叉,不覆盖 AppOps。

11.2 Grant/revoke ​

对 debuggable 测试包执行 pm grant、pm revoke,前后调用 checkPermission 并观察进程是否因 revoke 被终止。关键断言是状态按 userId 变化,另一个用户不受影响;不具备 runtime 类型或未声明权限时应失败。

11.3 AppOps 组合 ​

选择一个 permission-to-op 映射的危险权限,保持 permission granted,分别把 AppOps mode 设为 allowed 与 ignored。比较 checkPermission 和真实 API/PermissionChecker 结果:前者可能保持 granted,后者随 AppOps 改变。这验证两层访问控制。

bash
adb shell dumpsys package <package.name>
adb shell pm check-permission <permission> <package.name> --user 0
adb shell appops get <package.name>

11.4 卸载重装 ​

先授予运行时权限,再普通卸载与 -k 卸载并重装。比较 AccessState/最终 grant:完整删除应清理相应用户权限状态;保留数据路径可能保留身份和部分授权事实,但重新安装仍受签名、版本和 installer params 约束。

12. 源码路线 ​

  1. AccessCheckingService.onStart/initialize:确认现代实现、输入事实和持久化。
  2. PermissionManagerService.create:确认 Binder 与 LocalServices 门面。
  3. PermissionService.onPackageAdded/onPackageInstalled:连接 PMS 安装生命周期。
  4. AccessCheckingService.mutateState:理解权限状态事务和并发读取。
  5. PermissionService.checkPermission:跟踪包可见性、user/appId/device 与 flags。
  6. setRuntimePermissionGranted:继续阅读 grant/revoke 的权限、flag 和 kill UID 分支。
  7. PermissionCheckerService:连接 attribution chain 与 AppOps 数据访问。

Android 17 权限框架的核心不是单个 PermissionManagerService 类,而是一条分层链路:PackageManager 提供包和用户事实,Java Binder 门面承接 API,PermissionService 在 AccessPolicy 下读写 AccessState,AccessPersistence 保存事务结果,PermissionChecker 再把静态 grant 与 AppOps、attribution 组合成真实访问决定。后续阅读任何权限问题,都应先判断它属于定义、状态、运行时变更、AppOps 还是最终资源服务检查中的哪一层。