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

Commit 19e08edb authored by Oli Lan's avatar Oli Lan Committed by Android (Google) Code Review
Browse files

Merge "Move Rollback synchronisation into the Rollback class."

parents cf45fe7a 4af2f750
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ public class AppDataRollbackHelper {
     * {@code userIds}. Updates said {@code packageRollbackInfo} with the inodes of the CE user data
     * snapshot folders.
     */
    @GuardedBy("rollback.getLock")
    @GuardedBy("rollback.mLock")
    // TODO(b/136241838): Move into Rollback and synchronize there.
    public void snapshotAppData(
            int snapshotId, PackageRollbackInfo packageRollbackInfo, int[] userIds) {
@@ -88,7 +88,7 @@ public class AppDataRollbackHelper {
     *         to {@code packageRollbackInfo} are restricted to the removal or addition of {@code
     *         userId} to the list of pending backups or restores.
     */
    @GuardedBy("rollback.getLock")
    @GuardedBy("rollback.mLock")
    // TODO(b/136241838): Move into Rollback and synchronize there.
    public boolean restoreAppData(int rollbackId, PackageRollbackInfo packageRollbackInfo,
            int userId, int appId, String seInfo) {
@@ -133,7 +133,7 @@ public class AppDataRollbackHelper {
     * Deletes an app data snapshot with a given {@code rollbackId} for a specified package
     * {@code packageName} for a given {@code user}.
     */
    @GuardedBy("rollback.getLock")
    @GuardedBy("rollback.mLock")
    // TODO(b/136241838): Move into Rollback and synchronize there.
    public void destroyAppDataSnapshot(int rollbackId, PackageRollbackInfo packageRollbackInfo,
            int user) {
@@ -162,7 +162,7 @@ public class AppDataRollbackHelper {
     *
     * @return true if any backups or restores were found for the userId
     */
    @GuardedBy("rollback.getLock")
    @GuardedBy("rollback.mLock")
    boolean commitPendingBackupAndRestoreForUser(int userId, Rollback rollback) {
        boolean foundBackupOrRestore = false;
        for (PackageRollbackInfo info : rollback.info.getPackages()) {
+302 −245
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.util.SparseLongArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;

import java.io.File;
import java.io.IOException;
@@ -53,11 +54,6 @@ import java.util.List;

/**
 * Information about a rollback available for a set of atomically installed packages.
 *
 * <p>When accessing the state of a Rollback object, the caller is responsible for synchronization.
 * The lock object provided by {@link #getLock} should be acquired when accessing any of the mutable
 * state of a Rollback, including from the {@link RollbackInfo} and any of the
 * {@link PackageRollbackInfo} objects held within.
 */
class Rollback {

@@ -101,11 +97,7 @@ class Rollback {

    /**
     * The rollback info for this rollback.
     *
     * <p>Any access to this field that touches any mutable state should be synchronized on
     * {@link #getLock}.
     */
    @GuardedBy("getLock")
    public final RollbackInfo info;

    /**
@@ -146,8 +138,6 @@ class Rollback {

    /**
     * Lock object to guard all access to Rollback state.
     *
     * @see #getLock
     */
    private final Object mLock = new Object();

@@ -184,24 +174,9 @@ class Rollback {
        mRestoreUserDataInProgress = restoreUserDataInProgress;
    }

    /**
     * Returns a lock object that should be acquired before accessing any Rollback state from
     * {@link RollbackManagerServiceImpl}.
     *
     * <p>Note that while holding this lock, the lock for {@link RollbackManagerServiceImpl} should
     * not be acquired (but it is ok to acquire this lock while already holding the lock for that
     * class).
     */
    // TODO(b/136241838): Move rollback functionality into this class and synchronize on the lock
    // internally. Remove this method once this has been done for all cases.
    Object getLock() {
        return mLock;
    }

    /**
     * Whether the rollback is for rollback of a staged install.
     */
    @GuardedBy("getLock")
    boolean isStaged() {
        return info.isStaged();
    }
@@ -216,17 +191,20 @@ class Rollback {
    /**
     * Returns the time when the upgrade occurred, for purposes of expiring rollback data.
     */
    @GuardedBy("getLock")
    Instant getTimestamp() {
        synchronized (mLock) {
            return mTimestamp;
        }
    }

    /**
     * Sets the time at which upgrade occurred.
     */
    @GuardedBy("getLock")
    void setTimestamp(Instant timestamp) {
        synchronized (mLock) {
            mTimestamp = timestamp;
            RollbackStore.saveRollback(this);
        }
    }

    /**
@@ -240,41 +218,53 @@ class Rollback {
    /**
     * Returns true if the rollback is in the ENABLING state.
     */
    @GuardedBy("getLock")
    boolean isEnabling() {
        synchronized (mLock) {
            return mState == ROLLBACK_STATE_ENABLING;
        }
    }

    /**
     * Returns true if the rollback is in the AVAILABLE state.
     */
    @GuardedBy("getLock")
    boolean isAvailable() {
        synchronized (mLock) {
            return mState == ROLLBACK_STATE_AVAILABLE;
        }
    }

    /**
     * Returns true if the rollback is in the COMMITTED state.
     */
    @GuardedBy("getLock")
    boolean isCommitted() {
        synchronized (mLock) {
            return mState == ROLLBACK_STATE_COMMITTED;
        }
    }

    /**
     * Returns true if the rollback is in the DELETED state.
     */
    @GuardedBy("getLock")
    boolean isDeleted() {
        synchronized (mLock) {
            return mState == ROLLBACK_STATE_DELETED;
        }
    }

    /**
     * Saves this rollback to persistent storage.
     */
    void saveRollback() {
        synchronized (mLock) {
            RollbackStore.saveRollback(this);
        }
    }

    /**
     * Enables this rollback for the provided package.
     *
     * @return boolean True if the rollback was enabled successfully for the specified package.
     */
    @GuardedBy("getLock")
    boolean enableForPackage(String packageName, long newVersion, long installedVersion,
            boolean isApex, String sourceDir, String[] splitSourceDirs) {
        try {
@@ -295,7 +285,9 @@ class Rollback {
                new IntArray() /* pendingBackups */, new ArrayList<>() /* pendingRestores */,
                isApex, new IntArray(), new SparseLongArray() /* ceSnapshotInodes */);

        synchronized (mLock) {
            info.getPackages().add(packageRollbackInfo);
        }

        return true;
    }
@@ -304,8 +296,8 @@ class Rollback {
     * Snapshots user data for the provided package and user ids. Does nothing if this rollback is
     * not in the ENABLING state.
     */
    @GuardedBy("getLock")
    void snapshotUserData(String packageName, int[] userIds, AppDataRollbackHelper dataHelper) {
        synchronized (mLock) {
            if (!isEnabling()) {
                return;
            }
@@ -320,14 +312,28 @@ class Rollback {
                }
            }
        }
    }

    /**
     * Commits the pending backups and restores for a given {@code userId}. If this rollback has a
     * pending backup, it is updated with a mapping from {@code userId} to inode of the CE user data
     * snapshot.
     */
    void commitPendingBackupAndRestoreForUser(int userId, AppDataRollbackHelper dataHelper) {
        synchronized (mLock) {
            if (dataHelper.commitPendingBackupAndRestoreForUser(userId, this)) {
                RollbackStore.saveRollback(this);
            }
        }
    }

    /**
     * Changes the state of the rollback to AVAILABLE. This also changes the timestamp to the
     * current time and saves the rollback. Does nothing if this rollback is already in the
     * DELETED state.
     */
    @GuardedBy("getLock")
    void makeAvailable() {
        synchronized (mLock) {
            if (isDeleted()) {
                Slog.w(TAG, "Cannot make deleted rollback available.");
                return;
@@ -336,14 +342,14 @@ class Rollback {
            mTimestamp = Instant.now();
            RollbackStore.saveRollback(this);
        }
    }

    /**
     * Commits the rollback.
     */
    @GuardedBy("getLock")
    void commit(final Context context, List<VersionedPackage> causePackages,
            String callerPackageName, IntentSender statusReceiver) {

        synchronized (mLock) {
            if (!isAvailable()) {
                sendFailure(context, statusReceiver,
                        RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE,
@@ -430,8 +436,8 @@ class Rollback {
                                    PackageInstaller.STATUS_FAILURE);
                            if (status != PackageInstaller.STATUS_SUCCESS) {
                                // Committing the rollback failed, but we still have all the info we
                            // need to try rolling back again, so restore the rollback state to how
                            // it was before we tried committing.
                                // need to try rolling back again, so restore the rollback state to
                                // how it was before we tried committing.
                                // TODO: Should we just kill this rollback if commit failed?
                                // Why would we expect commit not to fail again?
                                // TODO: Could this cause a rollback to be resurrected
@@ -465,7 +471,8 @@ class Rollback {
                            try {
                                final Intent fillIn = new Intent();
                                fillIn.putExtra(
                                    RollbackManager.EXTRA_STATUS, RollbackManager.STATUS_SUCCESS);
                                        RollbackManager.EXTRA_STATUS,
                                        RollbackManager.STATUS_SUCCESS);
                                statusReceiver.sendIntent(context, 0, fillIn, null, null);
                            } catch (IntentSender.SendIntentException e) {
                                // Nowhere to send the result back to, so don't bother.
@@ -490,6 +497,7 @@ class Rollback {
                        "IOException: " + e.toString());
            }
        }
    }

    /**
     * Restores user data for the specified package if this rollback is currently marked as
@@ -498,9 +506,9 @@ class Rollback {
     * @return boolean True if this rollback has a restore in progress and contains the specified
     * package.
     */
    @GuardedBy("getLock")
    boolean restoreUserDataForPackageIfInProgress(String packageName, int[] userIds, int appId,
            String seInfo, AppDataRollbackHelper dataHelper) {
        synchronized (mLock) {
            if (!isRestoreUserDataInProgress()) {
                return false;
            }
@@ -523,12 +531,13 @@ class Rollback {
            }
            return foundPackage;
        }
    }

    /**
     * Deletes app data snapshots associated with this rollback, and moves to the DELETED state.
     */
    @GuardedBy("getLock")
    void delete(AppDataRollbackHelper dataHelper) {
        synchronized (mLock) {
            for (PackageRollbackInfo pkgInfo : info.getPackages()) {
                IntArray snapshottedUsers = pkgInfo.getSnapshottedUsers();
                for (int i = 0; i < snapshottedUsers.size(); i++) {
@@ -542,46 +551,53 @@ class Rollback {
            RollbackStore.deleteRollback(this);
            mState = ROLLBACK_STATE_DELETED;
        }
    }

    /**
     * Returns the id of the post-reboot apk session for a staged install, if any.
     */
    @GuardedBy("getLock")
    int getApkSessionId() {
        synchronized (mLock) {
            return mApkSessionId;
        }
    }

    /**
     * Sets the id of the post-reboot apk session for a staged install.
     */
    @GuardedBy("getLock")
    void setApkSessionId(int apkSessionId) {
        synchronized (mLock) {
            mApkSessionId = apkSessionId;
            RollbackStore.saveRollback(this);
        }
    }

    /**
     * Returns true if we are expecting the package manager to call restoreUserData for this
     * rollback because it has just been committed but the rollback has not yet been fully applied.
     */
    @GuardedBy("getLock")
    boolean isRestoreUserDataInProgress() {
        synchronized (mLock) {
            return mRestoreUserDataInProgress;
        }
    }

    /**
     * Sets whether we are expecting the package manager to call restoreUserData for this
     * rollback because it has just been committed but the rollback has not yet been fully applied.
     */
    @GuardedBy("getLock")
    void setRestoreUserDataInProgress(boolean restoreUserDataInProgress) {
        synchronized (mLock) {
            mRestoreUserDataInProgress = restoreUserDataInProgress;
            RollbackStore.saveRollback(this);
        }
    }

    /**
     * Returns true if this rollback includes the package with the provided {@code packageName}.
     */
    @GuardedBy("getLock")
    boolean includesPackage(String packageName) {
        synchronized (mLock) {
            for (PackageRollbackInfo packageRollbackInfo : info.getPackages()) {
                if (packageRollbackInfo.getPackageName().equals(packageName)) {
                    return true;
@@ -589,13 +605,14 @@ class Rollback {
            }
            return false;
        }
    }

    /**
     * Returns true if this rollback includes the package with the provided {@code packageName}
     * with a <i>version rolled back from</i> that is not {@code versionCode}.
     */
    @GuardedBy("getLock")
    boolean includesPackageWithDifferentVersion(String packageName, long versionCode) {
        synchronized (mLock) {
            for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) {
                if (pkgRollbackInfo.getPackageName().equals(packageName)
                        && pkgRollbackInfo.getVersionRolledBackFrom().getLongVersionCode()
@@ -605,24 +622,26 @@ class Rollback {
            }
            return false;
        }
    }

    /**
     * Returns a list containing the names of all the packages included in this rollback.
     */
    @GuardedBy("getLock")
    List<String> getPackageNames() {
        synchronized (mLock) {
            List<String> result = new ArrayList<>();
            for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) {
                result.add(pkgRollbackInfo.getPackageName());
            }
            return result;
        }
    }

    /**
     * Returns a list containing the names of all the apex packages included in this rollback.
     */
    @GuardedBy("getLock")
    List<String> getApexPackageNames() {
        synchronized (mLock) {
            List<String> result = new ArrayList<>();
            for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) {
                if (pkgRollbackInfo.isApex()) {
@@ -631,6 +650,13 @@ class Rollback {
            }
            return result;
        }
    }

    int getPackageCount() {
        synchronized (mLock) {
            return info.getPackages().size();
        }
    }

    static String rollbackStateToString(@RollbackState int state) {
        switch (state) {
@@ -651,8 +677,39 @@ class Rollback {
        throw new ParseException("Invalid rollback state: " + state, 0);
    }

    @GuardedBy("getLock")
    String getStateAsString() {
        synchronized (mLock) {
            return rollbackStateToString(mState);
        }
    }

    void dump(IndentingPrintWriter ipw) {
        synchronized (mLock) {
            ipw.println(info.getRollbackId() + ":");
            ipw.increaseIndent();
            ipw.println("-state: " + getStateAsString());
            ipw.println("-timestamp: " + getTimestamp());
            if (getStagedSessionId() != -1) {
                ipw.println("-stagedSessionId: " + getStagedSessionId());
            }
            ipw.println("-packages:");
            ipw.increaseIndent();
            for (PackageRollbackInfo pkg : info.getPackages()) {
                ipw.println(pkg.getPackageName()
                        + " " + pkg.getVersionRolledBackFrom().getLongVersionCode()
                        + " -> " + pkg.getVersionRolledBackTo().getLongVersionCode());
            }
            ipw.decreaseIndent();
            if (isCommitted()) {
                ipw.println("-causePackages:");
                ipw.increaseIndent();
                for (VersionedPackage cPkg : info.getCausePackages()) {
                    ipw.println(cPkg.getPackageName() + " " + cPkg.getLongVersionCode());
                }
                ipw.decreaseIndent();
                ipw.println("-committedSessionId: " + info.getCommittedSessionId());
            }
            ipw.decreaseIndent();
        }
    }
}
+154 −184

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -252,7 +252,7 @@ class RollbackStore {
    /**
     * Saves the given rollback to persistent storage.
     */
    @GuardedBy("rollback.getLock")
    @GuardedBy("rollback.mLock")
    static void saveRollback(Rollback rollback) {
        try {
            JSONObject dataJson = new JSONObject();