Merge changes I93d6af48,Ib53a54a3,I13f2649b,Ia4d800d7

* changes:
  Add isAvailable flag to RollbackData.
  Don't restore installer when rolling back APEX
  MATCH_APEX when getting installed package version.
  Wire up info for staged/apex rollbacks.
This commit is contained in:
Richard Uhler
2019-02-06 09:07:03 +00:00
committed by Android (Google) Code Review
4 changed files with 57 additions and 21 deletions

View File

@@ -55,6 +55,14 @@ class RollbackData {
*/
public int stagedSessionId;
/**
* A flag to indicate whether the rollback should be considered available
* for use. This will always be true for rollbacks of non-staged sessions.
* For rollbacks of staged sessions, this is not set to true until after
* the staged session has been applied.
*/
public boolean isAvailable;
/**
* Whether this Rollback is currently in progress. This field is true from the point
* we commit a {@code PackageInstaller} session containing these packages to the point the
@@ -63,9 +71,17 @@ class RollbackData {
// NOTE: All accesses to this field are from the RollbackManager handler thread.
public boolean inProgress = false;
RollbackData(int rollbackId, File backupDir, int stagedSessionId) {
RollbackData(int rollbackId, File backupDir, int stagedSessionId, boolean isAvailable) {
this.rollbackId = rollbackId;
this.backupDir = backupDir;
this.stagedSessionId = stagedSessionId;
this.isAvailable = isAvailable;
}
/**
* Whether the rollback is for rollback of a staged install.
*/
public boolean isStaged() {
return stagedSessionId != -1;
}
}

View File

@@ -221,9 +221,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
List<RollbackInfo> rollbacks = new ArrayList<>();
for (int i = 0; i < mAvailableRollbacks.size(); ++i) {
RollbackData data = mAvailableRollbacks.get(i);
// TODO: Pass the correct value for isStaged instead of
// assuming always false.
rollbacks.add(new RollbackInfo(data.rollbackId, data.packages, false));
if (data.isAvailable) {
rollbacks.add(new RollbackInfo(data.rollbackId,
data.packages, data.isStaged()));
}
}
return new ParceledListSlice<>(rollbacks);
}
@@ -323,20 +324,35 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
parentParams.setAllowDowngrade(true);
parentParams.setMultiPackage();
if (data.isStaged()) {
parentParams.setStaged();
}
int parentSessionId = packageInstaller.createSession(parentParams);
PackageInstaller.Session parentSession = packageInstaller.openSession(parentSessionId);
for (PackageRollbackInfo info : data.packages) {
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
String installerPackageName = pm.getInstallerPackageName(info.getPackageName());
if (installerPackageName == null) {
sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE,
"Cannot find installer package");
return;
// TODO: We can't get the installerPackageName for apex
// (b/123920130). Is it okay to ignore the installer package
// for apex?
if (!info.isApex()) {
String installerPackageName = pm.getInstallerPackageName(info.getPackageName());
if (installerPackageName == null) {
sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE,
"Cannot find installer package");
return;
}
params.setInstallerPackageName(installerPackageName);
}
params.setInstallerPackageName(installerPackageName);
params.setAllowDowngrade(true);
if (data.isStaged()) {
params.setStaged();
}
if (info.isApex()) {
params.setInstallAsApex();
}
int sessionId = packageInstaller.createSession(params);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
@@ -376,11 +392,9 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
return;
}
// TODO: Set the correct values for isStaged and
// committedSessionId.
addRecentlyExecutedRollback(new RollbackInfo(
data.rollbackId, data.packages, false, causePackages,
PackageInstaller.SessionInfo.INVALID_ID));
data.rollbackId, data.packages, data.isStaged(),
causePackages, parentSessionId));
sendSuccess(statusReceiver);
Intent broadcast = new Intent(Intent.ACTION_ROLLBACK_COMMITTED);
@@ -644,6 +658,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
Iterator<RollbackData> iter = mAvailableRollbacks.iterator();
while (iter.hasNext()) {
RollbackData data = iter.next();
if (!data.isAvailable) {
continue;
}
if (!now.isBefore(data.timestamp.plusMillis(ROLLBACK_LIFETIME_DURATION_MILLIS))) {
iter.remove();
mRollbackStore.deleteAvailableRollback(data);
@@ -918,7 +936,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
PackageManager pm = mContext.getPackageManager();
PackageInfo pkgInfo = null;
try {
pkgInfo = pm.getPackageInfo(packageName, 0);
pkgInfo = pm.getPackageInfo(packageName, PackageManager.MATCH_APEX);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
@@ -1053,7 +1071,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
ensureRollbackDataLoadedLocked();
for (int i = 0; i < mAvailableRollbacks.size(); ++i) {
RollbackData data = mAvailableRollbacks.get(i);
if (getPackageRollbackInfo(data, packageName) != null) {
if (data.isAvailable && getPackageRollbackInfo(data, packageName) != null) {
return data;
}
}
@@ -1072,7 +1090,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
ensureRollbackDataLoadedLocked();
for (int i = 0; i < mAvailableRollbacks.size(); ++i) {
RollbackData data = mAvailableRollbacks.get(i);
if (data.rollbackId == rollbackId) {
if (data.isAvailable && data.rollbackId == rollbackId) {
return data;
}
}

View File

@@ -201,13 +201,13 @@ class RollbackStore {
*/
RollbackData createAvailableRollback(int rollbackId) throws IOException {
File backupDir = new File(mAvailableRollbacksDir, Integer.toString(rollbackId));
return new RollbackData(rollbackId, backupDir, -1);
return new RollbackData(rollbackId, backupDir, -1, true);
}
RollbackData createPendingStagedRollback(int rollbackId, int stagedSessionId)
throws IOException {
File backupDir = new File(mAvailableRollbacksDir, Integer.toString(rollbackId));
return new RollbackData(rollbackId, backupDir, stagedSessionId);
return new RollbackData(rollbackId, backupDir, stagedSessionId, false);
}
/**
@@ -247,6 +247,7 @@ class RollbackStore {
dataJson.put("packages", toJson(data.packages));
dataJson.put("timestamp", data.timestamp.toString());
dataJson.put("stagedSessionId", data.stagedSessionId);
dataJson.put("isAvailable", data.isAvailable);
PrintWriter pw = new PrintWriter(new File(data.backupDir, "rollback.json"));
pw.println(dataJson.toString());
@@ -307,8 +308,9 @@ class RollbackStore {
int rollbackId = dataJson.getInt("rollbackId");
int stagedSessionId = dataJson.getInt("stagedSessionId");
boolean isAvailable = dataJson.getBoolean("isAvailable");
RollbackData data = new RollbackData(rollbackId, backupDir,
stagedSessionId);
stagedSessionId, isAvailable);
data.packages.addAll(packageRollbackInfosFromJson(dataJson.getJSONArray("packages")));
data.timestamp = Instant.parse(dataJson.getString("timestamp"));
return data;

View File

@@ -80,7 +80,7 @@ public class AppDataRollbackHelperTest {
}
private static RollbackData createInProgressRollbackData(String packageName) {
RollbackData data = new RollbackData(1, new File("/does/not/exist"), -1);
RollbackData data = new RollbackData(1, new File("/does/not/exist"), -1, true);
data.packages.add(new PackageRollbackInfo(
new VersionedPackage(packageName, 1), new VersionedPackage(packageName, 1),
new IntArray(), new ArrayList<>(), false));