Abandon other staged sessions when a rollback is staged.

This change causes all staged sessions that are not rollbacks to be
abandoned (failed) when a rollback is staged.

This will ensure that an SDK extension level dependency is not violated
if a rollback causes the extension level to drop while at the same time
an app is installed that depends on the higher extension level.

Other rollbacks are not failed so that multiple rollbacks can be staged
together.

Bug: 163734200
Test: atest RollbackManagerHostTest
Change-Id: Iffb50d2a05f6ab0b6691fc84ffc273c2faecb88b
This commit is contained in:
Oli Lan
2021-06-29 17:54:08 +01:00
parent 840870e7cb
commit c1e8f1f823

View File

@@ -737,31 +737,31 @@ public class StagingManager {
continue;
}
// New session cannot have same package name as one of the active sessions
if (stagedSession.sessionContains(s -> s.getPackageName().equals(packageName))) {
if (isRollback) {
// If the new session is a rollback, then it gets priority. The existing
// session is failed to unblock rollback.
final StagedSession root = stagedSession;
if (!ensureActiveApexSessionIsAborted(root)) {
Slog.e(TAG, "Failed to abort apex session " + root.sessionId());
// Safe to ignore active apex session abort failure since session
// will be marked failed on next step and staging directory for session
// will be deleted.
}
root.setSessionFailed(
SessionInfo.STAGED_SESSION_CONFLICT,
"Session was blocking rollback session: " + session.sessionId());
Slog.i(TAG, "Session " + root.sessionId() + " is marked failed due to "
+ "blocking rollback session: " + session.sessionId());
} else {
throw new PackageManagerException(
SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Package: " + session.getPackageName() + " in session: "
+ session.sessionId()
+ " has been staged already by session: "
+ stagedSession.sessionId(), null);
if (isRollback && !isRollback(stagedSession)) {
// If the new session is a rollback, then it gets priority. The existing
// session is failed to reduce risk and avoid an SDK extension dependency
// violation.
final StagedSession root = stagedSession;
if (!ensureActiveApexSessionIsAborted(root)) {
Slog.e(TAG, "Failed to abort apex session " + root.sessionId());
// Safe to ignore active apex session abort failure since session
// will be marked failed on next step and staging directory for session
// will be deleted.
}
root.setSessionFailed(
SessionInfo.STAGED_SESSION_CONFLICT,
"Session was failed by rollback session: " + session.sessionId());
Slog.i(TAG, "Session " + root.sessionId() + " is marked failed due to "
+ "rollback session: " + session.sessionId());
} else if (stagedSession.sessionContains(
s -> s.getPackageName().equals(packageName))) {
// New session cannot have same package name as one of the active sessions
throw new PackageManagerException(
SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Package: " + session.getPackageName() + " in session: "
+ session.sessionId()
+ " has been staged already by session: "
+ stagedSession.sessionId(), null);
}
// Staging multiple root sessions is not allowed if device doesn't support