diff --git a/services/core/java/com/android/server/rollback/RollbackData.java b/services/core/java/com/android/server/rollback/RollbackData.java index 467bb28f57440..f45666574ed78 100644 --- a/services/core/java/com/android/server/rollback/RollbackData.java +++ b/services/core/java/com/android/server/rollback/RollbackData.java @@ -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; } } diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 7885abe17c5bd..438e47964c5e7 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -221,9 +221,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { List 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 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; } } diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java index ff516902a5b35..1e45ba2e495cf 100644 --- a/services/core/java/com/android/server/rollback/RollbackStore.java +++ b/services/core/java/com/android/server/rollback/RollbackStore.java @@ -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; diff --git a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java index f1e6bc25dabfb..43e3eb0193b1f 100644 --- a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java @@ -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));