From da00497f07e57e8affef036f00a79b7bdc0ebaed Mon Sep 17 00:00:00 2001 From: Mohammad Samiul Islam Date: Wed, 9 Oct 2019 11:29:26 +0100 Subject: Allow staging multiple session with non-overlapping packages (apk-only) Bug: 141843321 Test: atest StagedInstallTest#testAllowNonOverlappingMultipleStagedInstall_BothSinglePackage_Apk Test: atest StagedInstallTest#testFailOverlappingMultipleStagedInstall_BothSinglePackage_Apk Test: atest StagedInstallTest#testFailOverlappingMultipleStagedInstall_BothSinglePackage_Apex Test: atest StagedInstallTest#testAllowNonOverlappingMultipleStagedInstall_MultiPackageSinglePackage Test: atest StagedInstallTest#testFailOverlappingMultipleStagedInstall_BothMultiPackage Test: atest StagedInstallTest#testMultipleStagedInstall_ApkOnly Test: atest RollbackManagerHostTest#testApkOnlyMultipleStagedRollback Test: atest RollbackManagerHostTest#testApkOnlyMultipleStagedPartialRollback Test: atest StagedInstallTest Change-Id: Iad2e35b50fd22e207e3ad91b48a767827d8e8926 --- core/java/android/content/pm/PackageInstaller.java | 78 ++++++++++++++-------- core/java/android/content/pm/PackageManager.java | 2 +- 2 files changed, 53 insertions(+), 27 deletions(-) (limited to 'core/java/android') diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index edc66c58b197..0c529798622e 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -68,6 +68,7 @@ import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.Executor; +import java.util.stream.Collectors; /** * Offers the ability to install, upgrade, and remove applications on the @@ -479,35 +480,30 @@ public class PackageInstaller { } /** - * Returns an active staged session, or {@code null} if there is none. + * Returns first active staged session, or {@code null} if there is none. * - *

Staged session is active iff: - *

+ *

For more information on what sessions are considered active see + * {@link SessionInfo#isStagedSessionActive()}. * - *

In case of a multi-apk session, reasoning above is applied to the parent session, since - * that is the one that should been {@link Session#commit committed}. + * @deprecated Use {@link #getActiveStagedSessions} as there can be more than one active staged + * session */ + @Deprecated public @Nullable SessionInfo getActiveStagedSession() { - final List stagedSessions = getStagedSessions(); - for (SessionInfo s : stagedSessions) { - if (s.isStagedSessionApplied() || s.isStagedSessionFailed()) { - // Finalized session. - continue; - } - if (s.getParentSessionId() != SessionInfo.INVALID_ID) { - // Child session. - continue; - } - if (s.isCommitted()) { - return s; - } - } - return null; + List activeSessions = getActiveStagedSessions(); + return activeSessions.isEmpty() ? null : activeSessions.get(0); + } + + /** + * Returns list of active staged sessions. Returns empty list if there is none. + * + *

For more information on what sessions are considered active see + * * {@link SessionInfo#isStagedSessionActive()}. + */ + public @NonNull List getActiveStagedSessions() { + return getStagedSessions().stream() + .filter(s -> s.isStagedSessionActive()) + .collect(Collectors.toList()); } /** @@ -2227,12 +2223,35 @@ public class PackageInstaller { } /** - * Returns true if this session is a staged session which will be applied at next reboot. + * Returns true if this session is a staged session. */ public boolean isStaged() { return isStaged; } + /** + * Returns {@code true} if this session is an active staged session. + * + * We consider a session active if it has been committed and it is either pending + * verification, or will be applied at next reboot. + * + *

Staged session is active iff: + *

+ * + *

In case of a multi-package session, reasoning above is applied to the parent session, + * since that is the one that should have been {@link Session#commit committed}. + */ + public boolean isStagedSessionActive() { + return isStaged && isCommitted && !isStagedSessionApplied && !isStagedSessionFailed + && !hasParentSessionId(); + } + /** * Returns the parent multi-package session ID if this session belongs to one, * {@link #INVALID_ID} otherwise. @@ -2241,6 +2260,13 @@ public class PackageInstaller { return parentSessionId; } + /** + * Returns true if session has a valid parent session, otherwise false. + */ + public boolean hasParentSessionId() { + return parentSessionId != INVALID_ID; + } + /** * Returns the set of session IDs that will be committed when this session is commited if * this session is a multi-package session. diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index c56c3076c3be..bbfdf910a9da 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1435,7 +1435,7 @@ public abstract class PackageManager { /** * Installation failed return code: a new staged session was attempted to be committed while - * there is already one in-progress. + * there is already one in-progress or new session has package that is already staged. * * @hide */ -- cgit v1.2.3