diff options
author | Svet Ganov <svetoslavganov@google.com> | 2015-05-09 19:47:27 -0700 |
---|---|---|
committer | Svetoslav <svetoslavganov@google.com> | 2015-05-11 17:09:40 -0700 |
commit | 785a9b6369db4c46a389a43ae30e1f6e8003366b (patch) | |
tree | d1e3b969ebb7a71c7e7409148278493a690da6b6 /src/com/android/packageinstaller/permission/model/PermissionGroup.java | |
parent | a8717e68410873ec51d3fa5fa805f3d3587fb743 (diff) | |
download | android_packages_apps_PackageInstaller-785a9b6369db4c46a389a43ae30e1f6e8003366b.tar.gz android_packages_apps_PackageInstaller-785a9b6369db4c46a389a43ae30e1f6e8003366b.tar.bz2 android_packages_apps_PackageInstaller-785a9b6369db4c46a389a43ae30e1f6e8003366b.zip |
Add support for permissions gran/revoke policy - package installer.
Change-Id: Id2d5733db0978e909d7159b0eade2b85ec838924
Diffstat (limited to 'src/com/android/packageinstaller/permission/model/PermissionGroup.java')
-rw-r--r-- | src/com/android/packageinstaller/permission/model/PermissionGroup.java | 173 |
1 files changed, 143 insertions, 30 deletions
diff --git a/src/com/android/packageinstaller/permission/model/PermissionGroup.java b/src/com/android/packageinstaller/permission/model/PermissionGroup.java index 9a5291d8..749ac29e 100644 --- a/src/com/android/packageinstaller/permission/model/PermissionGroup.java +++ b/src/com/android/packageinstaller/permission/model/PermissionGroup.java @@ -37,6 +37,8 @@ public final class PermissionGroup implements Comparable<PermissionGroup> { private static final String KILL_REASON_APP_OP_CHANGE = "Permission related app op changed"; private final Context mContext; + private final UserHandle mUserHandle; + private final PackageManager mPackageManager; private final AppOpsManager mAppOps; private final ActivityManager mActivityManager; @@ -130,28 +132,24 @@ public final class PermissionGroup implements Comparable<PermissionGroup> { continue; } - final boolean granted = (packageInfo.requestedPermissionsFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0; - final int appOp; - final boolean appOpAllowed; + final int appOp = PLATFORM_PACKAGE_NAME.equals(requestedPermissionInfo.packageName) + ? AppOpsManager.permissionToOpCode(requestedPermissionInfo.name) + : AppOpsManager.OP_NONE; - if (group.mAppSupportsRuntimePermissions) { - appOp = AppOpsManager.OP_NONE; - appOpAllowed = false; - } else { - appOp = PLATFORM_PACKAGE_NAME.equals(requestedPermissionInfo.packageName) - ? AppOpsManager.permissionToOpCode(requestedPermissionInfo.name) - : AppOpsManager.OP_NONE; - appOpAllowed = appOp != AppOpsManager.OP_NONE - && context.getSystemService(AppOpsManager.class).checkOp(appOp, - packageInfo.applicationInfo.uid, packageInfo.packageName) - == AppOpsManager.MODE_ALLOWED; - } + 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, + new UserHandle(context.getUserId())); Permission permission = new Permission(requestedPermission, granted, - appOp, appOpAllowed); + appOp, appOpAllowed, flags); group.addPermission(permission); } @@ -161,6 +159,8 @@ public final class PermissionGroup implements Comparable<PermissionGroup> { private PermissionGroup(Context context, PackageInfo packageInfo, String name, CharSequence label, String iconPkg, int iconResId) { mContext = context; + mUserHandle = new UserHandle(mContext.getUserId()); + mPackageManager = mContext.getPackageManager(); mPackageInfo = packageInfo; mAppSupportsRuntimePermissions = packageInfo.applicationInfo .targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1; @@ -212,7 +212,7 @@ public final class PermissionGroup implements Comparable<PermissionGroup> { return true; } - public boolean grantRuntimePermissions() { + public boolean grantRuntimePermissions(boolean fixedByTheUser) { final boolean isSharedUser = mPackageInfo.sharedUserId != null; final int uid = mPackageInfo.applicationInfo.uid; @@ -221,41 +221,76 @@ public final class PermissionGroup implements Comparable<PermissionGroup> { // to the permission if the permission is granted to the app. for (Permission permission : mPermissions.values()) { if (mAppSupportsRuntimePermissions) { + // Grant the permission if needed. if (!permission.isGranted()) { - mContext.getPackageManager().grantPermission(mPackageInfo.packageName, - permission.getName(), new UserHandle(mContext.getUserId())); permission.setGranted(true); + mPackageManager.grantRuntimePermission(mPackageInfo.packageName, + permission.getName(), new UserHandle(mContext.getUserId())); + } + + // Update the permission flags. + if (!fixedByTheUser) { + // Now the apps can ask for the permission as the user + // no longer has it fixed in a denied state. + if (permission.isUserFixed() || !permission.isUserSet()) { + permission.setUserFixed(false); + permission.setUserSet(true); + mPackageManager.updatePermissionFlags(permission.getName(), + mPackageInfo.packageName, + PackageManager.FLAG_PERMISSION_USER_FIXED + | PackageManager.FLAG_PERMISSION_USER_SET, + PackageManager.FLAG_PERMISSION_USER_SET, + mUserHandle); + } + } + + // Enable the permission app op. + if (permission.hasAppOp() && !permission.isAppOpAllowed()) { + permission.setAppOpAllowed(true); + mAppOps.setMode(permission.getAppOp(), android.os.Process.myUid(), + mPackageInfo.packageName, AppOpsManager.MODE_ALLOWED); } } else { // Legacy apps cannot have a not granted permission but just in case. // Also if the permissions has no corresponding app op, then it is a // third-party one and we do not offer toggling of such permissions. - if (!permission.isGranted() || permission.getAppOp() == AppOpsManager.OP_NONE) { + if (!permission.isGranted() || !permission.hasAppOp()) { continue; } if (!permission.isAppOpAllowed()) { + permission.setAppOpAllowed(true); // It this is a shared user we want to enable the app op for all // packages in the shared user to match the behavior of this // shared user having a runtime permission. if (isSharedUser) { - String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); + // Enable the app op. + String[] packageNames = mPackageManager.getPackagesForUid(uid); for (String packageName : packageNames) { mAppOps.setMode(permission.getAppOp(), uid, packageName, AppOpsManager.MODE_ALLOWED); } } else { + // Enable the app op. mAppOps.setMode(permission.getAppOp(), uid, mPackageInfo.packageName, AppOpsManager.MODE_ALLOWED); } + // Mark that the permission should not be be granted on upgrade + // when the app begins supporting runtime permissions. + if (permission.shouldRevokeOnUpgrade()) { + permission.setRevokeOnUpgrade(false); + mPackageManager.updatePermissionFlags(permission.getName(), + mPackageInfo.packageName, + PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, + 0, mUserHandle); + } + // Legacy apps do not know that they have to retry access to a // resource due to changes in runtime permissions (app ops in this // case). Therefore, we restart them on app op change, so they // can pick up the change. mActivityManager.killUid(uid, KILL_REASON_APP_OP_CHANGE); - - permission.setAppOpAllowed(true); } } } @@ -263,7 +298,7 @@ public final class PermissionGroup implements Comparable<PermissionGroup> { return true; } - public boolean revokeRuntimePermissions() { + public boolean revokeRuntimePermissions(boolean fixedByTheUser) { final boolean isSharedUser = mPackageInfo.sharedUserId != null; final int uid = mPackageInfo.applicationInfo.uid; @@ -272,40 +307,85 @@ public final class PermissionGroup implements Comparable<PermissionGroup> { // to the permission if the permission is granted to the app. for (Permission permission : mPermissions.values()) { if (mAppSupportsRuntimePermissions) { + // Revoke the permission if needed. if (permission.isGranted()) { - mContext.getPackageManager().revokePermission(mPackageInfo.packageName, - permission.getName(), new UserHandle(mContext.getUserId())); permission.setGranted(false); + mPackageManager.revokeRuntimePermission(mPackageInfo.packageName, + permission.getName(), mUserHandle); + } + + // Update the permission flags. + if (fixedByTheUser) { + // Take a note that the user fixed the permission. + if (permission.isUserSet() || !permission.isUserFixed()) { + permission.setUserSet(false); + permission.setUserFixed(true); + mPackageManager.updatePermissionFlags(permission.getName(), + mPackageInfo.packageName, + PackageManager.FLAG_PERMISSION_USER_SET + | PackageManager.FLAG_PERMISSION_USER_FIXED, + PackageManager.FLAG_PERMISSION_USER_FIXED, + mUserHandle); + } + } else { + if (!permission.isUserSet()) { + permission.setUserSet(true); + // Take a note that the user already chose once. + mPackageManager.updatePermissionFlags(permission.getName(), + mPackageInfo.packageName, + PackageManager.FLAG_PERMISSION_USER_SET, + PackageManager.FLAG_PERMISSION_USER_SET, + mUserHandle); + } + } + + // Disable the permission app op. + if (permission.hasAppOp() && permission.isAppOpAllowed()) { + permission.setAppOpAllowed(false); + mAppOps.setMode(permission.getAppOp(), android.os.Process.myUid(), + mPackageInfo.packageName, AppOpsManager.MODE_IGNORED); } } else { // Legacy apps cannot have a non-granted permission but just in case. // Also if the permission has no corresponding app op, then it is a // third-party one and we do not offer toggling of such permissions. - if (!permission.isGranted() || permission.getAppOp() == AppOpsManager.OP_NONE) { + if (!permission.isGranted() || !permission.hasAppOp()) { continue; } if (permission.isAppOpAllowed()) { + permission.setAppOpAllowed(false); // It this is a shared user we want to enable the app op for all // packages the the shared user to match the behavior of this // shared user having a runtime permission. if (isSharedUser) { - String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); + String[] packageNames = mPackageManager.getPackagesForUid(uid); for (String packageName : packageNames) { + // Disable the app op. mAppOps.setMode(permission.getAppOp(), uid, packageName, AppOpsManager.MODE_IGNORED); } } else { + // Disable the app op. mAppOps.setMode(permission.getAppOp(), uid, mPackageInfo.packageName, AppOpsManager.MODE_IGNORED); } + // Mark that the permission should not be granted on upgrade + // when the app begins supporting runtime permissions. + if (!permission.shouldRevokeOnUpgrade()) { + permission.setRevokeOnUpgrade(true); + mPackageManager.updatePermissionFlags(permission.getName(), + mPackageInfo.packageName, + PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, + PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, + mUserHandle); + } + // Disabling an app op may put the app in a situation in which it // has a handle to state it shouldn't have, so we have to kill the // app. This matches the revoke runtime permission behavior. mActivityManager.killUid(uid, KILL_REASON_APP_OP_CHANGE); - - permission.setAppOpAllowed(false); } } } @@ -317,6 +397,39 @@ public final class PermissionGroup implements Comparable<PermissionGroup> { return new ArrayList<>(mPermissions.values()); } + public boolean isUserFixed() { + final int permissionCount = mPermissions.size(); + for (int i = 0; i < permissionCount; i++) { + Permission permission = mPermissions.valueAt(i); + if (!permission.isUserFixed()) { + return false; + } + } + return true; + } + + public boolean isPolicyFixed() { + final int permissionCount = mPermissions.size(); + for (int i = 0; i < permissionCount; i++) { + Permission permission = mPermissions.valueAt(i); + if (permission.isPolicyFixed()) { + return true; + } + } + return false; + } + + public boolean isUserSet() { + final int permissionCount = mPermissions.size(); + for (int i = 0; i < permissionCount; i++) { + Permission permission = mPermissions.valueAt(i); + if (!permission.isUserSet()) { + return false; + } + } + return true; + } + @Override public int compareTo(PermissionGroup another) { final int result = mLabel.toString().compareTo(another.mLabel.toString()); |