[toc]
0 综述 基于 Android 7.1.1,分析权限管理相关知识,本文权限信息的获取!
PackageManagerService 提供了很多个接口用于获取权限的信息!
1 获取权限组相关的信息! PackageManagerService.mPermissionGroups 保存了从所有 Application 中解析到的权限组信息!
PackageManagerService 提供了如下的两个接口来获得权限组的信息!
1.1 PackageManagerS.getAllPermissionGroups 获得所有的权限组1 2 3 4 5 6 7 8 9 10 11 12 13 @Override public @NonNull ParceledListSlice<PermissionGroupInfo> getAllPermissionGroups (int flags) { synchronized (mPackages) { final int N = mPermissionGroups.size(); ArrayList<PermissionGroupInfo> out = new ArrayList<PermissionGroupInfo>(N); for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) { out.add(PackageParser.generatePermissionGroupInfo(pg, flags)); } return new ParceledListSlice<>(out); } }
1.2 PackageManagerS.getPermissionGroupInfo 获得指定的权限组信息
1 2 3 4 5 6 7 8 @Override public PermissionGroupInfo getPermissionGroupInfo (String name, int flags) { synchronized (mPackages) { return PackageParser.generatePermissionGroupInfo( mPermissionGroups.get(name), flags); } }
1.2.1 PackageParser.generatePermissionGroupInfo 该方法会新创建的 PermissionGroupInfo 对象,作为解析数据 PermissionGroup.PermissionGroupInfo 的拷贝!!
1 2 3 4 5 6 7 8 9 10 11 12 13 public static final PermissionGroupInfo generatePermissionGroupInfo( PermissionGroup pg, int flags) { if (pg == null) return null; // 如果 flags 没有设置 PackageManager.GET_META_DATA,直接返回 PermissionGroup.PermissionGroupInfo if ((flags & PackageManager.GET_META_DATA) == 0) { return pg.info; } // 如果 flags 设置了 PackageManager.GET_META_DATA,我们会新建一个 PermissionGroupInfo 对象, // 将解析的数据拷贝进来! PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info); pgi.metaData = pg.metaData; return pgi; }
2 获取权限相关的信息! mSettings.mPermissions 保存了系统和应用定义的所有的权限信息!
PackageManagerService 提供了如下的两个接口来获得权限组的信息!
2.1 PackageParser.getPermissionInfo 获得指定 name 的权限信息!
1 2 3 4 5 6 7 8 9 10 11 @Override public PermissionInfo getPermissionInfo (String name, int flags) { synchronized (mPackages) { final BasePermission p = mSettings.mPermissions.get(name); if (p != null ) { return generatePermissionInfo(p, flags); } return null ; } }
2.2 PackageParser.queryPermissionsByGroup 获得同一个 group 中的所有权限信息!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @Override public @Nullable ParceledListSlice<PermissionInfo> queryPermissionsByGroup (String group, int flags) { synchronized (mPackages) { if (group != null && !mPermissionGroups.containsKey(group)) { return null ; } ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10 ); for (BasePermission p : mSettings.mPermissions.values()) { if (group == null ) { if (p.perm == null || p.perm.info.group == null ) { out.add(generatePermissionInfo(p, flags)); } } else { if (p.perm != null && group.equals(p.perm.info.group)) { out.add(PackageParser.generatePermissionInfo(p.perm, flags)); } } } return new ParceledListSlice<>(out); } }
2.2.1 PackageParser.generatePermissionInfo 该方法会新创建的 PermissionInfo 对象,拷贝 Permission 的数据!!
1 2 3 4 5 6 7 8 9 10 public static final PermissionInfo generatePermissionInfo ( Permission p, int flags) { if (p == null ) return null ; if ((flags & PackageManager.GET_META_DATA) == 0 ) { return p.info; } PermissionInfo pi = new PermissionInfo(p.info); pi.metaData = p.metaData; return pi; }
如果不需要 GET_META_DATA,那就直接返回解析得到的 PermissionInfo 对象!
3 获取权限标志位的信息! PackageManagerService 提供了如下接口来获得权限标志位组的信息!
PackageManagerService.mPackages 用于保存所有解析过的 Pacakge 信息!
mSettings.mPermissions 中保存了系统中所有的权限信息!
3.1 PackageManagerService.getPermissionFlags 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @Override public int getPermissionFlags (String name, String packageName, int userId) { if (!sUserManager.exists(userId)) { return 0 ; } enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags" ); enforceCrossUserPermission(Binder.getCallingUid(), userId, true , false , "getPermissionFlags" ); synchronized (mPackages) { final PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null ) { return 0 ; } final BasePermission bp = mSettings.mPermissions.get(name); if (bp == null ) { return 0 ; } SettingBase sb = (SettingBase) pkg.mExtras; if (sb == null ) { return 0 ; } PermissionsState permissionsState = sb.getPermissionsState(); return permissionsState.getPermissionFlags(name, userId); } }
方法很简单,不多说了!
4 更新权限标志位的信息! PackageManagerService 提供了如下接口来更新权限标志位的信息!
4.1 PackageManagerService.updatePermissionFlags 该方法更新指定权限的 flags,flagMask 表示的是 flags 的位掩码,用来屏蔽某些位;flagValues 表示新的标志位值!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 @Override public void updatePermissionFlags (String name, String packageName, int flagMask, int flagValues, int userId) { if (!sUserManager.exists(userId)) { return ; } enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags" ); enforceCrossUserPermission(Binder.getCallingUid(), userId, true , true , "updatePermissionFlags" ); if (getCallingUid() != Process.SYSTEM_UID) { flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT; flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT; flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; } synchronized (mPackages) { final PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null ) { throw new IllegalArgumentException("Unknown package: " + packageName); } final BasePermission bp = mSettings.mPermissions.get(name); if (bp == null ) { throw new IllegalArgumentException("Unknown permission: " + name); } SettingBase sb = (SettingBase) pkg.mExtras; if (sb == null ) { throw new IllegalArgumentException("Unknown package: " + packageName); } PermissionsState permissionsState = sb.getPermissionsState(); boolean hadState = permissionsState.getRuntimePermissionState(name, userId) != null ; if (permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues)) { if (permissionsState.getInstallPermissionState(name) != null ) { scheduleWriteSettingsLocked(); } else if (permissionsState.getRuntimePermissionState(name, userId) != null || hadState) { mSettings.writeRuntimePermissionsForUserLPr(userId, false ); } } } }
先会更新 flags,更新成功后,会根据权限的类型去,去更新对应的持久化文件!
4.1.1 PermissionsState.updatePermissionFlags PermissionsState 用于管理 package 的权限状态!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public boolean updatePermissionFlags (BasePermission permission, int userId, int flagMask, int flagValues) { enforceValidUserId(userId); final boolean mayChangeFlags = flagValues != 0 || flagMask != 0 ; if (mPermissions == null ) { if (!mayChangeFlags) { return false ; } ensurePermissionData(permission); } PermissionData permissionData = mPermissions.get(permission.name); if (permissionData == null ) { if (!mayChangeFlags) { return false ; } permissionData = ensurePermissionData(permission); } final int oldFlags = permissionData.getFlags(userId); final boolean updated = permissionData.updateFlags(userId, flagMask, flagValues); if (updated) { final int newFlags = permissionData.getFlags(userId); if ((oldFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) == 0 && (newFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0 ) { if (mPermissionReviewRequired == null ) { mPermissionReviewRequired = new SparseBooleanArray(); } mPermissionReviewRequired.put(userId, true ); } else if ((oldFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0 && (newFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) == 0 ) { if (mPermissionReviewRequired != null ) { mPermissionReviewRequired.delete(userId); if (mPermissionReviewRequired.size() <= 0 ) { mPermissionReviewRequired = null ; } } } } return updated; }
整个方法很简单,无需多说,前面分析过了,这里就不多说了!!
4.1.1.1 PermissionData.updateFlags PermissionData 用于封装指定权限的状态信息!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public boolean updateFlags (int userId, int flagMask, int flagValues) { if (isInstallPermission()) { userId = UserHandle.USER_ALL; } if (!isCompatibleUserId(userId)) { return false ; } final int newFlags = flagValues & flagMask; PermissionState userState = mUserStates.get(userId); if (userState != null ) { final int oldFlags = userState.mFlags; userState.mFlags = (userState.mFlags & ~flagMask) | newFlags; if (userState.isDefault()) { mUserStates.remove(userId); } return userState.mFlags != oldFlags; } else if (newFlags != 0 ) { userState = new PermissionState(mPerm.name); userState.mFlags = newFlags; mUserStates.put(userId, userState); return true ; } return false ; }
这里首先,通过 flagValues & flagMask 取其相同的位值为 newFlags!
设置最新的 flags 的时候,先是 oldFlags & ~flagMask 取 oldFlags 和 ~flagMask 相同的位值,然后加上 newFlags!
4.2 PackageManagerService.updatePermissionFlagsForAllApps 该方法更新指定所有权限的 flags!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 @Override public void updatePermissionFlagsForAllApps (int flagMask, int flagValues, int userId) { if (!sUserManager.exists(userId)) { return ; } enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlagsForAllApps" ); enforceCrossUserPermission(Binder.getCallingUid(), userId, true , true , "updatePermissionFlagsForAllApps" ); if (getCallingUid() != Process.SYSTEM_UID) { flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; } synchronized (mPackages) { boolean changed = false ; final int packageCount = mPackages.size(); for (int pkgIndex = 0 ; pkgIndex < packageCount; pkgIndex++) { final PackageParser.Package pkg = mPackages.valueAt(pkgIndex); SettingBase sb = (SettingBase) pkg.mExtras; if (sb == null ) { continue ; } PermissionsState permissionsState = sb.getPermissionsState(); changed |= permissionsState.updatePermissionFlagsForAllPermissions( userId, flagMask, flagValues); } if (changed) { mSettings.writeRuntimePermissionsForUserLPr(userId, false ); } } }
4.2.1 PermissionsState.updatePermissionFlagsForAllPermissions 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public boolean updatePermissionFlagsForAllPermissions ( int userId, int flagMask, int flagValues) { enforceValidUserId(userId); if (mPermissions == null ) { return false ; } boolean changed = false ; final int permissionCount = mPermissions.size(); for (int i = 0 ; i < permissionCount; i++) { PermissionData permissionData = mPermissions.valueAt(i); changed |= permissionData.updateFlags(userId, flagMask, flagValues); } return changed; }
流程很简单,不多说了!