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

Commit d0d7a014 authored by Richard Uhler's avatar Richard Uhler Committed by android-build-merger
Browse files

Rename RollbackData to Rollback. am: 91fc4db1

am: b646e555

Change-Id: Ie5756dcc51eaded8d890e3b843e215022b68b495
parents ab81c07b b646e555
Loading
Loading
Loading
Loading
+38 −37
Original line number Diff line number Diff line
@@ -98,14 +98,14 @@ public class AppDataRollbackHelper {

        final IntArray pendingBackups = packageRollbackInfo.getPendingBackups();
        final List<RestoreInfo> pendingRestores = packageRollbackInfo.getPendingRestores();
        boolean changedRollbackData = false;
        boolean changedRollback = false;

        // If we still have a userdata backup pending for this user, it implies that the user
        // hasn't unlocked their device between the point of backup and the point of restore,
        // so the data cannot have changed. We simply skip restoring CE data in this case.
        if (pendingBackups != null && pendingBackups.indexOf(userId) != -1) {
            pendingBackups.remove(pendingBackups.indexOf(userId));
            changedRollbackData = true;
            changedRollback = true;
        } else {
            // There's no pending CE backup for this user, which means that we successfully
            // managed to backup data for the user, which means we seek to restore it
@@ -113,7 +113,7 @@ public class AppDataRollbackHelper {
                // We've encountered a user that hasn't unlocked on a FBE device, so we can't
                // copy across app user data until the user unlocks their device.
                pendingRestores.add(new RestoreInfo(userId, appId, seInfo));
                changedRollbackData = true;
                changedRollback = true;
            } else {
                // This user has unlocked, we can proceed to restore both CE and DE data.
                storageFlags = storageFlags | Installer.FLAG_STORAGE_CE;
@@ -128,7 +128,7 @@ public class AppDataRollbackHelper {
                        + packageRollbackInfo.getPackageName(), ie);
        }

        return changedRollbackData;
        return changedRollback;
    }

    /**
@@ -160,29 +160,29 @@ public class AppDataRollbackHelper {
     * Packages pending backup for the given user are added to {@code pendingBackupPackages} along
     * with their corresponding {@code PackageRollbackInfo}.
     *
     * @return the list of {@code RollbackData} that has pending backups. Note that some of the
     * @return the list of rollbacks that have pending backups. Note that some of the
     *         backups won't be performed, because they might be counteracted by pending restores.
     */
    private static List<RollbackData> computePendingBackups(int userId,
    private static List<Rollback> computePendingBackups(int userId,
            Map<String, PackageRollbackInfo> pendingBackupPackages,
            List<RollbackData> rollbacks) {
        List<RollbackData> rd = new ArrayList<>();
            List<Rollback> rollbacks) {
        List<Rollback> rollbacksWithPendingBackups = new ArrayList<>();

        for (RollbackData data : rollbacks) {
            for (PackageRollbackInfo info : data.info.getPackages()) {
        for (Rollback rollback : rollbacks) {
            for (PackageRollbackInfo info : rollback.info.getPackages()) {
                final IntArray pendingBackupUsers = info.getPendingBackups();
                if (pendingBackupUsers != null) {
                    final int idx = pendingBackupUsers.indexOf(userId);
                    if (idx != -1) {
                        pendingBackupPackages.put(info.getPackageName(), info);
                        if (rd.indexOf(data) == -1) {
                            rd.add(data);
                        if (rollbacksWithPendingBackups.indexOf(rollback) == -1) {
                            rollbacksWithPendingBackups.add(rollback);
                        }
                    }
                }
            }
        }
        return rd;
        return rollbacksWithPendingBackups;
    }

    /**
@@ -190,45 +190,45 @@ public class AppDataRollbackHelper {
     * Packages pending restore are added to {@code pendingRestores} along with their corresponding
     * {@code PackageRollbackInfo}.
     *
     * @return the list of {@code RollbackData} that has pending restores. Note that some of the
     * @return the list of rollbacks that have pending restores. Note that some of the
     *         restores won't be performed, because they might be counteracted by pending backups.
     */
    private static List<RollbackData> computePendingRestores(int userId,
    private static List<Rollback> computePendingRestores(int userId,
            Map<String, PackageRollbackInfo> pendingRestorePackages,
            List<RollbackData> rollbacks) {
        List<RollbackData> rd = new ArrayList<>();
            List<Rollback> rollbacks) {
        List<Rollback> rollbacksWithPendingRestores = new ArrayList<>();

        for (RollbackData data : rollbacks) {
            for (PackageRollbackInfo info : data.info.getPackages()) {
        for (Rollback rollback : rollbacks) {
            for (PackageRollbackInfo info : rollback.info.getPackages()) {
                final RestoreInfo ri = info.getRestoreInfo(userId);
                if (ri != null) {
                    pendingRestorePackages.put(info.getPackageName(), info);
                    if (rd.indexOf(data) == -1) {
                        rd.add(data);
                    if (rollbacksWithPendingRestores.indexOf(rollback) == -1) {
                        rollbacksWithPendingRestores.add(rollback);
                    }
                }
            }
        }

        return rd;
        return rollbacksWithPendingRestores;
    }

    /**
     * Commits the list of pending backups and restores for a given {@code userId}. For the pending
     * backups updates corresponding {@code changedRollbackData} with a mapping from {@code userId}
     * to a inode of theirs CE user data snapshot.
     * Commits the list of pending backups and restores for a given {@code userId}. For rollbacks
     * with pending backups, updates the {@code Rollback} instance with a mapping from
     * {@code userId} to inode of the CE user data snapshot.
     *
     * @return the set of {@code RollbackData} that have been changed and should be stored on disk.
     * @return the set of rollbacks with changes that should be stored on disk.
     */
    public Set<RollbackData> commitPendingBackupAndRestoreForUser(int userId,
            List<RollbackData> rollbacks) {
    public Set<Rollback> commitPendingBackupAndRestoreForUser(int userId,
            List<Rollback> rollbacks) {

        final Map<String, PackageRollbackInfo> pendingBackupPackages = new HashMap<>();
        final List<RollbackData> pendingBackups = computePendingBackups(userId,
        final List<Rollback> pendingBackups = computePendingBackups(userId,
                pendingBackupPackages, rollbacks);

        final Map<String, PackageRollbackInfo> pendingRestorePackages = new HashMap<>();
        final List<RollbackData> pendingRestores = computePendingRestores(userId,
        final List<Rollback> pendingRestores = computePendingRestores(userId,
                pendingRestorePackages, rollbacks);

        // First remove unnecessary backups, i.e. when user did not unlock their phone between the
@@ -248,14 +248,15 @@ public class AppDataRollbackHelper {
        }

        if (!pendingBackupPackages.isEmpty()) {
            for (RollbackData data : pendingBackups) {
                for (PackageRollbackInfo info : data.info.getPackages()) {
            for (Rollback rollback : pendingBackups) {
                for (PackageRollbackInfo info : rollback.info.getPackages()) {
                    final IntArray pendingBackupUsers = info.getPendingBackups();
                    final int idx = pendingBackupUsers.indexOf(userId);
                    if (idx != -1) {
                        try {
                            long ceSnapshotInode = mInstaller.snapshotAppData(info.getPackageName(),
                                    userId, data.info.getRollbackId(), Installer.FLAG_STORAGE_CE);
                                    userId, rollback.info.getRollbackId(),
                                    Installer.FLAG_STORAGE_CE);
                            info.putCeSnapshotInode(userId, ceSnapshotInode);
                            pendingBackupUsers.remove(idx);
                        } catch (InstallerException ie) {
@@ -269,13 +270,13 @@ public class AppDataRollbackHelper {
        }

        if (!pendingRestorePackages.isEmpty()) {
            for (RollbackData data : pendingRestores) {
                for (PackageRollbackInfo info : data.info.getPackages()) {
            for (Rollback rollback : pendingRestores) {
                for (PackageRollbackInfo info : rollback.info.getPackages()) {
                    final RestoreInfo ri = info.getRestoreInfo(userId);
                    if (ri != null) {
                        try {
                            mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId,
                                    ri.seInfo, userId, data.info.getRollbackId(),
                                    ri.seInfo, userId, rollback.info.getRollbackId(),
                                    Installer.FLAG_STORAGE_CE);
                            info.removeRestoreInfo(ri);
                        } catch (InstallerException ie) {
@@ -287,7 +288,7 @@ public class AppDataRollbackHelper {
            }
        }

        final Set<RollbackData> changed = new HashSet<>(pendingBackups);
        final Set<Rollback> changed = new HashSet<>(pendingBackups);
        changed.addAll(pendingRestores);
        return changed;
    }
+11 −11
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ import java.util.ArrayList;
 * Information about a rollback available for a set of atomically installed
 * packages.
 */
class RollbackData {
class Rollback {
    @IntDef(flag = true, prefix = { "ROLLBACK_STATE_" }, value = {
            ROLLBACK_STATE_ENABLING,
            ROLLBACK_STATE_AVAILABLE,
@@ -102,13 +102,13 @@ class RollbackData {
    public boolean restoreUserDataInProgress = false;

    /**
     * Constructs a new, empty RollbackData instance.
     * Constructs a new, empty Rollback instance.
     *
     * @param rollbackId the id of the rollback.
     * @param backupDir the directory where the rollback data is stored.
     * @param stagedSessionId the session id if this is a staged rollback, -1 otherwise.
     */
    RollbackData(int rollbackId, File backupDir, int stagedSessionId) {
    Rollback(int rollbackId, File backupDir, int stagedSessionId) {
        this.info = new RollbackInfo(rollbackId,
                /* packages */ new ArrayList<>(),
                /* isStaged */ stagedSessionId != -1,
@@ -121,9 +121,9 @@ class RollbackData {
    }

    /**
     * Constructs a RollbackData instance with full rollback data information.
     * Constructs a pre-populated Rollback instance.
     */
    RollbackData(RollbackInfo info, File backupDir, Instant timestamp, int stagedSessionId,
    Rollback(RollbackInfo info, File backupDir, Instant timestamp, int stagedSessionId,
            @RollbackState int state, int apkSessionId, boolean restoreUserDataInProgress) {
        this.info = info;
        this.backupDir = backupDir;
@@ -143,9 +143,9 @@ class RollbackData {

    static String rollbackStateToString(@RollbackState int state) {
        switch (state) {
            case RollbackData.ROLLBACK_STATE_ENABLING: return "enabling";
            case RollbackData.ROLLBACK_STATE_AVAILABLE: return "available";
            case RollbackData.ROLLBACK_STATE_COMMITTED: return "committed";
            case Rollback.ROLLBACK_STATE_ENABLING: return "enabling";
            case Rollback.ROLLBACK_STATE_AVAILABLE: return "available";
            case Rollback.ROLLBACK_STATE_COMMITTED: return "committed";
        }
        throw new AssertionError("Invalid rollback state: " + state);
    }
@@ -153,9 +153,9 @@ class RollbackData {
    static @RollbackState int rollbackStateFromString(String state)
            throws ParseException {
        switch (state) {
            case "enabling": return RollbackData.ROLLBACK_STATE_ENABLING;
            case "available": return RollbackData.ROLLBACK_STATE_AVAILABLE;
            case "committed": return RollbackData.ROLLBACK_STATE_COMMITTED;
            case "enabling": return Rollback.ROLLBACK_STATE_ENABLING;
            case "available": return Rollback.ROLLBACK_STATE_AVAILABLE;
            case "committed": return Rollback.ROLLBACK_STATE_COMMITTED;
        }
        throw new ParseException("Invalid rollback state: " + state, 0);
    }
+162 −162

File changed.

Preview size limit exceeded, changes collapsed.

+35 −35
Original line number Diff line number Diff line
@@ -16,8 +16,8 @@

package com.android.server.rollback;

import static com.android.server.rollback.RollbackData.rollbackStateFromString;
import static com.android.server.rollback.RollbackData.rollbackStateToString;
import static com.android.server.rollback.Rollback.rollbackStateFromString;
import static com.android.server.rollback.Rollback.rollbackStateToString;

import android.annotation.NonNull;
import android.content.pm.VersionedPackage;
@@ -73,17 +73,17 @@ class RollbackStore {
    }

    /**
     * Reads the rollback data from persistent storage.
     * Reads the rollbacks from persistent storage.
     */
    List<RollbackData> loadAllRollbackData() {
        List<RollbackData> rollbacks = new ArrayList<>();
    List<Rollback> loadRollbacks() {
        List<Rollback> rollbacks = new ArrayList<>();
        mRollbackDataDir.mkdirs();
        for (File rollbackDir : mRollbackDataDir.listFiles()) {
            if (rollbackDir.isDirectory()) {
                try {
                    rollbacks.add(loadRollbackData(rollbackDir));
                    rollbacks.add(loadRollback(rollbackDir));
                } catch (IOException e) {
                    Slog.e(TAG, "Unable to read rollback data at " + rollbackDir, e);
                    Slog.e(TAG, "Unable to read rollback at " + rollbackDir, e);
                    removeFile(rollbackDir);
                }
            }
@@ -191,21 +191,21 @@ class RollbackStore {
    }

    /**
     * Creates a new RollbackData instance for a non-staged rollback with
     * Creates a new Rollback instance for a non-staged rollback with
     * backupDir assigned.
     */
    RollbackData createNonStagedRollback(int rollbackId) {
    Rollback createNonStagedRollback(int rollbackId) {
        File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId));
        return new RollbackData(rollbackId, backupDir, -1);
        return new Rollback(rollbackId, backupDir, -1);
    }

    /**
     * Creates a new RollbackData instance for a staged rollback with
     * Creates a new Rollback instance for a staged rollback with
     * backupDir assigned.
     */
    RollbackData createStagedRollback(int rollbackId, int stagedSessionId) {
    Rollback createStagedRollback(int rollbackId, int stagedSessionId) {
        File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId));
        return new RollbackData(rollbackId, backupDir, stagedSessionId);
        return new Rollback(rollbackId, backupDir, stagedSessionId);
    }

    /**
@@ -213,10 +213,10 @@ class RollbackStore {
     * For packages containing splits, this method should be called for each
     * of the package's split apks in addition to the base apk.
     */
    static void backupPackageCodePath(RollbackData data, String packageName, String codePath)
    static void backupPackageCodePath(Rollback rollback, String packageName, String codePath)
            throws IOException {
        File sourceFile = new File(codePath);
        File targetDir = new File(data.backupDir, packageName);
        File targetDir = new File(rollback.backupDir, packageName);
        targetDir.mkdirs();
        File targetFile = new File(targetDir, sourceFile.getName());

@@ -228,8 +228,8 @@ class RollbackStore {
     * Returns the apk or apex files backed up for the given package.
     * Includes the base apk and any splits. Returns null if none found.
     */
    static File[] getPackageCodePaths(RollbackData data, String packageName) {
        File targetDir = new File(data.backupDir, packageName);
    static File[] getPackageCodePaths(Rollback rollback, String packageName) {
        File targetDir = new File(rollback.backupDir, packageName);
        File[] files = targetDir.listFiles();
        if (files == null || files.length == 0) {
            return null;
@@ -241,27 +241,27 @@ class RollbackStore {
     * Deletes all backed up apks and apex files associated with the given
     * rollback.
     */
    static void deletePackageCodePaths(RollbackData data) {
        for (PackageRollbackInfo info : data.info.getPackages()) {
            File targetDir = new File(data.backupDir, info.getPackageName());
    static void deletePackageCodePaths(Rollback rollback) {
        for (PackageRollbackInfo info : rollback.info.getPackages()) {
            File targetDir = new File(rollback.backupDir, info.getPackageName());
            removeFile(targetDir);
        }
    }

    /**
     * Saves the rollback data to persistent storage.
     * Saves the given rollback to persistent storage.
     */
    void saveRollbackData(RollbackData data) throws IOException {
    void saveRollback(Rollback rollback) throws IOException {
        try {
            JSONObject dataJson = new JSONObject();
            dataJson.put("info", rollbackInfoToJson(data.info));
            dataJson.put("timestamp", data.timestamp.toString());
            dataJson.put("stagedSessionId", data.stagedSessionId);
            dataJson.put("state", rollbackStateToString(data.state));
            dataJson.put("apkSessionId", data.apkSessionId);
            dataJson.put("restoreUserDataInProgress", data.restoreUserDataInProgress);

            PrintWriter pw = new PrintWriter(new File(data.backupDir, "rollback.json"));
            dataJson.put("info", rollbackInfoToJson(rollback.info));
            dataJson.put("timestamp", rollback.timestamp.toString());
            dataJson.put("stagedSessionId", rollback.stagedSessionId);
            dataJson.put("state", rollbackStateToString(rollback.state));
            dataJson.put("apkSessionId", rollback.apkSessionId);
            dataJson.put("restoreUserDataInProgress", rollback.restoreUserDataInProgress);

            PrintWriter pw = new PrintWriter(new File(rollback.backupDir, "rollback.json"));
            pw.println(dataJson.toString());
            pw.close();
        } catch (JSONException e) {
@@ -270,23 +270,23 @@ class RollbackStore {
    }

    /**
     * Removes all persistant storage associated with the given rollback data.
     * Removes all persistent storage associated with the given rollback.
     */
    void deleteRollbackData(RollbackData data) {
        removeFile(data.backupDir);
    void deleteRollback(Rollback rollback) {
        removeFile(rollback.backupDir);
    }

    /**
     * Reads the metadata for a rollback from the given directory.
     * @throws IOException in case of error reading the data.
     */
    private static RollbackData loadRollbackData(File backupDir) throws IOException {
    private static Rollback loadRollback(File backupDir) throws IOException {
        try {
            File rollbackJsonFile = new File(backupDir, "rollback.json");
            JSONObject dataJson = new JSONObject(
                    IoUtils.readFileAsString(rollbackJsonFile.getAbsolutePath()));

            return new RollbackData(
            return new Rollback(
                    rollbackInfoFromJson(dataJson.getJSONObject("info")),
                    backupDir,
                    Instant.parse(dataJson.getString("timestamp")),
+6 −6
Original line number Diff line number Diff line
@@ -235,22 +235,22 @@ public class AppDataRollbackHelperTest {
        wasRecentlyRestored.getPendingRestores().add(
                new RestoreInfo(73 /* userId */, 239 /* appId*/, "seInfo"));

        RollbackData dataWithPendingBackup = new RollbackData(101, new File("/does/not/exist"), -1);
        Rollback dataWithPendingBackup = new Rollback(101, new File("/does/not/exist"), -1);
        dataWithPendingBackup.info.getPackages().add(pendingBackup);

        RollbackData dataWithRecentRestore = new RollbackData(17239, new File("/does/not/exist"),
        Rollback dataWithRecentRestore = new Rollback(17239, new File("/does/not/exist"),
                -1);
        dataWithRecentRestore.info.getPackages().add(wasRecentlyRestored);

        RollbackData dataForDifferentUser = new RollbackData(17239, new File("/does/not/exist"),
        Rollback dataForDifferentUser = new Rollback(17239, new File("/does/not/exist"),
                -1);
        dataForDifferentUser.info.getPackages().add(ignoredInfo);

        RollbackData dataForRestore = new RollbackData(17239, new File("/does/not/exist"), -1);
        Rollback dataForRestore = new Rollback(17239, new File("/does/not/exist"), -1);
        dataForRestore.info.getPackages().add(pendingRestore);
        dataForRestore.info.getPackages().add(wasRecentlyRestored);

        Set<RollbackData> changed = helper.commitPendingBackupAndRestoreForUser(37,
        Set<Rollback> changed = helper.commitPendingBackupAndRestoreForUser(37,
                Arrays.asList(dataWithPendingBackup, dataWithRecentRestore, dataForDifferentUser,
                    dataForRestore));
        InOrder inOrder = Mockito.inOrder(installer);
@@ -265,7 +265,7 @@ public class AppDataRollbackHelperTest {
        assertEquals(-1, pendingBackup.getPendingBackups().indexOf(37));
        assertEquals(53, pendingBackup.getCeSnapshotInodes().get(37));

        // Check that changed returns correct RollbackData.
        // Check that changed returns correct Rollback.
        assertEquals(3, changed.size());
        assertTrue(changed.contains(dataWithPendingBackup));
        assertTrue(changed.contains(dataWithRecentRestore));