Loading services/core/java/com/android/server/rollback/AppDataRollbackHelper.java +38 −37 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; Loading @@ -128,7 +128,7 @@ public class AppDataRollbackHelper { + packageRollbackInfo.getPackageName(), ie); } return changedRollbackData; return changedRollback; } /** Loading Loading @@ -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; } /** Loading @@ -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 Loading @@ -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) { Loading @@ -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) { Loading @@ -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; } Loading services/core/java/com/android/server/rollback/RollbackData.java→services/core/java/com/android/server/rollback/Rollback.java +11 −11 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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, Loading @@ -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; Loading @@ -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); } Loading @@ -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); } Loading services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +162 −162 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/rollback/RollbackStore.java +35 −35 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } Loading Loading @@ -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); } /** Loading @@ -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()); Loading @@ -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; Loading @@ -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) { Loading @@ -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")), Loading services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java +6 −6 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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)); Loading Loading
services/core/java/com/android/server/rollback/AppDataRollbackHelper.java +38 −37 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; Loading @@ -128,7 +128,7 @@ public class AppDataRollbackHelper { + packageRollbackInfo.getPackageName(), ie); } return changedRollbackData; return changedRollback; } /** Loading Loading @@ -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; } /** Loading @@ -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 Loading @@ -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) { Loading @@ -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) { Loading @@ -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; } Loading
services/core/java/com/android/server/rollback/RollbackData.java→services/core/java/com/android/server/rollback/Rollback.java +11 −11 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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, Loading @@ -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; Loading @@ -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); } Loading @@ -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); } Loading
services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +162 −162 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/rollback/RollbackStore.java +35 −35 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } Loading Loading @@ -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); } /** Loading @@ -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()); Loading @@ -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; Loading @@ -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) { Loading @@ -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")), Loading
services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java +6 −6 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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)); Loading