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

Commit 76d19db2 authored by JW Wang's avatar JW Wang Committed by Android (Google) Code Review
Browse files

Merge changes Ie95789c9,I3d800491,I31f6b981,Ia3a4116b,I7edd3cf7

* changes:
  Rewrite handling of failed sessions (2/n)
  Rewrite the broadcast receiver for ACTION_CANCEL_ENABLE_ROLLBACK (1/n)
  Remove #mNewRollbacks (10/n)
  Put rollbacks into #mRollbacks (9/n)
  Add a flag to facilitate merging 2 rollback collections (8/n)
parents cbeeff9e 1ac3d118
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -216,6 +216,10 @@ public final class RollbackManager {
     * across device reboot, by simulating what happens on reboot without
     * actually rebooting the device.
     *
     * Note rollbacks in the process of enabling will be lost after calling
     * this method since they are not persisted yet. Don't call this method
     * in the middle of the install process.
     *
     * @throws SecurityException if the caller does not have appropriate permissions.
     *
     * @hide
+21 −0
Original line number Diff line number Diff line
@@ -181,6 +181,15 @@ class Rollback {
    @GuardedBy("mLock")
    private int mNumPackageSessionsWithSuccess;

    /**
     * A temp flag to facilitate merging of the 2 rollback collections managed by
     * RollbackManagerServiceImpl. True if this rollback is in the process of enabling and was
     * originally managed by RollbackManagerServiceImpl#mNewRollbacks.
     * TODO: remove this flag when merge is completed.
     */
    @GuardedBy("mLock")
    private boolean mIsNewRollback = false;

    /**
     * Constructs a new, empty Rollback instance.
     *
@@ -829,6 +838,18 @@ class Rollback {
        }
    }

    void setIsNewRollback(boolean newRollback) {
        synchronized (mLock) {
            mIsNewRollback = newRollback;
        }
    }

    boolean isNewRollback() {
        synchronized (mLock) {
            return mIsNewRollback;
        }
    }

    static String rollbackStateToString(@RollbackState int state) {
        switch (state) {
            case Rollback.ROLLBACK_STATE_ENABLING: return "enabling";
+42 −62
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.rollback;
import android.Manifest;
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.AppOpsManager;
@@ -50,7 +51,6 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.DeviceConfig;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.Log;
import android.util.LongArrayQueue;
@@ -121,10 +121,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
    @GuardedBy("mLock")
    private final SparseBooleanArray mAllocatedRollbackIds = new SparseBooleanArray();

    // Rollbacks we are in the process of enabling.
    @GuardedBy("mLock")
    private final Set<Rollback> mNewRollbacks = new ArraySet<>();

    // The list of all rollbacks, including available and committed rollbacks.
    @GuardedBy("mLock")
    private final List<Rollback> mRollbacks;
@@ -240,17 +236,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
                        Slog.v(TAG, "broadcast=ACTION_CANCEL_ENABLE_ROLLBACK token=" + token);
                    }
                    synchronized (mLock) {
                        Rollback found = null;
                        for (Rollback newRollback : mNewRollbacks) {
                            if (newRollback.hasToken(token)) {
                                found = newRollback;
                        for (int i = 0; i < mRollbacks.size(); ++i) {
                            Rollback rollback = mRollbacks.get(i);
                            if (rollback.hasToken(token) && rollback.isEnabling()) {
                                mRollbacks.remove(i);
                                rollback.delete(mAppDataRollbackHelper);
                                break;
                            }
                        }
                        if (found != null) {
                            mNewRollbacks.remove(found);
                            found.delete(mAppDataRollbackHelper);
                        }
                    }
                }
            }
@@ -442,15 +435,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
                    rollback.delete(mAppDataRollbackHelper);
                }
            }
            Iterator<Rollback> iter2 = mNewRollbacks.iterator();
            while (iter2.hasNext()) {
                Rollback newRollback = iter2.next();
                if (newRollback.includesPackage(packageName)) {
                    iter2.remove();
                    newRollback.delete(mAppDataRollbackHelper);
                }

            }
        }
    }

@@ -810,7 +794,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
            newRollback = getNewRollbackForPackageSessionLocked(packageSession.getSessionId());
            if (newRollback == null) {
                newRollback = createNewRollbackLocked(parentSession);
                mNewRollbacks.add(newRollback);
                mRollbacks.add(newRollback);
                newRollback.setIsNewRollback(true);
            }
        }
        newRollback.addToken(token);
@@ -818,34 +803,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        return enableRollbackForPackageSession(newRollback, packageSession);
    }

    @WorkerThread
    private void removeRollbackForPackageSessionId(int sessionId) {
        if (LOCAL_LOGV) {
            Slog.v(TAG, "removeRollbackForPackageSessionId=" + sessionId);
        }

        synchronized (mLock) {
            Rollback newRollback = getNewRollbackForPackageSessionLocked(sessionId);
            if (newRollback != null) {
                Slog.w(TAG, "Delete new rollback id=" + newRollback.info.getRollbackId()
                        + " for session id=" + sessionId);
                mNewRollbacks.remove(newRollback);
                newRollback.delete(mAppDataRollbackHelper);
            }
            Iterator<Rollback> iter = mRollbacks.iterator();
            while (iter.hasNext()) {
                Rollback rollback = iter.next();
                if (rollback.getStagedSessionId() == sessionId) {
                    Slog.w(TAG, "Delete rollback id=" + rollback.info.getRollbackId()
                            + " for session id=" + sessionId);
                    iter.remove();
                    rollback.delete(mAppDataRollbackHelper);
                    break;
                }
            }
        }
    }

    /**
     * Do code and userdata backups to enable rollback of the given session.
     * In case of multiPackage sessions, <code>session</code> should be one of
@@ -966,15 +923,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
                    + " users=" + Arrays.toString(userIds));
        }
        synchronized (mLock) {
            // staged installs
            for (int i = 0; i < mRollbacks.size(); i++) {
                Rollback rollback = mRollbacks.get(i);
                rollback.snapshotUserData(packageName, userIds, mAppDataRollbackHelper);
            }
            // non-staged installs
            for (Rollback rollback : mNewRollbacks) {
                rollback.snapshotUserData(packageName, userIds, mAppDataRollbackHelper);
            }
        }
    }

@@ -1200,7 +1152,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
                synchronized (mLock) {
                    newRollback = getNewRollbackForPackageSessionLocked(sessionId);
                    if (newRollback != null && newRollback.notifySessionWithSuccess()) {
                        mNewRollbacks.remove(newRollback);
                        mRollbacks.remove(newRollback);
                        newRollback.setIsNewRollback(false);
                    } else {
                        // Not all child sessions finished with success.
                        // Don't enable the rollback yet.
@@ -1215,7 +1168,15 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
                    }
                }
            } else {
                removeRollbackForPackageSessionId(sessionId);
                synchronized (mLock) {
                    Rollback rollback = getRollbackForSessionLocked(sessionId);
                    if (rollback != null && rollback.isEnabling()) {
                        Slog.w(TAG, "Delete rollback id=" + rollback.info.getRollbackId()
                                + " for failed session id=" + sessionId);
                        mRollbacks.remove(rollback);
                        rollback.delete(mAppDataRollbackHelper);
                    }
                }
            }
        }
    }
@@ -1375,6 +1336,25 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        return rollback;
    }

    /**
     * Returns the Rollback associated with the given session if parent or child session id matches.
     * Returns null if not found.
     */
    @WorkerThread
    @GuardedBy("mLock")
    @Nullable
    private Rollback getRollbackForSessionLocked(int sessionId) {
        // We expect mRollbacks to be a very small list; linear search should be plenty fast.
        for (int i = 0; i < mRollbacks.size(); ++i) {
            Rollback rollback = mRollbacks.get(i);
            if (rollback.getStagedSessionId() == sessionId
                    || rollback.containsSessionId(sessionId)) {
                return rollback;
            }
        }
        return null;
    }

    /**
     * Returns the NewRollback associated with the given package session.
     * Returns null if no NewRollback is found for the given package
@@ -1383,11 +1363,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
    @WorkerThread
    @GuardedBy("mLock")
    Rollback getNewRollbackForPackageSessionLocked(int packageSessionId) {
        // We expect mNewRollbacks to be a very small list; linear search
        // We expect mRollbacks to be a very small list; linear search
        // should be plenty fast.
        for (Rollback newRollback: mNewRollbacks) {
            if (newRollback.containsSessionId(packageSessionId)) {
                return newRollback;
        for (Rollback rollback: mRollbacks) {
            if (rollback.isNewRollback() && rollback.containsSessionId(packageSessionId)) {
                return rollback;
            }
        }
        return null;