1. 控制界面
在设置–》应用–》Email–》权限,然后可以看到最直观的界面显示 AppPermissionsFragment.java
这个界面是在packages/apps/PackageInstaller 里面来进行控制。
1. com.android.packageinstaller.permission.ui.AppPermissionsFragment#onCreate
在初始化过程中,会创建AppPermissions
@Override
public void onCreate(Bundle savedInstanceState) {
...
mAppPermissions = new (activity, packageInfo, null, true, new Runnable() {
@Override
public void run() {
getActivity().finish();
}
});
loadPreferences();
}
- com.android.packageinstaller.permission.model.AppPermissions#AppPermissions 接下来直接进入到
- com.android.packageinstaller.permission.model.AppPermissions#loadPermissionGroups
private void loadPermissionGroups() {
...
if (mFilterPermissions != null) {
...
} else {
for (String requestedPerm : mPackageInfo.requestedPermissions) {
if (hasGroupForPermission(requestedPerm)) {
continue;
}
// create AppPermissionGroup according to the package info
`AppPermissionGroup group = AppPermissionGroup.create(mContext,
mPackageInfo, requestedPerm);`
if (group == null) {
continue;
}
mGroups.add(group);
}
}
...
}
- com.android.packageinstaller.permission.model.#create(android.content.Context, android.content.pm.PackageInfo, java.lang.String)
这个方法中,首先会根据permissionName收集permissionInfo
try {
permissionInfo = context.getPackageManager().getPermissionInfo(permissionName, 0);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
static PermissionInfo generatePermissionInfo(
BasePermission bp, int flags) {
if (bp.perm != null) {
return PackageParser.generatePermissionInfo(bp.perm, flags);
}
PermissionInfo pi = new PermissionInfo();
pi.name = bp.name;
pi.packageName = bp.sourcePackage;
pi.nonLocalizedLabel = bp.name;
pi.protectionLevel = bp.protectionLevel;
return pi;
}
从以上信息可以看出,PermissionInfo大致上会由name、packageName、nonLocalizedLabel、protectionLevel组成。
接下来就会根据PermissionInfo收集PermissionGroupInfo。由于PermissionGroupInfo里面包含了所有的Permission,Android仅仅处理runtime permissions.所以最终会将PermissionGroupInfo里面的非runtime permisson和当前应用没有请求的权限过滤出去,这样就返回了当前应用请求的所有的android runtime permission.以下信息都会过滤:
- 非Android 定义的权限
- 非Runtime Permission(requestedPermissionInfo.protectionLevel != PermissionInfo.PROTECTION_DANGEROUS)
- targetapi 低于Android 6.0以下的应用不适用于Android Runtime Permission
- -
public static AppPermissionGroup create(Context context, PackageInfo packageInfo,
PackageItemInfo groupInfo, List<PermissionInfo> permissionInfos,
UserHandle userHandle) {
groupInfo.packageName, groupInfo.loadLabel(context.getPackageManager()),
loadGroupDescription(context, groupInfo), groupInfo.packageName, groupInfo.icon,
userHandle);
if (groupInfo instanceof PermissionInfo) {
permissionInfos = new ArrayList<>();
permissionInfos.add((PermissionInfo) groupInfo);
}
if (permissionInfos == null || permissionInfos.isEmpty()) {
return null;
}
final int permissionCount = packageInfo.requestedPermissions.length;
for (int i = 0; i < permissionCount; i++) {
String requestedPermission = packageInfo.requestedPermissions[i];
PermissionInfo requestedPermissionInfo = null;
for (PermissionInfo permissionInfo : permissionInfos) {
if (requestedPermission.equals(permissionInfo.name)) {
requestedPermissionInfo = permissionInfo;
break;
}
}
if (requestedPermissionInfo == null) {
continue;
}
// Collect only runtime permissions.
if (requestedPermissionInfo.protectionLevel != PermissionInfo.PROTECTION_DANGEROUS) {
continue;
}
// Don't allow toggle of non platform defined permissions for legacy apps via app ops.
if (packageInfo.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1
&& !PLATFORM_PACKAGE_NAME.equals(requestedPermissionInfo.packageName)) {
continue;
}
final boolean granted = (packageInfo.requestedPermissionsFlags[i]
& PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
final int appOp = PLATFORM_PACKAGE_NAME.equals(requestedPermissionInfo.packageName)
? AppOpsManager.permissionToOpCode(requestedPermissionInfo.name)
: AppOpsManager.OP_NONE;
final boolean appOpAllowed = appOp != AppOpsManager.OP_NONE
&& context.getSystemService(AppOpsManager.class).checkOp(appOp,
packageInfo.applicationInfo.uid, packageInfo.packageName)
== AppOpsManager.MODE_ALLOWED;
final int flags = context.getPackageManager().getPermissionFlags(
requestedPermission, packageInfo.packageName, userHandle);
Permission permission = new Permission(requestedPermission, granted,
appOp, appOpAllowed, flags);
group.addPermission(permission);
}
return group;
}
经过如上操作,会获取权满足所有条件的权限。然后以截图中的形式显示。
权限的撤掉和授予
撤销权限
com.android.packageinstaller.permission.model.AppPermissionGroup#revokeRuntimePermissions
- com.android.packageinstaller.permission.model.AppPermissionGroup#revokeRuntimePermissions
- com.android.server.pm.PackageManagerService#revokeRuntimePermission
- com.android.server.pm.PermissionsState#revokeRuntimePermission
com.android.server.pm.PermissionsState.PermissionData#revoke 此时已经被授予的权限将被取消
如上所属。
授予权限
- com.android.packageinstaller.permission.model.AppPermissionGroup#grantRuntimePermissions
- android.app.ApplicationPackageManager#grantRuntimePermission
- com.android.server.pm.PackageManagerService#grantRuntimePermission
- com.android.server.pm.PermissionsState#grantRuntimePermission
- com.android.server.pm.PermissionsState.PermissionData#grant
通过授予和撤销可以看出最终都是通过存入com.android.server.pm.PermissionsState.PermissionData#mUserStates来完成的。
也就是说权限管理里面最终控制的地方实际上是:
frameworks/base/services/core/java/com/android/server/pm/PermissionsState.java
mSettings.mPermissions是如何初始化的
mSettings.mPermissions初始化分为几大部分:
- com.android.server.pm.PackageManagerService#PackageManagerService
根据systemconfig里面的配置来进行初始化
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
...
SystemConfig systemConfig = SystemConfig.getInstance();
...
// Propagate permission configuration in to package manager.
ArrayMap<String, SystemConfig.PermissionEntry> permConfig
= systemConfig.getPermissions();
for (int i=0; i<permConfig.size(); i++) {
SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
BasePermission bp = mSettings.mPermissions.get(perm.name);
if (bp == null) {
bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
mSettings.mPermissions.put(perm.name, bp);
}
if (perm.gids != null) {
bp.setGids(perm.gids, perm.perUser);
}
}
...
}
在SystemConfig.getInstance()中,读取system/etc/permissions/里面的所有包含permission标签的xml文件(主要是解析platform.xml),然后将这个值保存到com.android.server.SystemConfig#mPermissions供后面com.android.server.SystemConfig#getPermissions调用。
2、 com.android.server.pm.PackageManagerService#scanPackageDirtyLI
在开机过程中,扫描所有的apk的过程中,会进行如下的动作
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,
int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
...
ArrayMap<String, BasePermission> permissionMap =
p.tree ? mSettings.mPermissionTrees
: mSettings.mPermissions;
BasePermission bp = permissionMap.get(p.info.name);
// Allow system apps to redefine non-system permissions
if (bp != null && !Objects.equals(bp.sourcePackage, p.info.packageName)) {
final boolean currentOwnerIsSystem = (bp.perm != null
&& isSystemApp(bp.perm.owner));
if (isSystemApp(p.owner)) {
if (bp.type == BasePermission.TYPE_BUILTIN && bp.perm == null) {
// It's a built-in permission and no owner, take ownership now
bp.packageSetting = pkgSetting;
bp.perm = p;
bp.uid = pkg.applicationInfo.uid;
bp.sourcePackage = p.info.packageName;
p.info.flags |= PermissionInfo.FLAG_INSTALLED;
} else if (!currentOwnerIsSystem) {
String msg = "New decl " + p.owner + " of permission "
+ p.info.name + " is system; overriding " + bp.sourcePackage;
reportSettingsProblem(Log.WARN, msg);
bp = null;
}
}
}
if (bp == null) {
bp = new BasePermission(p.info.name, p.info.packageName,
BasePermission.TYPE_NORMAL);
permissionMap.put(p.info.name, bp);
}
}
在permissionMap.put(p.info.name,bp);方法中,对于每一个扫描到的包,都会将他的权限相关的信息,添加到mSettings.mPermissions.
所有的权限的变更都会通过com.android.server.pm.Settings#writeLPr将相关信息写入到/data/system/packages.xml里面去了。
mSettingsFilename = new File(mSystemDir, “packages.xml”);
permission-group 是如何初始化
com.android.server.pm.PackageManagerService#scanPackageDirtyLI
在扫面所有apk和安装某一个apk的过程中,会将所有的含有permission-group的权限组解析出来,存入到
android.content.pm.PackageParser.Package#permissionGroups
最后会将里面会将所有的解析出来的permissionGroups添加到com.android.server.pm.PackageManagerService#mPermissionGroups里面供PackageInstaller调用。
授予应用默认权限
com.android.server.pm.PackageManagerService#systemReady
// If we upgraded grant all default permissions before kicking off.
for (int userId : grantPermissionsUserIds) {
mDefaultPermissionPolicy.grantDefaultPermissions(userId);
}
在grantDefaultPermissions中,可以授予系统应用默认权限。
本文介绍了Android运行时权限的控制界面,包括权限的撤消和授予流程。详细解析了`AppPermissionsFragment`如何加载权限组,并展示了如何筛选出适用于Runtime Permissions的权限。同时,概述了权限的撤销和授予涉及的方法及权限状态的管理核心——`PermissionsState`。
1万+

被折叠的 条评论
为什么被折叠?



