diff options
3 files changed, 37 insertions, 20 deletions
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java index e05991b33796..a79a1cfcd64f 100644 --- a/core/java/android/os/storage/StorageManagerInternal.java +++ b/core/java/android/os/storage/StorageManagerInternal.java @@ -118,7 +118,7 @@ public abstract class StorageManagerInternal { * affects them. */ public abstract void onAppOpsChanged(int code, int uid, - @Nullable String packageName, int mode); + @Nullable String packageName, int mode, int previousMode); /** * Asks the StorageManager to reset all state for the provided user; this will result diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 678387c540ed..391923324d0c 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -4745,15 +4745,20 @@ class StorageManagerService extends IStorageManager.Stub } } - public void onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode) { + public void onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode, + int previousMode) { final long token = Binder.clearCallingIdentity(); try { if (mIsFuseEnabled) { // When using FUSE, we may need to kill the app if the op changes switch(code) { case OP_REQUEST_INSTALL_PACKAGES: - // Always kill regardless of op change, to remount apps /storage - killAppForOpChange(code, uid); + if (previousMode == MODE_ALLOWED || mode == MODE_ALLOWED) { + // If we transition to/from MODE_ALLOWED, kill the app to make + // sure it has the correct view of /storage. Changing between + // MODE_DEFAULT / MODE_ERRORED is a no-op + killAppForOpChange(code, uid); + } return; case OP_MANAGE_EXTERNAL_STORAGE: if (mode != MODE_ALLOWED) { diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index c5bdb9edd069..600069335dbc 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -2198,6 +2198,7 @@ public class AppOpsService extends IAppOpsService.Stub { updatePermissionRevokedCompat(uid, code, mode); } + int previousMode; synchronized (this) { final int defaultMode = AppOpsManager.opToDefaultMode(code); @@ -2206,12 +2207,14 @@ public class AppOpsService extends IAppOpsService.Stub { if (mode == defaultMode) { return; } + previousMode = AppOpsManager.MODE_DEFAULT; uidState = new UidState(uid); uidState.opModes = new SparseIntArray(); uidState.opModes.put(code, mode); mUidStates.put(uid, uidState); scheduleWriteLocked(); } else if (uidState.opModes == null) { + previousMode = AppOpsManager.MODE_DEFAULT; if (mode != defaultMode) { uidState.opModes = new SparseIntArray(); uidState.opModes.put(code, mode); @@ -2221,6 +2224,7 @@ public class AppOpsService extends IAppOpsService.Stub { if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) { return; } + previousMode = uidState.opModes.get(code); if (mode == defaultMode) { uidState.opModes.delete(code); if (uidState.opModes.size() <= 0) { @@ -2235,7 +2239,7 @@ public class AppOpsService extends IAppOpsService.Stub { } notifyOpChangedForAllPkgsInUid(code, uid, false, permissionPolicyCallback); - notifyOpChangedSync(code, uid, null, mode); + notifyOpChangedSync(code, uid, null, mode, previousMode); } /** @@ -2414,11 +2418,12 @@ public class AppOpsService extends IAppOpsService.Stub { } } - private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode) { + private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode, + int previousMode) { final StorageManagerInternal storageManagerInternal = LocalServices.getService(StorageManagerInternal.class); if (storageManagerInternal != null) { - storageManagerInternal.onAppOpsChanged(code, uid, packageName, mode); + storageManagerInternal.onAppOpsChanged(code, uid, packageName, mode, previousMode); } } @@ -2450,11 +2455,13 @@ public class AppOpsService extends IAppOpsService.Stub { return; } + int previousMode = AppOpsManager.MODE_DEFAULT; synchronized (this) { UidState uidState = getUidStateLocked(uid, false); Op op = getOpLocked(code, uid, packageName, null, bypass, true); if (op != null) { if (op.mode != mode) { + previousMode = op.mode; op.mode = mode; if (uidState != null) { uidState.evalForegroundOps(mOpModeWatchers); @@ -2491,7 +2498,7 @@ public class AppOpsService extends IAppOpsService.Stub { this, repCbs, code, uid, packageName)); } - notifyOpChangedSync(code, uid, packageName, mode); + notifyOpChangedSync(code, uid, packageName, mode, previousMode); } private void notifyOpChanged(ArraySet<ModeCallback> callbacks, int code, @@ -2534,7 +2541,7 @@ public class AppOpsService extends IAppOpsService.Stub { } private static ArrayList<ChangeRec> addChange(ArrayList<ChangeRec> reports, - int op, int uid, String packageName) { + int op, int uid, String packageName, int previousMode) { boolean duplicate = false; if (reports == null) { reports = new ArrayList<>(); @@ -2549,7 +2556,7 @@ public class AppOpsService extends IAppOpsService.Stub { } } if (!duplicate) { - reports.add(new ChangeRec(op, uid, packageName)); + reports.add(new ChangeRec(op, uid, packageName, previousMode)); } return reports; @@ -2557,7 +2564,7 @@ public class AppOpsService extends IAppOpsService.Stub { private static HashMap<ModeCallback, ArrayList<ChangeRec>> addCallbacks( HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks, - int op, int uid, String packageName, ArraySet<ModeCallback> cbs) { + int op, int uid, String packageName, int previousMode, ArraySet<ModeCallback> cbs) { if (cbs == null) { return callbacks; } @@ -2568,7 +2575,7 @@ public class AppOpsService extends IAppOpsService.Stub { for (int i=0; i<N; i++) { ModeCallback cb = cbs.valueAt(i); ArrayList<ChangeRec> reports = callbacks.get(cb); - ArrayList<ChangeRec> changed = addChange(reports, op, uid, packageName); + ArrayList<ChangeRec> changed = addChange(reports, op, uid, packageName, previousMode); if (changed != reports) { callbacks.put(cb, changed); } @@ -2580,11 +2587,13 @@ public class AppOpsService extends IAppOpsService.Stub { final int op; final int uid; final String pkg; + final int previous_mode; - ChangeRec(int _op, int _uid, String _pkg) { + ChangeRec(int _op, int _uid, String _pkg, int _previous_mode) { op = _op; uid = _uid; pkg = _pkg; + previous_mode = _previous_mode; } } @@ -2620,18 +2629,19 @@ public class AppOpsService extends IAppOpsService.Stub { for (int j = uidOpCount - 1; j >= 0; j--) { final int code = opModes.keyAt(j); if (AppOpsManager.opAllowsReset(code)) { + int previousMode = opModes.valueAt(j); opModes.removeAt(j); if (opModes.size() <= 0) { uidState.opModes = null; } for (String packageName : getPackagesForUid(uidState.uid)) { callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, - mOpModeWatchers.get(code)); + previousMode, mOpModeWatchers.get(code)); callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, - mPackageModeWatchers.get(packageName)); + previousMode, mPackageModeWatchers.get(packageName)); allChanges = addChange(allChanges, code, uidState.uid, - packageName); + packageName, previousMode); } } } @@ -2662,16 +2672,18 @@ public class AppOpsService extends IAppOpsService.Stub { Op curOp = pkgOps.valueAt(j); if (AppOpsManager.opAllowsReset(curOp.op) && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) { + int previousMode = curOp.mode; curOp.mode = AppOpsManager.opToDefaultMode(curOp.op); changed = true; uidChanged = true; final int uid = curOp.uidState.uid; callbacks = addCallbacks(callbacks, curOp.op, uid, packageName, - mOpModeWatchers.get(curOp.op)); + previousMode, mOpModeWatchers.get(curOp.op)); callbacks = addCallbacks(callbacks, curOp.op, uid, packageName, - mPackageModeWatchers.get(packageName)); + previousMode, mPackageModeWatchers.get(packageName)); - allChanges = addChange(allChanges, curOp.op, uid, packageName); + allChanges = addChange(allChanges, curOp.op, uid, packageName, + previousMode); curOp.removeAttributionsWithNoTime(); if (curOp.mAttributions.isEmpty()) { pkgOps.removeAt(j); @@ -2712,7 +2724,7 @@ public class AppOpsService extends IAppOpsService.Stub { for (int i = 0; i < numChanges; i++) { ChangeRec change = allChanges.get(i); notifyOpChangedSync(change.op, change.uid, change.pkg, - AppOpsManager.opToDefaultMode(change.op)); + AppOpsManager.opToDefaultMode(change.op), change.previous_mode); } } } |