summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author JW Wang <wangchun@google.com> 2020-10-09 00:18:54 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-10-09 00:18:54 +0000
commit2ad34ca5e3f78097f6143823d74fd8a1235b6e1b (patch)
treeacf2ea6efa11f1749ec7d1306ce22467b5377899
parent93b2f301cfd921d99ad6c48ee2f3ec6ae6911526 (diff)
parent0becf9a6c6837a0a774ed01a3bf581ac80366f99 (diff)
Merge changes from topic "168268518"
* changes: Now #mStagedSessions stores only parent sessions (4/n) Move #checkNonOverlappingWithStagedSessions into pre-reboot verification (2/n) Iterate over parent sessions (1/n)
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java3
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java9
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java71
3 files changed, 37 insertions, 46 deletions
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 1104d4e3e13c..2e1543b17320 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -746,9 +746,6 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
synchronized (mSessions) {
mSessions.put(sessionId, session);
}
- if (params.isStaged) {
- mStagingManager.createSession(session);
- }
mCallbacks.notifySessionCreated(session.sessionId, session.userId);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 37fa9a2e19db..649cafb1cb06 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1602,13 +1602,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
validateApkInstallLocked();
}
}
- }
-
- if (params.isStaged) {
- mStagingManager.checkNonOverlappingWithStagedSessions(this);
- }
-
- synchronized (mLock) {
if (mDestroyed) {
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
"Session destroyed");
@@ -2311,7 +2304,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return (params.installFlags & PackageManager.INSTALL_APEX) != 0;
}
- private boolean sessionContains(Predicate<PackageInstallerSession> filter) {
+ boolean sessionContains(Predicate<PackageInstallerSession> filter) {
if (!isMultiPackage()) {
return filter.test(this);
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 2db72784ecb5..3bad3cb1d372 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -709,6 +709,8 @@ public class StagingManager {
}
void commitSession(@NonNull PackageInstallerSession session) {
+ // Store this parent session which will be used to check overlapping later
+ createSession(session);
mPreRebootVerificationHandler.startPreRebootVerification(session);
}
@@ -738,14 +740,16 @@ public class StagingManager {
* </ul>
* @throws PackageManagerException if session fails the check
*/
- void checkNonOverlappingWithStagedSessions(@NonNull PackageInstallerSession session)
+ private void checkNonOverlappingWithStagedSessions(@NonNull PackageInstallerSession session)
throws PackageManagerException {
if (session.isMultiPackage()) {
// We cannot say a parent session overlaps until we process its children
return;
}
- if (session.getPackageName() == null) {
- throw new PackageManagerException(PackageManager.INSTALL_FAILED_INVALID_APK,
+
+ String packageName = session.getPackageName();
+ if (packageName == null) {
+ throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Cannot stage session " + session.sessionId + " with package name null");
}
@@ -757,40 +761,26 @@ public class StagingManager {
synchronized (mStagedSessions) {
for (int i = 0; i < mStagedSessions.size(); i++) {
final PackageInstallerSession stagedSession = mStagedSessions.valueAt(i);
- if (!stagedSession.isCommitted() || stagedSession.isStagedAndInTerminalState()
+ if (stagedSession.hasParentSessionId() || !stagedSession.isCommitted()
+ || stagedSession.isStagedAndInTerminalState()
|| stagedSession.isDestroyed()) {
continue;
}
- if (stagedSession.isMultiPackage()) {
- // This active parent staged session is useless as it doesn't have a package
- // name and the session we are checking is not a parent session either.
- continue;
- }
- // Check if stagedSession has an active parent session or not
- if (stagedSession.hasParentSessionId()) {
- final int parentId = stagedSession.getParentSessionId();
- final PackageInstallerSession parentSession = mStagedSessions.get(parentId);
- if (parentSession == null || parentSession.isStagedAndInTerminalState()
- || parentSession.isDestroyed()) {
- // Parent session has been abandoned or terminated already
- continue;
- }
- }
- // From here on, stagedSession is a non-parent active staged session
+ // From here on, stagedSession is a parent active staged session
// Check if session is one of the active sessions
- if (session.sessionId == stagedSession.sessionId) {
+ if (getSessionIdForParentOrSelf(session) == stagedSession.sessionId) {
Slog.w(TAG, "Session " + session.sessionId + " is already staged");
continue;
}
// New session cannot have same package name as one of the active sessions
- if (session.getPackageName().equals(stagedSession.getPackageName())) {
+ 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 PackageInstallerSession root = getParentSessionOrSelf(stagedSession);
+ final PackageInstallerSession 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
@@ -804,7 +794,7 @@ public class StagingManager {
+ "blocking rollback session: " + session.sessionId);
} else {
throw new PackageManagerException(
- PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS,
+ SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Package: " + session.getPackageName() + " in session: "
+ session.sessionId + " has been staged already by session:"
+ " " + stagedSession.sessionId, null);
@@ -814,17 +804,16 @@ public class StagingManager {
// Staging multiple root sessions is not allowed if device doesn't support
// checkpoint. If session and stagedSession do not have common ancestor, they are
// from two different root sessions.
- if (!supportsCheckpoint && getSessionIdForParentOrSelf(session)
- != getSessionIdForParentOrSelf(stagedSession)) {
+ if (!supportsCheckpoint) {
throw new PackageManagerException(
- PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS,
+ SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Cannot stage multiple sessions without checkpoint support", null);
}
}
}
}
- void createSession(@NonNull PackageInstallerSession sessionInfo) {
+ private void createSession(@NonNull PackageInstallerSession sessionInfo) {
synchronized (mStagedSessions) {
mStagedSessions.append(sessionInfo.sessionId, sessionInfo);
}
@@ -900,16 +889,15 @@ public class StagingManager {
}
void restoreSession(@NonNull PackageInstallerSession session, boolean isDeviceUpgrading) {
- PackageInstallerSession sessionToResume = session;
- synchronized (mStagedSessions) {
- mStagedSessions.append(session.sessionId, session);
- if (session.hasParentSessionId()) {
- // Only parent sessions can be restored
- return;
- }
+ if (session.hasParentSessionId()) {
+ // Only parent sessions can be restored
+ return;
}
+ // Store this parent session which will be used to check overlapping later
+ createSession(session);
// The preconditions used during pre-reboot verification might have changed when device
// is upgrading. Updated staged sessions to activation failed before we resume the session.
+ PackageInstallerSession sessionToResume = session;
if (isDeviceUpgrading && !sessionToResume.isStagedAndInTerminalState()) {
sessionToResume.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
"Build fingerprint has changed");
@@ -1160,6 +1148,19 @@ public class StagingManager {
* See {@link PreRebootVerificationHandler} to see all nodes of pre reboot verification
*/
private void handlePreRebootVerification_Start(@NonNull PackageInstallerSession session) {
+ try {
+ if (session.isMultiPackage()) {
+ for (PackageInstallerSession s : session.getChildSessions()) {
+ checkNonOverlappingWithStagedSessions(s);
+ }
+ } else {
+ checkNonOverlappingWithStagedSessions(session);
+ }
+ } catch (PackageManagerException e) {
+ onPreRebootVerificationFailure(session, e.error, e.getMessage());
+ return;
+ }
+
int rollbackId = -1;
if ((session.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
// If rollback is enabled for this session, we call through to the RollbackManager