diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 2a189c0ebb0cd..60737bf77c488 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -169,6 +169,7 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Predicate; public class PackageInstallerSession extends IPackageInstallerSession.Stub { private static final String TAG = "PackageInstallerSession"; @@ -689,7 +690,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { stagedSessionErrorMessage != null ? stagedSessionErrorMessage : ""; if (isDataLoaderInstallation()) { - if (isApexInstallation()) { + if (isApexSession()) { throw new IllegalArgumentException( "DataLoader installation of APEX modules is not allowed."); } @@ -1576,7 +1577,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { return false; } - if (isApexInstallation()) { + if (isApexSession()) { validateApexInstallLocked(); } else { validateApkInstallLocked(); @@ -1733,7 +1734,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { try { sealLocked(); - if (isApexInstallation()) { + if (isApexSession()) { // APEX installations rely on certain fields to be populated after reboot. // E.g. mPackageName. validateApexInstallLocked(); @@ -1809,7 +1810,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { return; } - if (isApexInstallation()) { + if (isApexSession()) { destroyInternal(); dispatchSessionFinished(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, "APEX packages can only be installed using staged sessions.", null); @@ -1986,7 +1987,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // TODO(b/136257624): Some logic in this if block probably belongs in // makeInstallParams(). - if (!params.isMultiPackage && !isApexInstallation()) { + if (!params.isMultiPackage && !isApexSession()) { Objects.requireNonNull(mPackageName); Objects.requireNonNull(mSigningDetails); Objects.requireNonNull(mResolvedBaseFile); @@ -2215,10 +2216,34 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { /** * Returns true if the session is installing an APEX package. */ - private boolean isApexInstallation() { + boolean isApexSession() { return (params.installFlags & PackageManager.INSTALL_APEX) != 0; } + private boolean sessionContains(Predicate filter) { + if (!isMultiPackage()) { + return filter.test(this); + } + final List childSessions; + synchronized (mLock) { + childSessions = getChildSessionsLocked(); + } + for (PackageInstallerSession child: childSessions) { + if (filter.test(child)) { + return true; + } + } + return false; + } + + boolean containsApexSession() { + return sessionContains((s) -> s.isApexSession()); + } + + boolean containsApkSession() { + return sessionContains((s) -> !s.isApexSession()); + } + /** * Validate apex install. *

diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index d4132136c2265..35c26d6cd54ee 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -86,7 +86,6 @@ import java.util.List; import java.util.Set; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import java.util.function.Predicate; import java.util.function.Supplier; /** @@ -226,7 +225,7 @@ public class StagingManager { final IntArray childSessionIds = new IntArray(); if (session.isMultiPackage()) { for (PackageInstallerSession s : session.getChildSessions()) { - if (isApexSession(s)) { + if (s.isApexSession()) { childSessionIds.add(s.sessionId); } } @@ -329,31 +328,6 @@ public class StagingManager { } } - private static boolean isApexSession(@NonNull PackageInstallerSession session) { - return (session.params.installFlags & PackageManager.INSTALL_APEX) != 0; - } - - private boolean sessionContains(@NonNull PackageInstallerSession session, - Predicate filter) { - if (!session.isMultiPackage()) { - return filter.test(session); - } - for (PackageInstallerSession s : session.getChildSessions()) { - if (filter.test(s)) { - return true; - } - } - return false; - } - - private boolean sessionContainsApex(@NonNull PackageInstallerSession session) { - return sessionContains(session, (s) -> isApexSession(s)); - } - - private boolean sessionContainsApk(@NonNull PackageInstallerSession session) { - return sessionContains(session, (s) -> !isApexSession(s)); - } - // Reverts apex sessions and user data (if checkpoint is supported). Also reboots the device. private void abortCheckpoint(int sessionId, String errorMsg) { String failureReason = "Failed to install sessionId: " + sessionId + " Error: " + errorMsg; @@ -400,7 +374,7 @@ public class StagingManager { List apexSessions = new ArrayList<>(); if (session.isMultiPackage()) { for (PackageInstallerSession s : session.getChildSessions()) { - if (sessionContainsApex(s)) { + if (s.containsApexSession()) { apexSessions.add(s); } } @@ -521,7 +495,7 @@ public class StagingManager { private void resumeSession(@NonNull PackageInstallerSession session) { Slog.d(TAG, "Resuming session " + session.sessionId); - final boolean hasApex = sessionContainsApex(session); + final boolean hasApex = session.containsApexSession(); ApexSessionInfo apexSessionInfo = null; if (hasApex) { // Check with apexservice whether the apex packages have been activated. @@ -740,7 +714,7 @@ public class StagingManager { @Nullable private PackageInstallerSession extractApksInSession(PackageInstallerSession session) throws PackageManagerException { - if (!session.isMultiPackage() && !isApexSession(session)) { + if (!session.isMultiPackage() && !session.isApexSession()) { return createAndWriteApkSession(session); } else if (session.isMultiPackage()) { // For multi-package staged sessions containing APKs, we identify which child sessions @@ -749,7 +723,7 @@ public class StagingManager { // sessions will be installed atomically. final List childSessions = new ArrayList<>(); for (PackageInstallerSession s : session.getChildSessions()) { - if (!isApexSession(s)) { + if (!s.isApexSession()) { childSessions.add(s); } } @@ -798,7 +772,7 @@ public class StagingManager { } final Set apkNames = new ArraySet<>(); for (PackageInstallerSession s : session.getChildSessions()) { - if (!isApexSession(s)) { + if (!s.isApexSession()) { apkNames.add(s.getPackageName()); } } @@ -1020,7 +994,7 @@ public class StagingManager { * @return returns true if it is ensured that there is no active apex session, otherwise false */ private boolean ensureActiveApexSessionIsAborted(PackageInstallerSession session) { - if (!sessionContainsApex(session)) { + if (!session.containsApexSession()) { return true; } final ApexSessionInfo apexSession = mApexManager.getStagedSessionInfo(session.sessionId); @@ -1342,7 +1316,7 @@ public class StagingManager { */ private void handlePreRebootVerification_Apex( @NonNull PackageInstallerSession session, int rollbackId) { - final boolean hasApex = sessionContainsApex(session); + final boolean hasApex = session.containsApexSession(); // APEX checks. For single-package sessions, check if they contain an APEX. For // multi-package sessions, find all the child sessions that contain an APEX. @@ -1372,7 +1346,7 @@ public class StagingManager { * {@link #notifyPreRebootVerification_Apk_Complete} */ private void handlePreRebootVerification_Apk(@NonNull PackageInstallerSession session) { - if (!sessionContainsApk(session)) { + if (!session.containsApkSession()) { notifyPreRebootVerification_Apk_Complete(session); return; } @@ -1421,7 +1395,7 @@ public class StagingManager { Slog.d(TAG, "Marking session " + session.sessionId + " as ready"); session.setStagedSessionReady(); if (session.isStagedSessionReady()) { - final boolean hasApex = sessionContainsApex(session); + final boolean hasApex = session.containsApexSession(); if (hasApex) { try { mApexManager.markStagedSessionReady(session.sessionId);