Rename RollbackData to Rollback.

Because "Data" doesn't add anything useful to the name.

Also prefer the variable name "rollback" over "data" and "rd" for
instances of Rollback.

Test: builds.
Change-Id: Ibaa3326660345a763c67c573368ba1da11c0a830
Merged-In: I5ae3866753d6badcdf019525b40522937568dee5
This commit is contained in:
Richard Uhler
2019-07-19 14:55:01 +01:00
committed by Bill Lin
parent 87a504d1fc
commit 91fc4db14e
5 changed files with 251 additions and 250 deletions

View File

@@ -98,14 +98,14 @@ public class AppDataRollbackHelper {
final IntArray pendingBackups = packageRollbackInfo.getPendingBackups(); final IntArray pendingBackups = packageRollbackInfo.getPendingBackups();
final List<RestoreInfo> pendingRestores = packageRollbackInfo.getPendingRestores(); 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 // 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, // 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. // so the data cannot have changed. We simply skip restoring CE data in this case.
if (pendingBackups != null && pendingBackups.indexOf(userId) != -1) { if (pendingBackups != null && pendingBackups.indexOf(userId) != -1) {
pendingBackups.remove(pendingBackups.indexOf(userId)); pendingBackups.remove(pendingBackups.indexOf(userId));
changedRollbackData = true; changedRollback = true;
} else { } else {
// There's no pending CE backup for this user, which means that we successfully // 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 // 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 // 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. // copy across app user data until the user unlocks their device.
pendingRestores.add(new RestoreInfo(userId, appId, seInfo)); pendingRestores.add(new RestoreInfo(userId, appId, seInfo));
changedRollbackData = true; changedRollback = true;
} else { } else {
// This user has unlocked, we can proceed to restore both CE and DE data. // This user has unlocked, we can proceed to restore both CE and DE data.
storageFlags = storageFlags | Installer.FLAG_STORAGE_CE; storageFlags = storageFlags | Installer.FLAG_STORAGE_CE;
@@ -128,7 +128,7 @@ public class AppDataRollbackHelper {
+ packageRollbackInfo.getPackageName(), ie); + 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 * Packages pending backup for the given user are added to {@code pendingBackupPackages} along
* with their corresponding {@code PackageRollbackInfo}. * 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. * 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, Map<String, PackageRollbackInfo> pendingBackupPackages,
List<RollbackData> rollbacks) { List<Rollback> rollbacks) {
List<RollbackData> rd = new ArrayList<>(); List<Rollback> rollbacksWithPendingBackups = new ArrayList<>();
for (RollbackData data : rollbacks) { for (Rollback rollback : rollbacks) {
for (PackageRollbackInfo info : data.info.getPackages()) { for (PackageRollbackInfo info : rollback.info.getPackages()) {
final IntArray pendingBackupUsers = info.getPendingBackups(); final IntArray pendingBackupUsers = info.getPendingBackups();
if (pendingBackupUsers != null) { if (pendingBackupUsers != null) {
final int idx = pendingBackupUsers.indexOf(userId); final int idx = pendingBackupUsers.indexOf(userId);
if (idx != -1) { if (idx != -1) {
pendingBackupPackages.put(info.getPackageName(), info); pendingBackupPackages.put(info.getPackageName(), info);
if (rd.indexOf(data) == -1) { if (rollbacksWithPendingBackups.indexOf(rollback) == -1) {
rd.add(data); 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 * Packages pending restore are added to {@code pendingRestores} along with their corresponding
* {@code PackageRollbackInfo}. * {@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. * 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, Map<String, PackageRollbackInfo> pendingRestorePackages,
List<RollbackData> rollbacks) { List<Rollback> rollbacks) {
List<RollbackData> rd = new ArrayList<>(); List<Rollback> rollbacksWithPendingRestores = new ArrayList<>();
for (RollbackData data : rollbacks) { for (Rollback rollback : rollbacks) {
for (PackageRollbackInfo info : data.info.getPackages()) { for (PackageRollbackInfo info : rollback.info.getPackages()) {
final RestoreInfo ri = info.getRestoreInfo(userId); final RestoreInfo ri = info.getRestoreInfo(userId);
if (ri != null) { if (ri != null) {
pendingRestorePackages.put(info.getPackageName(), info); pendingRestorePackages.put(info.getPackageName(), info);
if (rd.indexOf(data) == -1) { if (rollbacksWithPendingRestores.indexOf(rollback) == -1) {
rd.add(data); rollbacksWithPendingRestores.add(rollback);
} }
} }
} }
} }
return rd; return rollbacksWithPendingRestores;
} }
/** /**
* Commits the list of pending backups and restores for a given {@code userId}. For the pending * Commits the list of pending backups and restores for a given {@code userId}. For rollbacks
* backups updates corresponding {@code changedRollbackData} with a mapping from {@code userId} * with pending backups, updates the {@code Rollback} instance with a mapping from
* to a inode of theirs CE user data snapshot. * {@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, public Set<Rollback> commitPendingBackupAndRestoreForUser(int userId,
List<RollbackData> rollbacks) { List<Rollback> rollbacks) {
final Map<String, PackageRollbackInfo> pendingBackupPackages = new HashMap<>(); final Map<String, PackageRollbackInfo> pendingBackupPackages = new HashMap<>();
final List<RollbackData> pendingBackups = computePendingBackups(userId, final List<Rollback> pendingBackups = computePendingBackups(userId,
pendingBackupPackages, rollbacks); pendingBackupPackages, rollbacks);
final Map<String, PackageRollbackInfo> pendingRestorePackages = new HashMap<>(); final Map<String, PackageRollbackInfo> pendingRestorePackages = new HashMap<>();
final List<RollbackData> pendingRestores = computePendingRestores(userId, final List<Rollback> pendingRestores = computePendingRestores(userId,
pendingRestorePackages, rollbacks); pendingRestorePackages, rollbacks);
// First remove unnecessary backups, i.e. when user did not unlock their phone between the // 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()) { if (!pendingBackupPackages.isEmpty()) {
for (RollbackData data : pendingBackups) { for (Rollback rollback : pendingBackups) {
for (PackageRollbackInfo info : data.info.getPackages()) { for (PackageRollbackInfo info : rollback.info.getPackages()) {
final IntArray pendingBackupUsers = info.getPendingBackups(); final IntArray pendingBackupUsers = info.getPendingBackups();
final int idx = pendingBackupUsers.indexOf(userId); final int idx = pendingBackupUsers.indexOf(userId);
if (idx != -1) { if (idx != -1) {
try { try {
long ceSnapshotInode = mInstaller.snapshotAppData(info.getPackageName(), 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); info.putCeSnapshotInode(userId, ceSnapshotInode);
pendingBackupUsers.remove(idx); pendingBackupUsers.remove(idx);
} catch (InstallerException ie) { } catch (InstallerException ie) {
@@ -269,13 +270,13 @@ public class AppDataRollbackHelper {
} }
if (!pendingRestorePackages.isEmpty()) { if (!pendingRestorePackages.isEmpty()) {
for (RollbackData data : pendingRestores) { for (Rollback rollback : pendingRestores) {
for (PackageRollbackInfo info : data.info.getPackages()) { for (PackageRollbackInfo info : rollback.info.getPackages()) {
final RestoreInfo ri = info.getRestoreInfo(userId); final RestoreInfo ri = info.getRestoreInfo(userId);
if (ri != null) { if (ri != null) {
try { try {
mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId, mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId,
ri.seInfo, userId, data.info.getRollbackId(), ri.seInfo, userId, rollback.info.getRollbackId(),
Installer.FLAG_STORAGE_CE); Installer.FLAG_STORAGE_CE);
info.removeRestoreInfo(ri); info.removeRestoreInfo(ri);
} catch (InstallerException ie) { } 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); changed.addAll(pendingRestores);
return changed; return changed;
} }

View File

@@ -32,7 +32,7 @@ import java.util.ArrayList;
* Information about a rollback available for a set of atomically installed * Information about a rollback available for a set of atomically installed
* packages. * packages.
*/ */
class RollbackData { class Rollback {
@IntDef(flag = true, prefix = { "ROLLBACK_STATE_" }, value = { @IntDef(flag = true, prefix = { "ROLLBACK_STATE_" }, value = {
ROLLBACK_STATE_ENABLING, ROLLBACK_STATE_ENABLING,
ROLLBACK_STATE_AVAILABLE, ROLLBACK_STATE_AVAILABLE,
@@ -102,13 +102,13 @@ class RollbackData {
public boolean restoreUserDataInProgress = false; public boolean restoreUserDataInProgress = false;
/** /**
* Constructs a new, empty RollbackData instance. * Constructs a new, empty Rollback instance.
* *
* @param rollbackId the id of the rollback. * @param rollbackId the id of the rollback.
* @param backupDir the directory where the rollback data is stored. * @param backupDir the directory where the rollback data is stored.
* @param stagedSessionId the session id if this is a staged rollback, -1 otherwise. * @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, this.info = new RollbackInfo(rollbackId,
/* packages */ new ArrayList<>(), /* packages */ new ArrayList<>(),
/* isStaged */ stagedSessionId != -1, /* 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) { @RollbackState int state, int apkSessionId, boolean restoreUserDataInProgress) {
this.info = info; this.info = info;
this.backupDir = backupDir; this.backupDir = backupDir;
@@ -143,9 +143,9 @@ class RollbackData {
static String rollbackStateToString(@RollbackState int state) { static String rollbackStateToString(@RollbackState int state) {
switch (state) { switch (state) {
case RollbackData.ROLLBACK_STATE_ENABLING: return "enabling"; case Rollback.ROLLBACK_STATE_ENABLING: return "enabling";
case RollbackData.ROLLBACK_STATE_AVAILABLE: return "available"; case Rollback.ROLLBACK_STATE_AVAILABLE: return "available";
case RollbackData.ROLLBACK_STATE_COMMITTED: return "committed"; case Rollback.ROLLBACK_STATE_COMMITTED: return "committed";
} }
throw new AssertionError("Invalid rollback state: " + state); throw new AssertionError("Invalid rollback state: " + state);
} }
@@ -153,9 +153,9 @@ class RollbackData {
static @RollbackState int rollbackStateFromString(String state) static @RollbackState int rollbackStateFromString(String state)
throws ParseException { throws ParseException {
switch (state) { switch (state) {
case "enabling": return RollbackData.ROLLBACK_STATE_ENABLING; case "enabling": return Rollback.ROLLBACK_STATE_ENABLING;
case "available": return RollbackData.ROLLBACK_STATE_AVAILABLE; case "available": return Rollback.ROLLBACK_STATE_AVAILABLE;
case "committed": return RollbackData.ROLLBACK_STATE_COMMITTED; case "committed": return Rollback.ROLLBACK_STATE_COMMITTED;
} }
throw new ParseException("Invalid rollback state: " + state, 0); throw new ParseException("Invalid rollback state: " + state, 0);
} }

View File

@@ -110,13 +110,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
@GuardedBy("mLock") @GuardedBy("mLock")
private final SparseBooleanArray mAllocatedRollbackIds = new SparseBooleanArray(); private final SparseBooleanArray mAllocatedRollbackIds = new SparseBooleanArray();
// Package rollback data for rollbacks we are in the process of enabling. // Rollbacks we are in the process of enabling.
@GuardedBy("mLock") @GuardedBy("mLock")
private final Set<NewRollback> mNewRollbacks = new ArraySet<>(); private final Set<NewRollback> mNewRollbacks = new ArraySet<>();
// The list of all rollbacks, including available and committed rollbacks. // The list of all rollbacks, including available and committed rollbacks.
@GuardedBy("mLock") @GuardedBy("mLock")
private final List<RollbackData> mRollbacks; private final List<Rollback> mRollbacks;
private final RollbackStore mRollbackStore; private final RollbackStore mRollbackStore;
@@ -127,7 +127,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
private final AppDataRollbackHelper mAppDataRollbackHelper; private final AppDataRollbackHelper mAppDataRollbackHelper;
// This field stores the difference in Millis between the uptime (millis since device // This field stores the difference in Millis between the uptime (millis since device
// has booted) and current time (device wall clock) - it's used to update rollback data // has booted) and current time (device wall clock) - it's used to update rollback
// timestamps when the time is changed, by the user or by change of timezone. // timestamps when the time is changed, by the user or by change of timezone.
// No need for guarding with lock because value is only accessed in handler thread. // No need for guarding with lock because value is only accessed in handler thread.
private long mRelativeBootTime = calculateRelativeBootTime(); private long mRelativeBootTime = calculateRelativeBootTime();
@@ -146,9 +146,9 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// Load rollback data from device storage. // Load rollback data from device storage.
synchronized (mLock) { synchronized (mLock) {
mRollbacks = mRollbackStore.loadAllRollbackData(); mRollbacks = mRollbackStore.loadRollbacks();
for (RollbackData data : mRollbacks) { for (Rollback rollback : mRollbacks) {
mAllocatedRollbackIds.put(data.info.getRollbackId(), true); mAllocatedRollbackIds.put(rollback.info.getRollbackId(), true);
} }
} }
@@ -301,9 +301,9 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
synchronized (mLock) { synchronized (mLock) {
List<RollbackInfo> rollbacks = new ArrayList<>(); List<RollbackInfo> rollbacks = new ArrayList<>();
for (int i = 0; i < mRollbacks.size(); ++i) { for (int i = 0; i < mRollbacks.size(); ++i) {
RollbackData data = mRollbacks.get(i); Rollback rollback = mRollbacks.get(i);
if (data.state == RollbackData.ROLLBACK_STATE_AVAILABLE) { if (rollback.state == Rollback.ROLLBACK_STATE_AVAILABLE) {
rollbacks.add(data.info); rollbacks.add(rollback.info);
} }
} }
return new ParceledListSlice<>(rollbacks); return new ParceledListSlice<>(rollbacks);
@@ -317,9 +317,9 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
synchronized (mLock) { synchronized (mLock) {
List<RollbackInfo> rollbacks = new ArrayList<>(); List<RollbackInfo> rollbacks = new ArrayList<>();
for (int i = 0; i < mRollbacks.size(); ++i) { for (int i = 0; i < mRollbacks.size(); ++i) {
RollbackData data = mRollbacks.get(i); Rollback rollback = mRollbacks.get(i);
if (data.state == RollbackData.ROLLBACK_STATE_COMMITTED) { if (rollback.state == Rollback.ROLLBACK_STATE_COMMITTED) {
rollbacks.add(data.info); rollbacks.add(rollback.info);
} }
} }
return new ParceledListSlice<>(rollbacks); return new ParceledListSlice<>(rollbacks);
@@ -349,11 +349,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
final long timeDifference = mRelativeBootTime - oldRelativeBootTime; final long timeDifference = mRelativeBootTime - oldRelativeBootTime;
synchronized (mLock) { synchronized (mLock) {
Iterator<RollbackData> iter = mRollbacks.iterator(); Iterator<Rollback> iter = mRollbacks.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
RollbackData data = iter.next(); Rollback rollback = iter.next();
data.timestamp = data.timestamp.plusMillis(timeDifference); rollback.timestamp = rollback.timestamp.plusMillis(timeDifference);
saveRollbackData(data); saveRollback(rollback);
} }
} }
} }
@@ -377,8 +377,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
String callerPackageName, IntentSender statusReceiver) { String callerPackageName, IntentSender statusReceiver) {
Slog.i(TAG, "Initiating rollback"); Slog.i(TAG, "Initiating rollback");
RollbackData data = getRollbackForId(rollbackId); Rollback rollback = getRollbackForId(rollbackId);
if (data == null || data.state != RollbackData.ROLLBACK_STATE_AVAILABLE) { if (rollback == null || rollback.state != Rollback.ROLLBACK_STATE_AVAILABLE) {
sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE, sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE,
"Rollback unavailable"); "Rollback unavailable");
return; return;
@@ -402,14 +402,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
PackageInstaller.SessionParams.MODE_FULL_INSTALL); PackageInstaller.SessionParams.MODE_FULL_INSTALL);
parentParams.setRequestDowngrade(true); parentParams.setRequestDowngrade(true);
parentParams.setMultiPackage(); parentParams.setMultiPackage();
if (data.isStaged()) { if (rollback.isStaged()) {
parentParams.setStaged(); parentParams.setStaged();
} }
int parentSessionId = packageInstaller.createSession(parentParams); int parentSessionId = packageInstaller.createSession(parentParams);
PackageInstaller.Session parentSession = packageInstaller.openSession(parentSessionId); PackageInstaller.Session parentSession = packageInstaller.openSession(parentSessionId);
for (PackageRollbackInfo info : data.info.getPackages()) { for (PackageRollbackInfo info : rollback.info.getPackages()) {
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL); PackageInstaller.SessionParams.MODE_FULL_INSTALL);
// TODO: We can't get the installerPackageName for apex // TODO: We can't get the installerPackageName for apex
@@ -424,7 +424,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
params.setRequestDowngrade(true); params.setRequestDowngrade(true);
params.setRequiredInstalledVersionCode( params.setRequiredInstalledVersionCode(
info.getVersionRolledBackFrom().getLongVersionCode()); info.getVersionRolledBackFrom().getLongVersionCode());
if (data.isStaged()) { if (rollback.isStaged()) {
params.setStaged(); params.setStaged();
} }
if (info.isApex()) { if (info.isApex()) {
@@ -433,7 +433,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
int sessionId = packageInstaller.createSession(params); int sessionId = packageInstaller.createSession(params);
PackageInstaller.Session session = packageInstaller.openSession(sessionId); PackageInstaller.Session session = packageInstaller.openSession(sessionId);
File[] packageCodePaths = RollbackStore.getPackageCodePaths( File[] packageCodePaths = RollbackStore.getPackageCodePaths(
data, info.getPackageName()); rollback, info.getPackageName());
if (packageCodePaths == null) { if (packageCodePaths == null) {
sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE, sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE,
"Backup copy of package inaccessible"); "Backup copy of package inaccessible");
@@ -474,8 +474,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// TODO: Could this cause a rollback to be // TODO: Could this cause a rollback to be
// resurrected if it should otherwise have // resurrected if it should otherwise have
// expired by now? // expired by now?
data.state = RollbackData.ROLLBACK_STATE_AVAILABLE; rollback.state = Rollback.ROLLBACK_STATE_AVAILABLE;
data.restoreUserDataInProgress = false; rollback.restoreUserDataInProgress = false;
} }
sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_INSTALL, sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_INSTALL,
"Rollback downgrade install failed: " "Rollback downgrade install failed: "
@@ -485,17 +485,17 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
} }
synchronized (mLock) { synchronized (mLock) {
if (!data.isStaged()) { if (!rollback.isStaged()) {
// All calls to restoreUserData should have // All calls to restoreUserData should have
// completed by now for a non-staged install. // completed by now for a non-staged install.
data.restoreUserDataInProgress = false; rollback.restoreUserDataInProgress = false;
} }
data.info.setCommittedSessionId(parentSessionId); rollback.info.setCommittedSessionId(parentSessionId);
data.info.getCausePackages().addAll(causePackages); rollback.info.getCausePackages().addAll(causePackages);
} }
mRollbackStore.deletePackageCodePaths(data); mRollbackStore.deletePackageCodePaths(rollback);
saveRollbackData(data); saveRollback(rollback);
sendSuccess(statusReceiver); sendSuccess(statusReceiver);
@@ -510,8 +510,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
); );
synchronized (mLock) { synchronized (mLock) {
data.state = RollbackData.ROLLBACK_STATE_COMMITTED; rollback.state = Rollback.ROLLBACK_STATE_COMMITTED;
data.restoreUserDataInProgress = true; rollback.restoreUserDataInProgress = true;
} }
parentSession.commit(receiver.getIntentSender()); parentSession.commit(receiver.getIntentSender());
} catch (IOException e) { } catch (IOException e) {
@@ -533,7 +533,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
updateRollbackLifetimeDurationInMillis(); updateRollbackLifetimeDurationInMillis();
synchronized (mLock) { synchronized (mLock) {
mRollbacks.clear(); mRollbacks.clear();
mRollbacks.addAll(mRollbackStore.loadAllRollbackData()); mRollbacks.addAll(mRollbackStore.loadRollbacks());
} }
latch.countDown(); latch.countDown();
}); });
@@ -551,13 +551,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
Manifest.permission.TEST_MANAGE_ROLLBACKS, Manifest.permission.TEST_MANAGE_ROLLBACKS,
"expireRollbackForPackage"); "expireRollbackForPackage");
synchronized (mLock) { synchronized (mLock) {
Iterator<RollbackData> iter = mRollbacks.iterator(); Iterator<Rollback> iter = mRollbacks.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
RollbackData data = iter.next(); Rollback rollback = iter.next();
for (PackageRollbackInfo info : data.info.getPackages()) { for (PackageRollbackInfo info : rollback.info.getPackages()) {
if (info.getPackageName().equals(packageName)) { if (info.getPackageName().equals(packageName)) {
iter.remove(); iter.remove();
deleteRollback(data); deleteRollback(rollback);
break; break;
} }
} }
@@ -581,16 +581,16 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
void onUnlockUser(int userId) { void onUnlockUser(int userId) {
getHandler().post(() -> { getHandler().post(() -> {
final List<RollbackData> rollbacks; final List<Rollback> rollbacks;
synchronized (mLock) { synchronized (mLock) {
rollbacks = new ArrayList<>(mRollbacks); rollbacks = new ArrayList<>(mRollbacks);
} }
final Set<RollbackData> changed = final Set<Rollback> changed =
mAppDataRollbackHelper.commitPendingBackupAndRestoreForUser(userId, rollbacks); mAppDataRollbackHelper.commitPendingBackupAndRestoreForUser(userId, rollbacks);
for (RollbackData rd : changed) { for (Rollback rollback : changed) {
saveRollbackData(rd); saveRollback(rollback);
} }
}); });
} }
@@ -613,19 +613,19 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
getHandler().post(() -> { getHandler().post(() -> {
// Check to see if any rollback-enabled staged sessions or staged // Check to see if any rollback-enabled staged sessions or staged
// rollback sessions been applied. // rollback sessions been applied.
List<RollbackData> enabling = new ArrayList<>(); List<Rollback> enabling = new ArrayList<>();
List<RollbackData> restoreInProgress = new ArrayList<>(); List<Rollback> restoreInProgress = new ArrayList<>();
Set<String> apexPackageNames = new HashSet<>(); Set<String> apexPackageNames = new HashSet<>();
synchronized (mLock) { synchronized (mLock) {
for (RollbackData data : mRollbacks) { for (Rollback rollback : mRollbacks) {
if (data.isStaged()) { if (rollback.isStaged()) {
if (data.state == RollbackData.ROLLBACK_STATE_ENABLING) { if (rollback.state == Rollback.ROLLBACK_STATE_ENABLING) {
enabling.add(data); enabling.add(rollback);
} else if (data.restoreUserDataInProgress) { } else if (rollback.restoreUserDataInProgress) {
restoreInProgress.add(data); restoreInProgress.add(rollback);
} }
for (PackageRollbackInfo info : data.info.getPackages()) { for (PackageRollbackInfo info : rollback.info.getPackages()) {
if (info.isApex()) { if (info.isApex()) {
apexPackageNames.add(info.getPackageName()); apexPackageNames.add(info.getPackageName());
} }
@@ -634,32 +634,32 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
} }
} }
for (RollbackData data : enabling) { for (Rollback rollback : enabling) {
PackageInstaller installer = mContext.getPackageManager().getPackageInstaller(); PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
PackageInstaller.SessionInfo session = installer.getSessionInfo( PackageInstaller.SessionInfo session = installer.getSessionInfo(
data.stagedSessionId); rollback.stagedSessionId);
if (session == null || session.isStagedSessionFailed()) { if (session == null || session.isStagedSessionFailed()) {
// TODO: Do we need to remove this from // TODO: Do we need to remove this from
// mRollbacks, or is it okay to leave as // mRollbacks, or is it okay to leave as
// unavailable until the next reboot when it will go // unavailable until the next reboot when it will go
// away on its own? // away on its own?
deleteRollback(data); deleteRollback(rollback);
} else if (session.isStagedSessionApplied()) { } else if (session.isStagedSessionApplied()) {
makeRollbackAvailable(data); makeRollbackAvailable(rollback);
} }
} }
for (RollbackData data : restoreInProgress) { for (Rollback rollback : restoreInProgress) {
PackageInstaller installer = mContext.getPackageManager().getPackageInstaller(); PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
PackageInstaller.SessionInfo session = installer.getSessionInfo( PackageInstaller.SessionInfo session = installer.getSessionInfo(
data.stagedSessionId); rollback.stagedSessionId);
// TODO: What if session is null? // TODO: What if session is null?
if (session != null) { if (session != null) {
if (session.isStagedSessionApplied() || session.isStagedSessionFailed()) { if (session.isStagedSessionApplied() || session.isStagedSessionFailed()) {
synchronized (mLock) { synchronized (mLock) {
data.restoreUserDataInProgress = false; rollback.restoreUserDataInProgress = false;
} }
saveRollbackData(data); saveRollback(rollback);
} }
} }
} }
@@ -686,19 +686,19 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
VersionedPackage installedVersion = getInstalledPackageVersion(packageName); VersionedPackage installedVersion = getInstalledPackageVersion(packageName);
synchronized (mLock) { synchronized (mLock) {
Iterator<RollbackData> iter = mRollbacks.iterator(); Iterator<Rollback> iter = mRollbacks.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
RollbackData data = iter.next(); Rollback rollback = iter.next();
// TODO: Should we remove rollbacks in the ENABLING state here? // TODO: Should we remove rollbacks in the ENABLING state here?
if (data.state == RollbackData.ROLLBACK_STATE_AVAILABLE if (rollback.state == Rollback.ROLLBACK_STATE_AVAILABLE
|| data.state == RollbackData.ROLLBACK_STATE_ENABLING) { || rollback.state == Rollback.ROLLBACK_STATE_ENABLING) {
for (PackageRollbackInfo info : data.info.getPackages()) { for (PackageRollbackInfo info : rollback.info.getPackages()) {
if (info.getPackageName().equals(packageName) if (info.getPackageName().equals(packageName)
&& !packageVersionsEqual( && !packageVersionsEqual(
info.getVersionRolledBackFrom(), info.getVersionRolledBackFrom(),
installedVersion)) { installedVersion)) {
iter.remove(); iter.remove();
deleteRollback(data); deleteRollback(rollback);
break; break;
} }
} }
@@ -754,17 +754,18 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
Instant now = Instant.now(); Instant now = Instant.now();
Instant oldest = null; Instant oldest = null;
synchronized (mLock) { synchronized (mLock) {
Iterator<RollbackData> iter = mRollbacks.iterator(); Iterator<Rollback> iter = mRollbacks.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
RollbackData data = iter.next(); Rollback rollback = iter.next();
if (data.state != RollbackData.ROLLBACK_STATE_AVAILABLE) { if (rollback.state != Rollback.ROLLBACK_STATE_AVAILABLE) {
continue; continue;
} }
if (!now.isBefore(data.timestamp.plusMillis(mRollbackLifetimeDurationInMillis))) { if (!now.isBefore(
rollback.timestamp.plusMillis(mRollbackLifetimeDurationInMillis))) {
iter.remove(); iter.remove();
deleteRollback(data); deleteRollback(rollback);
} else if (oldest == null || oldest.isAfter(data.timestamp)) { } else if (oldest == null || oldest.isAfter(rollback.timestamp)) {
oldest = data.timestamp; oldest = rollback.timestamp;
} }
} }
} }
@@ -871,8 +872,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// rollback enabled. // rollback enabled.
synchronized (mLock) { synchronized (mLock) {
for (int i = 0; i < mRollbacks.size(); ++i) { for (int i = 0; i < mRollbacks.size(); ++i) {
RollbackData data = mRollbacks.get(i); Rollback rollback = mRollbacks.get(i);
if (data.apkSessionId == parentSession.getSessionId()) { if (rollback.apkSessionId == parentSession.getSessionId()) {
// This is the apk session for a staged session with rollback enabled. We do not // This is the apk session for a staged session with rollback enabled. We do not
// need to create a new rollback for this session. // need to create a new rollback for this session.
return true; return true;
@@ -893,7 +894,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
} }
newRollback.addToken(token); newRollback.addToken(token);
return enableRollbackForPackageSession(newRollback.data, packageSession); return enableRollbackForPackageSession(newRollback.rollback, packageSession);
} }
/** /**
@@ -903,7 +904,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
* *
* @return true on success, false on failure. * @return true on success, false on failure.
*/ */
private boolean enableRollbackForPackageSession(RollbackData data, private boolean enableRollbackForPackageSession(Rollback rollback,
PackageInstaller.SessionInfo session) { PackageInstaller.SessionInfo session) {
// TODO: Don't attempt to enable rollback for split installs. // TODO: Don't attempt to enable rollback for split installs.
final int installFlags = session.installFlags; final int installFlags = session.installFlags;
@@ -966,10 +967,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
try { try {
ApplicationInfo appInfo = pkgInfo.applicationInfo; ApplicationInfo appInfo = pkgInfo.applicationInfo;
RollbackStore.backupPackageCodePath(data, packageName, appInfo.sourceDir); RollbackStore.backupPackageCodePath(rollback, packageName, appInfo.sourceDir);
if (!ArrayUtils.isEmpty(appInfo.splitSourceDirs)) { if (!ArrayUtils.isEmpty(appInfo.splitSourceDirs)) {
for (String sourceDir : appInfo.splitSourceDirs) { for (String sourceDir : appInfo.splitSourceDirs) {
RollbackStore.backupPackageCodePath(data, packageName, sourceDir); RollbackStore.backupPackageCodePath(rollback, packageName, sourceDir);
} }
} }
} catch (IOException e) { } catch (IOException e) {
@@ -978,7 +979,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
} }
synchronized (mLock) { synchronized (mLock) {
data.info.getPackages().add(packageRollbackInfo); rollback.info.getPackages().add(packageRollbackInfo);
} }
return true; return true;
} }
@@ -1004,16 +1005,16 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
synchronized (mLock) { synchronized (mLock) {
// staged installs // staged installs
for (int i = 0; i < mRollbacks.size(); i++) { for (int i = 0; i < mRollbacks.size(); i++) {
RollbackData data = mRollbacks.get(i); Rollback rollback = mRollbacks.get(i);
if (data.state != RollbackData.ROLLBACK_STATE_ENABLING) { if (rollback.state != Rollback.ROLLBACK_STATE_ENABLING) {
continue; continue;
} }
for (PackageRollbackInfo info : data.info.getPackages()) { for (PackageRollbackInfo info : rollback.info.getPackages()) {
if (info.getPackageName().equals(packageName)) { if (info.getPackageName().equals(packageName)) {
mAppDataRollbackHelper.snapshotAppData( mAppDataRollbackHelper.snapshotAppData(
data.info.getRollbackId(), info, userIds); rollback.info.getRollbackId(), info, userIds);
saveRollbackData(data); saveRollback(rollback);
break; break;
} }
} }
@@ -1021,11 +1022,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// non-staged installs // non-staged installs
PackageRollbackInfo info; PackageRollbackInfo info;
for (NewRollback rollback : mNewRollbacks) { for (NewRollback rollback : mNewRollbacks) {
info = getPackageRollbackInfo(rollback.data, packageName); info = getPackageRollbackInfo(rollback.rollback, packageName);
if (info != null) { if (info != null) {
mAppDataRollbackHelper.snapshotAppData( mAppDataRollbackHelper.snapshotAppData(
rollback.data.info.getRollbackId(), info, userIds); rollback.rollback.info.getRollbackId(), info, userIds);
saveRollbackData(rollback.data); saveRollback(rollback.rollback);
} }
} }
} }
@@ -1034,31 +1035,31 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
private void restoreUserDataInternal(String packageName, int[] userIds, int appId, private void restoreUserDataInternal(String packageName, int[] userIds, int appId,
long ceDataInode, String seInfo, int token) { long ceDataInode, String seInfo, int token) {
PackageRollbackInfo info = null; PackageRollbackInfo info = null;
RollbackData rollbackData = null; Rollback rollback = null;
synchronized (mLock) { synchronized (mLock) {
for (int i = 0; i < mRollbacks.size(); ++i) { for (int i = 0; i < mRollbacks.size(); ++i) {
RollbackData data = mRollbacks.get(i); Rollback candidate = mRollbacks.get(i);
if (data.restoreUserDataInProgress) { if (candidate.restoreUserDataInProgress) {
info = getPackageRollbackInfo(data, packageName); info = getPackageRollbackInfo(candidate, packageName);
if (info != null) { if (info != null) {
rollbackData = data; rollback = candidate;
break; break;
} }
} }
} }
} }
if (rollbackData == null) { if (rollback == null) {
return; return;
} }
for (int userId : userIds) { for (int userId : userIds) {
final boolean changedRollbackData = mAppDataRollbackHelper.restoreAppData( final boolean changedRollback = mAppDataRollbackHelper.restoreAppData(
rollbackData.info.getRollbackId(), info, userId, appId, seInfo); rollback.info.getRollbackId(), info, userId, appId, seInfo);
// We've updated metadata about this rollback, so save it to flash. // We've updated metadata about this rollback, so save it to flash.
if (changedRollbackData) { if (changedRollback) {
saveRollbackData(rollbackData); saveRollback(rollback);
} }
} }
} }
@@ -1088,7 +1089,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
} }
if (!session.isMultiPackage()) { if (!session.isMultiPackage()) {
if (!enableRollbackForPackageSession(newRollback.data, session)) { if (!enableRollbackForPackageSession(newRollback.rollback, session)) {
Slog.e(TAG, "Unable to enable rollback for session: " + sessionId); Slog.e(TAG, "Unable to enable rollback for session: " + sessionId);
result.offer(false); result.offer(false);
return; return;
@@ -1102,7 +1103,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
result.offer(false); result.offer(false);
return; return;
} }
if (!enableRollbackForPackageSession(newRollback.data, childSession)) { if (!enableRollbackForPackageSession(newRollback.rollback, childSession)) {
Slog.e(TAG, "Unable to enable rollback for session: " + sessionId); Slog.e(TAG, "Unable to enable rollback for session: " + sessionId);
result.offer(false); result.offer(false);
return; return;
@@ -1127,20 +1128,20 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
throw new SecurityException("notifyStagedApkSession may only be called by the system."); throw new SecurityException("notifyStagedApkSession may only be called by the system.");
} }
getHandler().post(() -> { getHandler().post(() -> {
RollbackData rd = null; Rollback rollback = null;
synchronized (mLock) { synchronized (mLock) {
for (int i = 0; i < mRollbacks.size(); ++i) { for (int i = 0; i < mRollbacks.size(); ++i) {
RollbackData data = mRollbacks.get(i); Rollback candidate = mRollbacks.get(i);
if (data.stagedSessionId == originalSessionId) { if (candidate.stagedSessionId == originalSessionId) {
data.apkSessionId = apkSessionId; candidate.apkSessionId = apkSessionId;
rd = data; rollback = candidate;
break; break;
} }
} }
} }
if (rd != null) { if (rollback != null) {
saveRollbackData(rd); saveRollback(rollback);
} }
}); });
} }
@@ -1250,7 +1251,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
} }
if (newRollback != null) { if (newRollback != null) {
RollbackData rollback = completeEnableRollback(newRollback, success); Rollback rollback = completeEnableRollback(newRollback, success);
if (rollback != null && !rollback.isStaged()) { if (rollback != null && !rollback.isStaged()) {
makeRollbackAvailable(rollback); makeRollbackAvailable(rollback);
} }
@@ -1263,32 +1264,32 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
* This should be called after rollback has been enabled for all packages * This should be called after rollback has been enabled for all packages
* in the rollback. It does not make the rollback available yet. * in the rollback. It does not make the rollback available yet.
* *
* @return the rollback data for a successfully enable-completed rollback, * @return the Rollback instance for a successfully enable-completed rollback,
* or null on error. * or null on error.
*/ */
private RollbackData completeEnableRollback(NewRollback newRollback, boolean success) { private Rollback completeEnableRollback(NewRollback newRollback, boolean success) {
RollbackData data = newRollback.data; Rollback rollback = newRollback.rollback;
if (!success) { if (!success) {
// The install session was aborted, clean up the pending install. // The install session was aborted, clean up the pending install.
deleteRollback(data); deleteRollback(rollback);
return null; return null;
} }
if (newRollback.isCancelled) { if (newRollback.isCancelled) {
Slog.e(TAG, "Rollback has been cancelled by PackageManager"); Slog.e(TAG, "Rollback has been cancelled by PackageManager");
deleteRollback(data); deleteRollback(rollback);
return null; return null;
} }
// It's safe to access data.info outside a synchronized block because // It's safe to access rollback.info outside a synchronized block because
// this is running on the handler thread and all changes to the // this is running on the handler thread and all changes to the
// data.info occur on the handler thread. // rollback.info occur on the handler thread.
if (data.info.getPackages().size() != newRollback.packageSessionIds.length) { if (rollback.info.getPackages().size() != newRollback.packageSessionIds.length) {
Slog.e(TAG, "Failed to enable rollback for all packages in session."); Slog.e(TAG, "Failed to enable rollback for all packages in session.");
deleteRollback(data); deleteRollback(rollback);
return null; return null;
} }
saveRollbackData(data); saveRollback(rollback);
synchronized (mLock) { synchronized (mLock) {
// Note: There is a small window of time between when // Note: There is a small window of time between when
// the session has been committed by the package // the session has been committed by the package
@@ -1296,25 +1297,25 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// here. Presumably the window is small enough that // here. Presumably the window is small enough that
// nobody will want to roll back the newly installed // nobody will want to roll back the newly installed
// package before we make the rollback available. // package before we make the rollback available.
// TODO: We'll lose the rollback data if the // TODO: We'll lose the rollback if the
// device reboots between when the session is // device reboots between when the session is
// committed and this point. Revisit this after // committed and this point. Revisit this after
// adding support for rollback of staged installs. // adding support for rollback of staged installs.
mRollbacks.add(data); mRollbacks.add(rollback);
} }
return data; return rollback;
} }
private void makeRollbackAvailable(RollbackData data) { private void makeRollbackAvailable(Rollback rollback) {
// TODO: What if the rollback has since been expired, for example due // TODO: What if the rollback has since been expired, for example due
// to a new package being installed. Won't this revive an expired // to a new package being installed. Won't this revive an expired
// rollback? Consider adding a ROLLBACK_STATE_EXPIRED to address this. // rollback? Consider adding a ROLLBACK_STATE_EXPIRED to address this.
synchronized (mLock) { synchronized (mLock) {
data.state = RollbackData.ROLLBACK_STATE_AVAILABLE; rollback.state = Rollback.ROLLBACK_STATE_AVAILABLE;
data.timestamp = Instant.now(); rollback.timestamp = Instant.now();
} }
saveRollbackData(data); saveRollback(rollback);
// TODO(zezeozue): Provide API to explicitly start observing instead // TODO(zezeozue): Provide API to explicitly start observing instead
// of doing this for all rollbacks. If we do this for all rollbacks, // of doing this for all rollbacks. If we do this for all rollbacks,
@@ -1322,8 +1323,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// After enabling and commiting any rollback, observe packages and // After enabling and commiting any rollback, observe packages and
// prepare to rollback if packages crashes too frequently. // prepare to rollback if packages crashes too frequently.
List<String> packages = new ArrayList<>(); List<String> packages = new ArrayList<>();
for (int i = 0; i < data.info.getPackages().size(); i++) { for (int i = 0; i < rollback.info.getPackages().size(); i++) {
packages.add(data.info.getPackages().get(i).getPackageName()); packages.add(rollback.info.getPackages().get(i).getPackageName());
} }
mPackageHealthObserver.startObservingHealth(packages, mPackageHealthObserver.startObservingHealth(packages,
mRollbackLifetimeDurationInMillis); mRollbackLifetimeDurationInMillis);
@@ -1331,15 +1332,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
} }
/* /*
* Returns the RollbackData, if any, for a rollback with the given * Returns the rollback with the given rollbackId, if any.
* rollbackId.
*/ */
private RollbackData getRollbackForId(int rollbackId) { private Rollback getRollbackForId(int rollbackId) {
synchronized (mLock) { synchronized (mLock) {
for (int i = 0; i < mRollbacks.size(); ++i) { for (int i = 0; i < mRollbacks.size(); ++i) {
RollbackData data = mRollbacks.get(i); Rollback rollback = mRollbacks.get(i);
if (data.info.getRollbackId() == rollbackId) { if (rollback.info.getRollbackId() == rollbackId) {
return data; return rollback;
} }
} }
} }
@@ -1349,11 +1349,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
/** /**
* Returns the {@code PackageRollbackInfo} associated with {@code packageName} from * Returns the {@code PackageRollbackInfo} associated with {@code packageName} from
* a specified {@code RollbackData}. * a specified {@code Rollback}.
*/ */
private static PackageRollbackInfo getPackageRollbackInfo(RollbackData data, private static PackageRollbackInfo getPackageRollbackInfo(Rollback rollback,
String packageName) { String packageName) {
for (PackageRollbackInfo info : data.info.getPackages()) { for (PackageRollbackInfo info : rollback.info.getPackages()) {
if (info.getPackageName().equals(packageName)) { if (info.getPackageName().equals(packageName)) {
return info; return info;
} }
@@ -1377,30 +1377,30 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
throw new IllegalStateException("Failed to allocate rollback ID"); throw new IllegalStateException("Failed to allocate rollback ID");
} }
private void deleteRollback(RollbackData rollbackData) { private void deleteRollback(Rollback rollback) {
for (PackageRollbackInfo info : rollbackData.info.getPackages()) { for (PackageRollbackInfo info : rollback.info.getPackages()) {
IntArray snapshottedUsers = info.getSnapshottedUsers(); IntArray snapshottedUsers = info.getSnapshottedUsers();
for (int i = 0; i < snapshottedUsers.size(); i++) { for (int i = 0; i < snapshottedUsers.size(); i++) {
int userId = snapshottedUsers.get(i); int userId = snapshottedUsers.get(i);
mAppDataRollbackHelper.destroyAppDataSnapshot(rollbackData.info.getRollbackId(), mAppDataRollbackHelper.destroyAppDataSnapshot(rollback.info.getRollbackId(),
info, userId); info, userId);
} }
} }
mRollbackStore.deleteRollbackData(rollbackData); mRollbackStore.deleteRollback(rollback);
} }
/** /**
* Saves rollback data, swallowing any IOExceptions. * Saves a rollback, swallowing any IOExceptions.
* For those times when it's not obvious what to do about the IOException. * For those times when it's not obvious what to do about the IOException.
* TODO: Double check we can't do a better job handling the IOException in * TODO: Double check we can't do a better job handling the IOException in
* a cases where this method is called. * a cases where this method is called.
*/ */
private void saveRollbackData(RollbackData rollbackData) { private void saveRollback(Rollback rollback) {
try { try {
mRollbackStore.saveRollbackData(rollbackData); mRollbackStore.saveRollback(rollback);
} catch (IOException ioe) { } catch (IOException ioe) {
Slog.e(TAG, "Unable to save rollback info for: " Slog.e(TAG, "Unable to save rollback for: "
+ rollbackData.info.getRollbackId(), ioe); + rollback.info.getRollbackId(), ioe);
} }
} }
@@ -1408,14 +1408,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
synchronized (mLock) { synchronized (mLock) {
for (RollbackData data : mRollbacks) { for (Rollback rollback : mRollbacks) {
RollbackInfo info = data.info; RollbackInfo info = rollback.info;
ipw.println(info.getRollbackId() + ":"); ipw.println(info.getRollbackId() + ":");
ipw.increaseIndent(); ipw.increaseIndent();
ipw.println("-state: " + data.getStateAsString()); ipw.println("-state: " + rollback.getStateAsString());
ipw.println("-timestamp: " + data.timestamp); ipw.println("-timestamp: " + rollback.timestamp);
if (data.stagedSessionId != -1) { if (rollback.stagedSessionId != -1) {
ipw.println("-stagedSessionId: " + data.stagedSessionId); ipw.println("-stagedSessionId: " + rollback.stagedSessionId);
} }
ipw.println("-packages:"); ipw.println("-packages:");
ipw.increaseIndent(); ipw.increaseIndent();
@@ -1425,7 +1425,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
+ " -> " + pkg.getVersionRolledBackTo().getLongVersionCode()); + " -> " + pkg.getVersionRolledBackTo().getLongVersionCode());
} }
ipw.decreaseIndent(); ipw.decreaseIndent();
if (data.state == RollbackData.ROLLBACK_STATE_COMMITTED) { if (rollback.state == Rollback.ROLLBACK_STATE_COMMITTED) {
ipw.println("-causePackages:"); ipw.println("-causePackages:");
ipw.increaseIndent(); ipw.increaseIndent();
for (VersionedPackage cPkg : info.getCausePackages()) { for (VersionedPackage cPkg : info.getCausePackages()) {
@@ -1451,7 +1451,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
} }
private static class NewRollback { private static class NewRollback {
public final RollbackData data; public final Rollback rollback;
/** /**
* This array holds all of the rollback tokens associated with package sessions included * This array holds all of the rollback tokens associated with package sessions included
@@ -1469,9 +1469,9 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
public final int[] packageSessionIds; public final int[] packageSessionIds;
/** /**
* Flag to determine whether the RollbackData has been cancelled. * Flag to determine whether the rollback has been cancelled.
* *
* <p>RollbackData could be invalidated and cancelled if RollbackManager receives * <p>Rollback could be invalidated and cancelled if RollbackManager receives
* {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK} from {@link PackageManager}. * {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK} from {@link PackageManager}.
* *
* <p>The main underlying assumption here is that if enabling the rollback times out, then * <p>The main underlying assumption here is that if enabling the rollback times out, then
@@ -1481,8 +1481,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
*/ */
public boolean isCancelled = false; public boolean isCancelled = false;
NewRollback(RollbackData data, int[] packageSessionIds) { NewRollback(Rollback rollback, int[] packageSessionIds) {
this.data = data; this.rollback = rollback;
this.packageSessionIds = packageSessionIds; this.packageSessionIds = packageSessionIds;
} }
@@ -1497,13 +1497,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
NewRollback createNewRollbackLocked(PackageInstaller.SessionInfo parentSession) { NewRollback createNewRollbackLocked(PackageInstaller.SessionInfo parentSession) {
int rollbackId = allocateRollbackIdLocked(); int rollbackId = allocateRollbackIdLocked();
final RollbackData data; final Rollback rollback;
int parentSessionId = parentSession.getSessionId(); int parentSessionId = parentSession.getSessionId();
if (parentSession.isStaged()) { if (parentSession.isStaged()) {
data = mRollbackStore.createStagedRollback(rollbackId, parentSessionId); rollback = mRollbackStore.createStagedRollback(rollbackId, parentSessionId);
} else { } else {
data = mRollbackStore.createNonStagedRollback(rollbackId); rollback = mRollbackStore.createNonStagedRollback(rollbackId);
} }
int[] packageSessionIds; int[] packageSessionIds;
@@ -1513,7 +1513,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
packageSessionIds = new int[]{parentSessionId}; packageSessionIds = new int[]{parentSessionId};
} }
return new NewRollback(data, packageSessionIds); return new NewRollback(rollback, packageSessionIds);
} }
/** /**
@@ -1524,10 +1524,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
NewRollback getNewRollbackForPackageSessionLocked(int packageSessionId) { NewRollback getNewRollbackForPackageSessionLocked(int packageSessionId) {
// We expect mNewRollbacks to be a very small list; linear search // We expect mNewRollbacks to be a very small list; linear search
// should be plenty fast. // should be plenty fast.
for (NewRollback newRollbackData : mNewRollbacks) { for (NewRollback newRollback: mNewRollbacks) {
for (int id : newRollbackData.packageSessionIds) { for (int id : newRollback.packageSessionIds) {
if (id == packageSessionId) { if (id == packageSessionId) {
return newRollbackData; return newRollback;
} }
} }
} }

View File

@@ -16,8 +16,8 @@
package com.android.server.rollback; package com.android.server.rollback;
import static com.android.server.rollback.RollbackData.rollbackStateFromString; import static com.android.server.rollback.Rollback.rollbackStateFromString;
import static com.android.server.rollback.RollbackData.rollbackStateToString; import static com.android.server.rollback.Rollback.rollbackStateToString;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.content.pm.VersionedPackage; 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<Rollback> loadRollbacks() {
List<RollbackData> rollbacks = new ArrayList<>(); List<Rollback> rollbacks = new ArrayList<>();
mRollbackDataDir.mkdirs(); mRollbackDataDir.mkdirs();
for (File rollbackDir : mRollbackDataDir.listFiles()) { for (File rollbackDir : mRollbackDataDir.listFiles()) {
if (rollbackDir.isDirectory()) { if (rollbackDir.isDirectory()) {
try { try {
rollbacks.add(loadRollbackData(rollbackDir)); rollbacks.add(loadRollback(rollbackDir));
} catch (IOException e) { } 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); 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. * backupDir assigned.
*/ */
RollbackData createNonStagedRollback(int rollbackId) { Rollback createNonStagedRollback(int rollbackId) {
File backupDir = new File(mRollbackDataDir, Integer.toString(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. * backupDir assigned.
*/ */
RollbackData createStagedRollback(int rollbackId, int stagedSessionId) { Rollback createStagedRollback(int rollbackId, int stagedSessionId) {
File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId)); 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 * For packages containing splits, this method should be called for each
* of the package's split apks in addition to the base apk. * 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 { throws IOException {
File sourceFile = new File(codePath); File sourceFile = new File(codePath);
File targetDir = new File(data.backupDir, packageName); File targetDir = new File(rollback.backupDir, packageName);
targetDir.mkdirs(); targetDir.mkdirs();
File targetFile = new File(targetDir, sourceFile.getName()); 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. * Returns the apk or apex files backed up for the given package.
* Includes the base apk and any splits. Returns null if none found. * Includes the base apk and any splits. Returns null if none found.
*/ */
static File[] getPackageCodePaths(RollbackData data, String packageName) { static File[] getPackageCodePaths(Rollback rollback, String packageName) {
File targetDir = new File(data.backupDir, packageName); File targetDir = new File(rollback.backupDir, packageName);
File[] files = targetDir.listFiles(); File[] files = targetDir.listFiles();
if (files == null || files.length == 0) { if (files == null || files.length == 0) {
return null; return null;
@@ -241,27 +241,27 @@ class RollbackStore {
* Deletes all backed up apks and apex files associated with the given * Deletes all backed up apks and apex files associated with the given
* rollback. * rollback.
*/ */
static void deletePackageCodePaths(RollbackData data) { static void deletePackageCodePaths(Rollback rollback) {
for (PackageRollbackInfo info : data.info.getPackages()) { for (PackageRollbackInfo info : rollback.info.getPackages()) {
File targetDir = new File(data.backupDir, info.getPackageName()); File targetDir = new File(rollback.backupDir, info.getPackageName());
removeFile(targetDir); 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 { try {
JSONObject dataJson = new JSONObject(); JSONObject dataJson = new JSONObject();
dataJson.put("info", rollbackInfoToJson(data.info)); dataJson.put("info", rollbackInfoToJson(rollback.info));
dataJson.put("timestamp", data.timestamp.toString()); dataJson.put("timestamp", rollback.timestamp.toString());
dataJson.put("stagedSessionId", data.stagedSessionId); dataJson.put("stagedSessionId", rollback.stagedSessionId);
dataJson.put("state", rollbackStateToString(data.state)); dataJson.put("state", rollbackStateToString(rollback.state));
dataJson.put("apkSessionId", data.apkSessionId); dataJson.put("apkSessionId", rollback.apkSessionId);
dataJson.put("restoreUserDataInProgress", data.restoreUserDataInProgress); dataJson.put("restoreUserDataInProgress", rollback.restoreUserDataInProgress);
PrintWriter pw = new PrintWriter(new File(data.backupDir, "rollback.json")); PrintWriter pw = new PrintWriter(new File(rollback.backupDir, "rollback.json"));
pw.println(dataJson.toString()); pw.println(dataJson.toString());
pw.close(); pw.close();
} catch (JSONException e) { } 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) { void deleteRollback(Rollback rollback) {
removeFile(data.backupDir); removeFile(rollback.backupDir);
} }
/** /**
* Reads the metadata for a rollback from the given directory. * Reads the metadata for a rollback from the given directory.
* @throws IOException in case of error reading the data. * @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 { try {
File rollbackJsonFile = new File(backupDir, "rollback.json"); File rollbackJsonFile = new File(backupDir, "rollback.json");
JSONObject dataJson = new JSONObject( JSONObject dataJson = new JSONObject(
IoUtils.readFileAsString(rollbackJsonFile.getAbsolutePath())); IoUtils.readFileAsString(rollbackJsonFile.getAbsolutePath()));
return new RollbackData( return new Rollback(
rollbackInfoFromJson(dataJson.getJSONObject("info")), rollbackInfoFromJson(dataJson.getJSONObject("info")),
backupDir, backupDir,
Instant.parse(dataJson.getString("timestamp")), Instant.parse(dataJson.getString("timestamp")),

View File

@@ -235,22 +235,22 @@ public class AppDataRollbackHelperTest {
wasRecentlyRestored.getPendingRestores().add( wasRecentlyRestored.getPendingRestores().add(
new RestoreInfo(73 /* userId */, 239 /* appId*/, "seInfo")); 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); 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); -1);
dataWithRecentRestore.info.getPackages().add(wasRecentlyRestored); 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); -1);
dataForDifferentUser.info.getPackages().add(ignoredInfo); 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(pendingRestore);
dataForRestore.info.getPackages().add(wasRecentlyRestored); dataForRestore.info.getPackages().add(wasRecentlyRestored);
Set<RollbackData> changed = helper.commitPendingBackupAndRestoreForUser(37, Set<Rollback> changed = helper.commitPendingBackupAndRestoreForUser(37,
Arrays.asList(dataWithPendingBackup, dataWithRecentRestore, dataForDifferentUser, Arrays.asList(dataWithPendingBackup, dataWithRecentRestore, dataForDifferentUser,
dataForRestore)); dataForRestore));
InOrder inOrder = Mockito.inOrder(installer); InOrder inOrder = Mockito.inOrder(installer);
@@ -265,7 +265,7 @@ public class AppDataRollbackHelperTest {
assertEquals(-1, pendingBackup.getPendingBackups().indexOf(37)); assertEquals(-1, pendingBackup.getPendingBackups().indexOf(37));
assertEquals(53, pendingBackup.getCeSnapshotInodes().get(37)); assertEquals(53, pendingBackup.getCeSnapshotInodes().get(37));
// Check that changed returns correct RollbackData. // Check that changed returns correct Rollback.
assertEquals(3, changed.size()); assertEquals(3, changed.size());
assertTrue(changed.contains(dataWithPendingBackup)); assertTrue(changed.contains(dataWithPendingBackup));
assertTrue(changed.contains(dataWithRecentRestore)); assertTrue(changed.contains(dataWithRecentRestore));