diff options
author | 2019-01-28 17:04:24 +0000 | |
---|---|---|
committer | 2019-01-28 17:04:24 +0000 | |
commit | 87969723fc13cd69784fffb7ed3e8f8f6eed1a14 (patch) | |
tree | e8082558950c70d5e51cd89adfd527ee5c30566c | |
parent | 94f1dbb4474781f5522f9602b02c08722f4c1012 (diff) | |
parent | dde07852280b8ea2ae40d366816aae11f194d2bd (diff) |
Merge "Reset per-pkg app-ops for runtime permissions"
4 files changed, 123 insertions, 3 deletions
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java index b5560331e7aa..da45054cbe51 100644 --- a/core/java/android/app/AppOpsManagerInternal.java +++ b/core/java/android/app/AppOpsManagerInternal.java @@ -78,7 +78,7 @@ public abstract class AppOpsManagerInternal { /** * Sets the app-ops mode for a certain app-op and uid. * - * <p>Similar as {@link AppOpsManager#setMode} but does not require the package manager to be + * <p>Similar as {@link AppOpsManager#setUidMode} but does not require the package manager to be * working. Hence this can be used very early during boot. * * <p>Only for internal callers. Does <u>not</u> verify that package name belongs to uid. @@ -88,4 +88,12 @@ public abstract class AppOpsManagerInternal { * @param mode The new mode to set. */ public abstract void setUidMode(int code, int uid, int mode); + + /** + * Set all {@link #setMode (package) modes} for this uid to the default value. + * + * @param code The app-op + * @param uid The uid + */ + public abstract void setAllPkgModesToDefault(int code, int uid); } diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 7ede6dcd41bd..26d2d17fec7d 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -16,8 +16,8 @@ package com.android.server.appop; -import static android.app.AppOpsManager.OP_PLAY_AUDIO; import static android.app.AppOpsManager.OP_NONE; +import static android.app.AppOpsManager.OP_PLAY_AUDIO; import static android.app.AppOpsManager.UID_STATE_BACKGROUND; import static android.app.AppOpsManager.UID_STATE_CACHED; import static android.app.AppOpsManager.UID_STATE_FOREGROUND; @@ -94,9 +94,9 @@ import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.internal.util.function.pooled.PooledLambda; - import com.android.server.LocalServices; import com.android.server.LockGuard; + import libcore.util.EmptyArray; import org.xmlpull.v1.XmlPullParser; @@ -1282,6 +1282,46 @@ public class AppOpsService extends IAppOpsService.Stub { } } + /** + * Set all {@link #setMode (package) modes} for this uid to the default value. + * + * @param code The app-op + * @param uid The uid + */ + private void setAllPkgModesToDefault(int code, int uid) { + synchronized (this) { + UidState uidState = getUidStateLocked(uid, false); + if (uidState == null) { + return; + } + + ArrayMap<String, Ops> pkgOps = uidState.pkgOps; + if (pkgOps == null) { + return; + } + + int numPkgs = pkgOps.size(); + for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) { + Ops ops = pkgOps.valueAt(pkgNum); + + Op op = ops.get(code); + if (op == null) { + continue; + } + + int defaultMode = AppOpsManager.opToDefaultMode(code); + if (op.mode != defaultMode) { + Slog.w(TAG, "resetting app-op mode for " + AppOpsManager.opToName(code) + " of " + + pkgOps.keyAt(pkgNum)); + + op.mode = defaultMode; + + scheduleWriteLocked(); + } + } + } + } + @Override public void setMode(int code, int uid, String packageName, int mode) { setMode(code, uid, packageName, mode, true, false); @@ -4387,5 +4427,10 @@ public class AppOpsService extends IAppOpsService.Stub { public void setUidMode(int code, int uid, int mode) { AppOpsService.this.setUidMode(code, uid, mode); } + + @Override + public void setAllPkgModesToDefault(int code, int uid) { + AppOpsService.this.setAllPkgModesToDefault(code, uid); + } } } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 30b5e49bc3fd..3c89d7801852 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -1049,6 +1049,8 @@ public class PermissionManagerService { updatedUserIds); updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions, permissionsState, pkg, updatedUserIds); + + setAppOpsLocked(permissionsState, pkg); } // Persist the runtime permissions state for users with changes. If permissions @@ -1387,6 +1389,60 @@ public class PermissionManagerService { return updatedUserIds; } + /** + * Fix app-op modes for runtime permissions. + * + * @param permsState The state of the permissions of the package + * @param pkg The package information + */ + private void setAppOpsLocked(@NonNull PermissionsState permsState, + @NonNull PackageParser.Package pkg) { + for (int userId : UserManagerService.getInstance().getUserIds()) { + int numPerms = pkg.requestedPermissions.size(); + for (int i = 0; i < numPerms; i++) { + String permission = pkg.requestedPermissions.get(i); + + int op = permissionToOpCode(permission); + if (op == OP_NONE) { + continue; + } + + // Runtime permissions are per uid, not per package, hence per package app-op + // modes should never have been set. It is possible to set them via the shell + // though. Revert such settings during boot to get the device back into a good + // state. + LocalServices.getService(AppOpsManagerInternal.class).setAllPkgModesToDefault( + op, getUid(userId, getAppId(pkg.applicationInfo.uid))); + + // For pre-M apps the runtime permission do not store the state + if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { + continue; + } + + PermissionState state = permsState.getRuntimePermissionState(permission, userId); + if (state == null) { + continue; + } + + // Adjust app-op mods for foreground/background permissions. If an package used to + // have both fg and bg permission granted and it lost the bg permission during an + // upgrade the app-op mode should get downgraded to foreground. + if (state.isGranted()) { + BasePermission bp = mSettings.getPermission(permission); + + if (bp != null && bp.perm != null && bp.perm.info != null + && bp.perm.info.backgroundPermission != null) { + PermissionState bgState = permsState.getRuntimePermissionState( + bp.perm.info.backgroundPermission, userId); + + setAppOpMode(permission, pkg, userId, bgState != null && bgState.isGranted() + ? MODE_ALLOWED : MODE_FOREGROUND); + } + } + } + } + } + private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) { boolean allowed = false; final int NP = PackageParser.NEW_PERMISSIONS.length; diff --git a/services/core/java/com/android/server/pm/permission/TEST_MAPPING b/services/core/java/com/android/server/pm/permission/TEST_MAPPING index 076c94c994a5..09bacd6ed332 100644 --- a/services/core/java/com/android/server/pm/permission/TEST_MAPPING +++ b/services/core/java/com/android/server/pm/permission/TEST_MAPPING @@ -7,6 +7,17 @@ "include-filter": "com.google.android.permission.gts.DefaultPermissionGrantPolicyTest" } ] + }, + { + "name": "CtsPermissionTestCases", + "options": [ + { + "include-filter": "android.permission.cts.BackgroundPermissionsTest" + }, + { + "include-filter": "android.permission.cts.SplitPermissionTest" + } + ] } ] }
\ No newline at end of file |