默认权限策略
本文承接 权限框架、权限类型 和 权限授予。DefaultPermissionGrantPolicy 不是普通 runtime grant 的 UI,也不是 privapp-permissions 静态白名单;它在系统启动、新用户创建和默认 handler 变化时,根据系统身份、known package、provider 和配置例外,为特定包初始化 runtime permission 状态。本文专讲 Android 17 真实 Java 策略类的选择、缓存、fixed/allowlist flags 和撤销边界。
1. 策略入口
1.1 一次批处理
源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
public void grantDefaultPermissions(int userId) {
final DelayingPackageManagerCache pm =
new DelayingPackageManagerCache();
grantPermissionsToSysComponentsAndPrivApps(pm, userId);
grantDefaultSystemHandlerPermissions(pm, userId);
grantSignatureAppsNotificationPermissions(pm, userId);
grantDefaultPermissionExceptions(pm, userId);
// 最后一次性提交缓存中的 flags/grants
pm.apply();
}一次默认授权由四个阶段组成:系统组件/特权 app、默认 system handler、platform-signature app 的通知权限、配置例外。DelayingPackageManagerCache 把操作延迟到最后 apply(),避免每个权限都独立触发持久化和监听。
1.2 user scope
默认权限函数接收 userId,并不隐含 USER_ALL。系统启动会为既有用户分别调用;新用户创建时只初始化新用户。角色/默认 handler 变化也按目标 user 重新计算,防止 user 0 的授权泄漏到工作 profile。
2. 包操作封装
2.1 抽象操作
源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
private interface PackageManagerWrapper {
int getPermissionFlags(String permission,
PackageInfo pkg, UserHandle user);
void updatePermissionFlags(String permission,
PackageInfo pkg, int flagMask,
int flagValues, UserHandle user);
void grantPermission(String permission,
PackageInfo pkg, UserHandle user);
void revokePermission(String permission,
PackageInfo pkg, UserHandle user);
boolean isGranted(String permission,
PackageInfo pkg, UserHandle user);
}策略只依赖 wrapper,不把 PackageManagerInternal 或 PermissionService 细节散落到每个默认 handler 分支。这个接口还允许测试替换包查询和 grant 行为。
2.2 延迟实现
NO_PM_CACHE 直接调用 PermissionManager 内部 API;DelayingPackageManagerCache 则缓存 PackageInfo、permission flags 和待执行操作。默认入口使用延迟实现,公开的单个 handler 变更 API 可以使用 no-cache,确保角色切换后立即生效。
3. 系统组件
3.1 选择包
源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
private void grantPermissionsToSysComponentsAndPrivApps(
DelayingPackageManagerCache pm, int userId) {
final List<PackageInfo> packages =
mContext.getPackageManager()
.getInstalledPackagesAsUser(
DEFAULT_PACKAGE_INFO_QUERY_FLAGS,
UserHandle.USER_SYSTEM);
for (PackageInfo pkg : packages) {
if (pkg == null) continue;
pm.addPackageInfo(pkg.packageName, pkg);
if (!pm.isSysComponentOrPersistentPlatformSignedPrivApp(pkg)
|| !doesPackageSupportRuntimePermissions(pkg)
|| ArrayUtils.isEmpty(pkg.requestedPermissions)) {
continue;
}
grantRuntimePermissionsForSystemPackage(pm, userId, pkg);
}
}候选包必须是系统组件或持久 platform-signed privileged app,并且支持 runtime permissions、声明了 requested permissions。默认策略不是“给所有 priv-app 全部危险权限”。
3.2 fixed 授予
private void grantPermissionsToSystemPackage(
PackageManagerWrapper pm, String packageName,
int userId, boolean systemFixed,
Set<String>... permissionGroups) {
if (!pm.isSystemPackage(packageName)) return;
grantPermissionsToPackage(
pm, pm.getSystemPackageInfo(packageName),
userId, systemFixed,
false, true, permissionGroups);
}系统组件可以按 systemFixed=true 授予,使用户不能在 Settings 中撤销;默认 handler 某些权限只普通授予,让用户仍可改变。fixed 是策略选择,不由 permission protectionLevel 自动决定。
4. 默认 Handler
4.1 Provider 注入
源码文件:frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
private void grantDefaultSystemHandlerPermissions(
PackageManagerWrapper pm, int userId) {
final PackagesProvider dialerProvider;
final PackagesProvider smsProvider;
final PackagesProvider locationProvider;
synchronized (mLock) {
dialerProvider = mDialerAppPackagesProvider;
smsProvider = mSmsAppPackagesProvider;
locationProvider = mLocationPackagesProvider;
}
final String[] dialers = dialerProvider == null
? null : dialerProvider.getPackages(userId);
final String[] smsApps = smsProvider == null
? null : smsProvider.getPackages(userId);
final String[] locations = locationProvider == null
? null : locationProvider.getPackages(userId);默认 handler 的真实包名来自 provider/role/intent resolution,而非固定字符串。provider 在 mLock 下取出,调用 getPackages(userId) 时已经脱离策略锁;返回 null 时策略会通过默认 intent handler 查询兜底。
4.2 handler 权限组
if (dialers == null) {
final String dialer = getDefaultSystemHandlerActivityPackage(
pm, Intent.ACTION_DIAL, userId);
grantDefaultPermissionsToDefaultSystemDialerApp(
pm, dialer, userId);
} else {
for (String dialer : dialers) {
grantDefaultPermissionsToDefaultSystemDialerApp(
pm, dialer, userId);
}
}
if (smsApps == null) {
final String sms = getDefaultSystemHandlerActivityPackageForCategory(
pm, Intent.CATEGORY_APP_MESSAGING, userId);
grantDefaultPermissionsToDefaultSystemSmsApp(pm, sms, userId);
}拨号器会获得 PHONE、CONTACTS、SMS、MICROPHONE、CAMERA 等组合,短信 app 也有自己的集合。每个 helper 仍会过滤 package 是否 system、是否支持 runtime 和是否真正 requested permission。
4.3 通知权限
private void grantSignatureAppsNotificationPermissions(
PackageManagerWrapper pm, int userId) {
final List<PackageInfo> packages =
mContext.getPackageManager().getInstalledPackagesAsUser(
DEFAULT_PACKAGE_INFO_QUERY_FLAGS,
UserHandle.USER_SYSTEM);
for (PackageInfo pkg : packages) {
if (pkg == null
|| !pkg.applicationInfo.isSystemApp()
|| !pkg.applicationInfo.isSignedWithPlatformKey()) {
continue;
}
grantRuntimePermissionsForSystemPackage(
pm, userId, pkg, NOTIFICATION_PERMISSIONS);
}
}POST_NOTIFICATIONS 的默认授予使用 system app + platform key 条件,不等于所有通知权限都由 manifest 安装自动授予。最终是否被 AppOps/用户设置影响仍由通知和权限服务继续判断。
5. 权限授予实现
5.1 requested 过滤
private void grantRuntimePermissions(
PackageManagerWrapper pm, PackageInfo pkg,
Set<String> permissions, boolean systemFixed,
boolean ignoreSystemPackage,
boolean whitelistRestrictedPermissions,
int userId) {
if (pkg == null || ArrayUtils.isEmpty(pkg.requestedPermissions)) {
return;
}
for (String permission : permissions) {
if (!ArrayUtils.contains(
pkg.requestedPermissions, permission)) {
continue;
}
final PermissionInfo info = pm.getPermissionInfo(permission);
if (info == null || !info.isRuntime()) {
continue;
}
if (!ignoreSystemPackage && !pm.isSystemPackage(pkg.packageName)) {
continue;
}
pm.grantPermission(permission, pkg,
UserHandle.of(userId));
pm.updatePermissionFlags(permission, pkg,
PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT
| (systemFixed
? PackageManager.FLAG_PERMISSION_SYSTEM_FIXED : 0),
PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT
| (systemFixed
? PackageManager.FLAG_PERMISSION_SYSTEM_FIXED : 0),
UserHandle.of(userId));
}
}默认策略不强行授予未声明权限,也不处理 normal/signature 等非 runtime permission。whitelistRestrictedPermissions 还会把 restricted 权限加入 allowlist,单独影响 restriction flags;它和 grant 本身是两个操作。
5.2 缓存提交
public void grantDefaultPermissions(int userId) {
final DelayingPackageManagerCache pm =
new DelayingPackageManagerCache();
grantPermissionsToSysComponentsAndPrivApps(pm, userId);
grantDefaultSystemHandlerPermissions(pm, userId);
grantSignatureAppsNotificationPermissions(pm, userId);
grantDefaultPermissionExceptions(pm, userId);
pm.apply();
}批处理保证同一个用户的默认权限变更尽量一起提交。某个包缺失、权限未声明或不支持 runtime 时,helper 跳过该项,不应因此把整个系统启动判定为失败。
6. 配置例外
6.1 XML 输入
默认权限例外来自设备配置目录中的 XML。每条 exception 至少包含 package、permission、fixed/allowlist 等策略属性;DefaultPermissionGrantPolicy 读取后仍会验证包存在、权限是 runtime、包是否允许获得该权限。
6.2 例外边界
配置例外不是 privileged permission allowlist 的替代品。它主要影响 runtime pregrant/restricted allowlist;signature/internal 的保护仍由 PermissionService 的 protection 规则和签名判断决定。
7. 撤销与变化
7.1 Handler 变化
当默认拨号器、短信或 telephony data service 发生变化,策略会对旧包撤销由默认策略授予的权限,再对新包执行 grant。撤销通常只清理 GRANTED_BY_DEFAULT/system-fixed 对应来源,不能删除用户独立授予。
7.2 用户创建
新用户创建时,策略以该 userId 重新解析 handlers 和 exceptions。由于 PackageUserState、runtime flags、AppOps exemption 都按用户保存,系统 user 的默认授权不会直接复制到新 profile。
8. 失败与验证
8.1 包缺失
默认 handler provider 返回不存在包时,策略跳过;解析不到 intent handler 也不会授予虚构包。日志和 dumpsys package 应显示最终选中的 system handler。
8.2 权限未声明
即使权限组列表包含 CAMERA/PHONE,目标包未在 requested permissions 中也不会授予。验证时必须同时检查 Manifest 请求和最终 flags,不能只检查策略常量。
8.3 固定边界
对拨号器等 system handler 检查 FLAG_PERMISSION_SYSTEM_FIXED;再切换默认 handler,确认旧包的默认来源被撤销但用户独立 grant 不被误删。
8.4 用户隔离
创建新 user 或 work profile,比较每个用户的 handler 和默认权限 flags。若 provider 为不同用户返回不同包,授予结果也应分离。
adb shell dumpsys package <package.name>
adb shell pm check-permission <permission> <package.name> --user 0
adb shell cmd role get-role-holders <role.name> --user 09. 源码路线
DefaultPermissionGrantPolicy.grantDefaultPermissions:掌握四阶段批处理。PackageManagerWrapper/DelayingPackageManagerCache:理解权限操作和提交时机。grantPermissionsToSysComponentsAndPrivApps:系统组件/priv-app 候选条件。grantDefaultSystemHandlerPermissions:provider、intent handler 和权限组。grantRuntimePermissions:requested、runtime、systemFixed 和 restricted allowlist。grantDefaultPermissionExceptions:设备配置例外。- handler 变化与 user 创建入口:继续阅读撤销和 user-scoped 初始化。
DefaultPermissionGrantPolicy 是“默认身份到权限状态”的策略编排器:它先按 user 解析系统组件和 handler,再验证包声明与 runtime 类型,通过缓存批量修改 grant/fixed/allowlist flags。它不替代 PermissionService 的安全检查,也不等于静态 privileged allowlist;遇到默认权限问题时,应同时检查候选包、requested permissions、flags 来源、用户和 AppOps 状态。
