Loading services/core/java/com/android/server/pm/PackageInstallerService.java +4 −1 Original line number Diff line number Diff line Loading @@ -1650,7 +1650,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements public void onSessionChanged(PackageInstallerSession session) { session.markUpdated(); mSettingsWriteRequest.schedule(); if (mOkToSendBroadcasts && !session.isDestroyed()) { // TODO(b/210359798): Remove the session.isStaged() check. Some apps assume this // broadcast is sent by only staged sessions and call isStagedSessionApplied() without // checking if it is a staged session or not and cause exception. if (mOkToSendBroadcasts && !session.isDestroyed() && session.isStaged()) { // we don't scrub the data here as this is sent only to the installer several // privileged system packages sendSessionUpdatedBroadcast( Loading services/core/java/com/android/server/pm/PackageInstallerSession.java +83 −68 Original line number Diff line number Diff line Loading @@ -182,6 +182,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Predicate; Loading Loading @@ -549,18 +550,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { /** * Installs apks of staged session while skipping the verification process for a committed * and ready session. * * @return a CompletableFuture that will be completed when installation completes. */ @Override public void installSession(IntentSender statusReceiver) { public CompletableFuture<Void> installSession() { assertCallerIsOwnerOrRootOrSystem(); assertNotChild("StagedSession#installSession"); Preconditions.checkArgument(isCommitted() && isSessionReady()); // Since staged sessions are installed during boot, the original reference to status // receiver from the owner has already been lost. We can safely replace it with a // status receiver from the system without effecting the flow. updateRemoteStatusReceiver(statusReceiver); install(); return install(); } private void updateRemoteStatusReceiver(IntentSender remoteStatusReceiver) { Loading Loading @@ -1694,15 +1692,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } if (isMultiPackage()) { synchronized (mLock) { final IntentSender childIntentSender = new ChildStatusIntentReceiver(mChildSessions.clone(), statusReceiver) .getIntentSender(); boolean sealFailed = false; for (int i = mChildSessions.size() - 1; i >= 0; --i) { // seal all children, regardless if any of them fail; we'll throw/return // as appropriate once all children have been processed if (!mChildSessions.valueAt(i) .markAsSealed(childIntentSender, forTransfer)) { if (!mChildSessions.valueAt(i).markAsSealed(null, forTransfer)) { sealFailed = true; } } Loading Loading @@ -1890,8 +1884,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * This method may be called multiple times to update the status receiver validate caller * permissions. */ private boolean markAsSealed(@NonNull IntentSender statusReceiver, boolean forTransfer) { Objects.requireNonNull(statusReceiver); private boolean markAsSealed(@Nullable IntentSender statusReceiver, boolean forTransfer) { Preconditions.checkState(statusReceiver != null || hasParentSessionId(), "statusReceiver can't be null for the root session"); assertCallerIsOwnerOrRoot(); synchronized (mLock) { Loading Loading @@ -2191,7 +2186,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } @WorkerThread private static boolean checkUserActionRequirement(PackageInstallerSession session) { private static boolean checkUserActionRequirement( PackageInstallerSession session, IntentSender target) { if (session.isMultiPackage()) { return false; } Loading @@ -2200,7 +2196,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // TODO(b/159331446): Move this to makeSessionActiveForInstall and update javadoc userActionRequirement = session.computeUserActionRequirement(); if (userActionRequirement == USER_ACTION_REQUIRED) { session.sendPendingUserActionIntent(); session.sendPendingUserActionIntent(target); return true; } Loading @@ -2212,7 +2208,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { if (validatedTargetSdk != INVALID_TARGET_SDK_VERSION && validatedTargetSdk < Build.VERSION_CODES.Q) { session.sendPendingUserActionIntent(); session.sendPendingUserActionIntent(target); return true; } Loading @@ -2221,7 +2217,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { session.getInstallerPackageName(), session.getPackageName())) { // Fall back to the non-silent update if a repeated installation is invoked // within the throttle time. session.sendPendingUserActionIntent(); session.sendPendingUserActionIntent(target); return true; } session.mSilentUpdatePolicy.track(session.getInstallerPackageName(), Loading @@ -2241,7 +2237,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private boolean sendPendingUserActionIntentIfNeeded() { assertNotChild("PackageInstallerSession#sendPendingUserActionIntentIfNeeded"); return sessionContains(PackageInstallerSession::checkUserActionRequirement); final IntentSender statusReceiver = getRemoteStatusReceiver(); return sessionContains(s -> checkUserActionRequirement(s, statusReceiver)); } @WorkerThread Loading Loading @@ -2439,53 +2436,69 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { }); } private void install() { try { installNonStaged(); } catch (PackageManagerException e) { final String completeMsg = ExceptionUtils.getCompleteMessage(e); onSessionInstallationFailure(e.error, completeMsg); /** * Stages installs and do cleanup accordingly depending on whether the installation is * successful or not. * * @return a future that will be completed when the whole process is completed. */ private CompletableFuture<Void> install() { return installNonStaged().whenComplete((r, t) -> { if (t == null) { setSessionApplied(); dispatchSessionFinished(INSTALL_SUCCEEDED, "Session installed", null); maybeFinishChildSessions(INSTALL_SUCCEEDED, "Session installed"); } else { PackageManagerException e = (PackageManagerException) t.getCause(); setSessionFailed(SessionInfo.SESSION_ACTIVATION_FAILED, PackageManager.installStatusToString(e.error, e.getMessage())); dispatchSessionFinished(e.error, e.getMessage(), null); maybeFinishChildSessions(e.error, e.getMessage()); } }); } private void installNonStaged() throws PackageManagerException { final InstallParams installingSession = makeInstallParams(); if (installingSession == null) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session should contain at least one apk session for installation"); } /** * Stages sessions (including child sessions if any) for install. * * @return a future that will be completed when the whole session is completed (could be * success or failure). */ private CompletableFuture<Void> installNonStaged() { try { List<CompletableFuture<Void>> futures = new ArrayList<>(); CompletableFuture<Void> future = new CompletableFuture<>(); futures.add(future); final InstallParams installingSession = makeInstallParams(future); if (isMultiPackage()) { final List<PackageInstallerSession> childSessions = getChildSessions(); List<InstallParams> installingChildSessions = new ArrayList<>(childSessions.size()); boolean success = true; PackageManagerException failure = null; for (int i = 0; i < childSessions.size(); ++i) { final PackageInstallerSession session = childSessions.get(i); try { final InstallParams installingChildSession = session.makeInstallParams(); future = new CompletableFuture<>(); futures.add(future); final InstallParams installingChildSession = session.makeInstallParams(future); if (installingChildSession != null) { installingChildSessions.add(installingChildSession); } } catch (PackageManagerException e) { failure = e; success = false; } } if (!success) { sendOnPackageInstalled(mContext, getRemoteStatusReceiver(), sessionId, isInstallerDeviceOwnerOrAffiliatedProfileOwner(), userId, null, failure.error, failure.getLocalizedMessage(), null); return; } if (!installingChildSessions.isEmpty()) { installingSession.installStage(installingChildSessions); } else { } } else if (installingSession != null) { installingSession.installStage(); } CompletableFuture<Void>[] arr = new CompletableFuture[futures.size()]; return CompletableFuture.allOf(futures.toArray(arr)); } catch (PackageManagerException e) { CompletableFuture<Void> future = new CompletableFuture<>(); future.completeExceptionally(e); return future; } } private void sendPendingUserActionIntent() { private void sendPendingUserActionIntent(IntentSender target) { // User needs to confirm installation; // give installer an intent they can use to involve // user. Loading @@ -2493,7 +2506,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { intent.setPackage(mPm.getPackageInstallerPackageName()); intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); sendOnUserActionRequired(mContext, getRemoteStatusReceiver(), sessionId, intent); sendOnUserActionRequired(mContext, target, sessionId, intent); // Commit was keeping session marked as active until now; release // that extra refcount so session appears idle. Loading Loading @@ -2525,9 +2538,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { /** * Stages this session for install and returns a * {@link InstallParams} representing this new staged state. * * @param future a future that will be completed when this session is completed. */ @Nullable private InstallParams makeInstallParams() private InstallParams makeInstallParams(CompletableFuture<Void> future) throws PackageManagerException { synchronized (mLock) { if (mDestroyed) { Loading @@ -2540,11 +2555,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } // Do not try to install staged apex session. Parent session will have at least one apk // session. if (!isMultiPackage() && isApexSession() && params.isStaged) { dispatchSessionFinished(INSTALL_SUCCEEDED, "Apex package should have been installed by apexd", null); if (isMultiPackage()) { // Always treat parent session as success for it has nothing to install future.complete(null); } else if (isApexSession() && params.isStaged) { // Staged apex sessions have been handled by apexd future.complete(null); return null; } Loading @@ -2557,12 +2573,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @Override public void onPackageInstalled(String basePackageName, int returnCode, String msg, Bundle extras) { if (!isStaged()) { // We've reached point of no return; call into PMS to install the stage. // Regardless of success or failure we always destroy session. destroyInternal(); if (returnCode == INSTALL_SUCCEEDED) { future.complete(null); } else { future.completeExceptionally(new PackageManagerException(returnCode, msg)); } dispatchSessionFinished(returnCode, msg, extras); } }; Loading services/core/java/com/android/server/pm/StagingManager.java +13 −21 Original line number Diff line number Diff line Loading @@ -77,6 +77,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; Loading Loading @@ -131,7 +132,7 @@ public class StagingManager { void setSessionReady(); void setSessionFailed(@SessionErrorCode int errorCode, String errorMessage); void setSessionApplied(); void installSession(IntentSender statusReceiver); CompletableFuture<Void> installSession(); boolean hasParentSessionId(); long getCommittedMillis(); void abandon(); Loading Loading @@ -417,8 +418,6 @@ public class StagingManager { installApksInSession(session); t.traceEnd(); Slog.d(TAG, "Marking session " + session.sessionId() + " as applied"); session.setSessionApplied(); if (hasApex) { if (supportsCheckpoint) { // Store the session ID, which will be marked as successful by ApexManager upon Loading Loading @@ -494,24 +493,17 @@ public class StagingManager { } } private void installApksInSession(StagedSession session) throws PackageManagerException { if (!session.containsApkSession()) { return; } final LocalIntentReceiverSync receiver = new LocalIntentReceiverSync(); session.installSession(receiver.getIntentSender()); final Intent result = receiver.getResult(); final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE); if (status != PackageInstaller.STATUS_SUCCESS) { final String errorMessage = result.getStringExtra( PackageInstaller.EXTRA_STATUS_MESSAGE); Slog.e(TAG, "Failure to install APK staged session " + session.sessionId() + " [" + errorMessage + "]"); throw new PackageManagerException( SessionInfo.SESSION_ACTIVATION_FAILED, errorMessage); private void installApksInSession(StagedSession session) throws PackageManagerException { try { // Blocking wait for installation to complete session.installSession().get(); } catch (InterruptedException e) { // Should be impossible throw new RuntimeException(e); } catch (ExecutionException ee) { PackageManagerException e = (PackageManagerException) ee.getCause(); final String errorMsg = PackageManager.installStatusToString(e.error, e.getMessage()); throw new PackageManagerException(SessionInfo.SESSION_ACTIVATION_FAILED, errorMsg); } } Loading services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.apex.ApexInfo; import android.apex.ApexSessionInfo; import android.apex.ApexSessionParams; import android.content.Context; import android.content.IntentSender; import android.content.pm.ApexStagedEvent; import android.content.pm.IStagedApexObserver; import android.content.pm.PackageInstaller; Loading Loading @@ -75,6 +74,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.function.Predicate; @Presubmit Loading Loading @@ -953,7 +953,7 @@ public class StagingManagerTest { } @Override public void installSession(IntentSender statusReceiver) { public CompletableFuture<Void> installSession() { throw new UnsupportedOperationException(); } Loading Loading
services/core/java/com/android/server/pm/PackageInstallerService.java +4 −1 Original line number Diff line number Diff line Loading @@ -1650,7 +1650,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements public void onSessionChanged(PackageInstallerSession session) { session.markUpdated(); mSettingsWriteRequest.schedule(); if (mOkToSendBroadcasts && !session.isDestroyed()) { // TODO(b/210359798): Remove the session.isStaged() check. Some apps assume this // broadcast is sent by only staged sessions and call isStagedSessionApplied() without // checking if it is a staged session or not and cause exception. if (mOkToSendBroadcasts && !session.isDestroyed() && session.isStaged()) { // we don't scrub the data here as this is sent only to the installer several // privileged system packages sendSessionUpdatedBroadcast( Loading
services/core/java/com/android/server/pm/PackageInstallerSession.java +83 −68 Original line number Diff line number Diff line Loading @@ -182,6 +182,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Predicate; Loading Loading @@ -549,18 +550,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { /** * Installs apks of staged session while skipping the verification process for a committed * and ready session. * * @return a CompletableFuture that will be completed when installation completes. */ @Override public void installSession(IntentSender statusReceiver) { public CompletableFuture<Void> installSession() { assertCallerIsOwnerOrRootOrSystem(); assertNotChild("StagedSession#installSession"); Preconditions.checkArgument(isCommitted() && isSessionReady()); // Since staged sessions are installed during boot, the original reference to status // receiver from the owner has already been lost. We can safely replace it with a // status receiver from the system without effecting the flow. updateRemoteStatusReceiver(statusReceiver); install(); return install(); } private void updateRemoteStatusReceiver(IntentSender remoteStatusReceiver) { Loading Loading @@ -1694,15 +1692,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } if (isMultiPackage()) { synchronized (mLock) { final IntentSender childIntentSender = new ChildStatusIntentReceiver(mChildSessions.clone(), statusReceiver) .getIntentSender(); boolean sealFailed = false; for (int i = mChildSessions.size() - 1; i >= 0; --i) { // seal all children, regardless if any of them fail; we'll throw/return // as appropriate once all children have been processed if (!mChildSessions.valueAt(i) .markAsSealed(childIntentSender, forTransfer)) { if (!mChildSessions.valueAt(i).markAsSealed(null, forTransfer)) { sealFailed = true; } } Loading Loading @@ -1890,8 +1884,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * This method may be called multiple times to update the status receiver validate caller * permissions. */ private boolean markAsSealed(@NonNull IntentSender statusReceiver, boolean forTransfer) { Objects.requireNonNull(statusReceiver); private boolean markAsSealed(@Nullable IntentSender statusReceiver, boolean forTransfer) { Preconditions.checkState(statusReceiver != null || hasParentSessionId(), "statusReceiver can't be null for the root session"); assertCallerIsOwnerOrRoot(); synchronized (mLock) { Loading Loading @@ -2191,7 +2186,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } @WorkerThread private static boolean checkUserActionRequirement(PackageInstallerSession session) { private static boolean checkUserActionRequirement( PackageInstallerSession session, IntentSender target) { if (session.isMultiPackage()) { return false; } Loading @@ -2200,7 +2196,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // TODO(b/159331446): Move this to makeSessionActiveForInstall and update javadoc userActionRequirement = session.computeUserActionRequirement(); if (userActionRequirement == USER_ACTION_REQUIRED) { session.sendPendingUserActionIntent(); session.sendPendingUserActionIntent(target); return true; } Loading @@ -2212,7 +2208,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { if (validatedTargetSdk != INVALID_TARGET_SDK_VERSION && validatedTargetSdk < Build.VERSION_CODES.Q) { session.sendPendingUserActionIntent(); session.sendPendingUserActionIntent(target); return true; } Loading @@ -2221,7 +2217,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { session.getInstallerPackageName(), session.getPackageName())) { // Fall back to the non-silent update if a repeated installation is invoked // within the throttle time. session.sendPendingUserActionIntent(); session.sendPendingUserActionIntent(target); return true; } session.mSilentUpdatePolicy.track(session.getInstallerPackageName(), Loading @@ -2241,7 +2237,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private boolean sendPendingUserActionIntentIfNeeded() { assertNotChild("PackageInstallerSession#sendPendingUserActionIntentIfNeeded"); return sessionContains(PackageInstallerSession::checkUserActionRequirement); final IntentSender statusReceiver = getRemoteStatusReceiver(); return sessionContains(s -> checkUserActionRequirement(s, statusReceiver)); } @WorkerThread Loading Loading @@ -2439,53 +2436,69 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { }); } private void install() { try { installNonStaged(); } catch (PackageManagerException e) { final String completeMsg = ExceptionUtils.getCompleteMessage(e); onSessionInstallationFailure(e.error, completeMsg); /** * Stages installs and do cleanup accordingly depending on whether the installation is * successful or not. * * @return a future that will be completed when the whole process is completed. */ private CompletableFuture<Void> install() { return installNonStaged().whenComplete((r, t) -> { if (t == null) { setSessionApplied(); dispatchSessionFinished(INSTALL_SUCCEEDED, "Session installed", null); maybeFinishChildSessions(INSTALL_SUCCEEDED, "Session installed"); } else { PackageManagerException e = (PackageManagerException) t.getCause(); setSessionFailed(SessionInfo.SESSION_ACTIVATION_FAILED, PackageManager.installStatusToString(e.error, e.getMessage())); dispatchSessionFinished(e.error, e.getMessage(), null); maybeFinishChildSessions(e.error, e.getMessage()); } }); } private void installNonStaged() throws PackageManagerException { final InstallParams installingSession = makeInstallParams(); if (installingSession == null) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session should contain at least one apk session for installation"); } /** * Stages sessions (including child sessions if any) for install. * * @return a future that will be completed when the whole session is completed (could be * success or failure). */ private CompletableFuture<Void> installNonStaged() { try { List<CompletableFuture<Void>> futures = new ArrayList<>(); CompletableFuture<Void> future = new CompletableFuture<>(); futures.add(future); final InstallParams installingSession = makeInstallParams(future); if (isMultiPackage()) { final List<PackageInstallerSession> childSessions = getChildSessions(); List<InstallParams> installingChildSessions = new ArrayList<>(childSessions.size()); boolean success = true; PackageManagerException failure = null; for (int i = 0; i < childSessions.size(); ++i) { final PackageInstallerSession session = childSessions.get(i); try { final InstallParams installingChildSession = session.makeInstallParams(); future = new CompletableFuture<>(); futures.add(future); final InstallParams installingChildSession = session.makeInstallParams(future); if (installingChildSession != null) { installingChildSessions.add(installingChildSession); } } catch (PackageManagerException e) { failure = e; success = false; } } if (!success) { sendOnPackageInstalled(mContext, getRemoteStatusReceiver(), sessionId, isInstallerDeviceOwnerOrAffiliatedProfileOwner(), userId, null, failure.error, failure.getLocalizedMessage(), null); return; } if (!installingChildSessions.isEmpty()) { installingSession.installStage(installingChildSessions); } else { } } else if (installingSession != null) { installingSession.installStage(); } CompletableFuture<Void>[] arr = new CompletableFuture[futures.size()]; return CompletableFuture.allOf(futures.toArray(arr)); } catch (PackageManagerException e) { CompletableFuture<Void> future = new CompletableFuture<>(); future.completeExceptionally(e); return future; } } private void sendPendingUserActionIntent() { private void sendPendingUserActionIntent(IntentSender target) { // User needs to confirm installation; // give installer an intent they can use to involve // user. Loading @@ -2493,7 +2506,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { intent.setPackage(mPm.getPackageInstallerPackageName()); intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); sendOnUserActionRequired(mContext, getRemoteStatusReceiver(), sessionId, intent); sendOnUserActionRequired(mContext, target, sessionId, intent); // Commit was keeping session marked as active until now; release // that extra refcount so session appears idle. Loading Loading @@ -2525,9 +2538,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { /** * Stages this session for install and returns a * {@link InstallParams} representing this new staged state. * * @param future a future that will be completed when this session is completed. */ @Nullable private InstallParams makeInstallParams() private InstallParams makeInstallParams(CompletableFuture<Void> future) throws PackageManagerException { synchronized (mLock) { if (mDestroyed) { Loading @@ -2540,11 +2555,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } // Do not try to install staged apex session. Parent session will have at least one apk // session. if (!isMultiPackage() && isApexSession() && params.isStaged) { dispatchSessionFinished(INSTALL_SUCCEEDED, "Apex package should have been installed by apexd", null); if (isMultiPackage()) { // Always treat parent session as success for it has nothing to install future.complete(null); } else if (isApexSession() && params.isStaged) { // Staged apex sessions have been handled by apexd future.complete(null); return null; } Loading @@ -2557,12 +2573,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @Override public void onPackageInstalled(String basePackageName, int returnCode, String msg, Bundle extras) { if (!isStaged()) { // We've reached point of no return; call into PMS to install the stage. // Regardless of success or failure we always destroy session. destroyInternal(); if (returnCode == INSTALL_SUCCEEDED) { future.complete(null); } else { future.completeExceptionally(new PackageManagerException(returnCode, msg)); } dispatchSessionFinished(returnCode, msg, extras); } }; Loading
services/core/java/com/android/server/pm/StagingManager.java +13 −21 Original line number Diff line number Diff line Loading @@ -77,6 +77,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; Loading Loading @@ -131,7 +132,7 @@ public class StagingManager { void setSessionReady(); void setSessionFailed(@SessionErrorCode int errorCode, String errorMessage); void setSessionApplied(); void installSession(IntentSender statusReceiver); CompletableFuture<Void> installSession(); boolean hasParentSessionId(); long getCommittedMillis(); void abandon(); Loading Loading @@ -417,8 +418,6 @@ public class StagingManager { installApksInSession(session); t.traceEnd(); Slog.d(TAG, "Marking session " + session.sessionId() + " as applied"); session.setSessionApplied(); if (hasApex) { if (supportsCheckpoint) { // Store the session ID, which will be marked as successful by ApexManager upon Loading Loading @@ -494,24 +493,17 @@ public class StagingManager { } } private void installApksInSession(StagedSession session) throws PackageManagerException { if (!session.containsApkSession()) { return; } final LocalIntentReceiverSync receiver = new LocalIntentReceiverSync(); session.installSession(receiver.getIntentSender()); final Intent result = receiver.getResult(); final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE); if (status != PackageInstaller.STATUS_SUCCESS) { final String errorMessage = result.getStringExtra( PackageInstaller.EXTRA_STATUS_MESSAGE); Slog.e(TAG, "Failure to install APK staged session " + session.sessionId() + " [" + errorMessage + "]"); throw new PackageManagerException( SessionInfo.SESSION_ACTIVATION_FAILED, errorMessage); private void installApksInSession(StagedSession session) throws PackageManagerException { try { // Blocking wait for installation to complete session.installSession().get(); } catch (InterruptedException e) { // Should be impossible throw new RuntimeException(e); } catch (ExecutionException ee) { PackageManagerException e = (PackageManagerException) ee.getCause(); final String errorMsg = PackageManager.installStatusToString(e.error, e.getMessage()); throw new PackageManagerException(SessionInfo.SESSION_ACTIVATION_FAILED, errorMsg); } } Loading
services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.apex.ApexInfo; import android.apex.ApexSessionInfo; import android.apex.ApexSessionParams; import android.content.Context; import android.content.IntentSender; import android.content.pm.ApexStagedEvent; import android.content.pm.IStagedApexObserver; import android.content.pm.PackageInstaller; Loading Loading @@ -75,6 +74,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.function.Predicate; @Presubmit Loading Loading @@ -953,7 +953,7 @@ public class StagingManagerTest { } @Override public void installSession(IntentSender statusReceiver) { public CompletableFuture<Void> installSession() { throw new UnsupportedOperationException(); } Loading