Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 27c52fca authored by Martijn Coenen's avatar Martijn Coenen
Browse files

Don't kill for REQUEST_INSTALL_PACKAGES on default/error mode

transition.

When handling unknown sources, PackageManager transitions from
MODE_DEFAULT to MODE_ERRORED, causing us to kill the app before the user
has even decided whether to allow external sources or not.

Since MODE_DEFAULT and MODE_ERRORED are the same from a storage point of
view, ignore transitions between the two.

This required some AppOps changes to store the previous mode and pass it
in.

Bug: 162849988
Test: run Epic installer
Change-Id: Ic866216f877e9b727fe70556f66dd998966fe0a2
Merged-In: Ic866216f877e9b727fe70556f66dd998966fe0a2
parent c4f4369f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
+8 −3
Original line number Diff line number Diff line
@@ -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
                            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) {
+28 −16
Original line number Diff line number Diff line
@@ -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);
            }
        }
    }