From 534642ef58747bb72e8555546942638bcd84dd6d Mon Sep 17 00:00:00 2001 From: Mohammad Samiul Islam Date: Wed, 13 May 2020 15:50:35 +0100 Subject: [PATCH] Create a channel using which PMS can return result of verification In the existing flow, once session is verified, it gets installed immediately. In future, once a session is verified, we want to perform some actions before we move onto installation phase. Note that we only return the verification result, but do not stop the installation or process the result in any way yet. We still don't have any easy way to resume installation from where verification ends. This will be created soon. Note that, in order to create this channel, I had to temporarily add two observers to InstallParams. This is because it now needs to return verification complete notification AND result of installation. In future, we will create a duplicate of InstallParams called VerificationParams to handle verification exclusively and this temorary observer will be deleted. Bug: 159331446 Test: atest StagedInstallTest Test: atest GtsSecurityHostTestCases Change-Id: I8aa4a72ebbf4fa1616d0be70343f9c4f9cb98f87 --- .../server/pm/PackageInstallerSession.java | 33 +++++++- .../server/pm/PackageManagerService.java | 84 ++++++++++++++++--- 2 files changed, 102 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index bad74a5c3de7f..68f87514a3958 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -1749,7 +1749,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { failure.error, failure.getLocalizedMessage(), null); return; } - mPm.installStage(installingChildSessions); + mPm.installStage(installingSession, installingChildSessions); } else { mPm.installStage(installingSession); } @@ -1868,6 +1868,34 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } }; + // An observer through which PMS returns the result of verification + // TODO(samiul): We are temporarily assigning two observer to ActiveInstallSession. One for + // installation and one for verification. This will be fixed within next few CLs. + final IPackageInstallObserver2 sessionVerificationObserver; + if (!hasParentSessionId()) { + // Avoid attaching this observer to child session since they won't use it. + sessionVerificationObserver = new IPackageInstallObserver2.Stub() { + @Override + public void onUserActionRequired(Intent intent) { + throw new IllegalStateException(); + } + + @Override + public void onPackageInstalled(String basePackageName, int returnCode, String msg, + Bundle extras) { + if (returnCode == PackageManager.INSTALL_SUCCEEDED) { + // TODO(samiul): In future, packages will not be installed immediately after + // verification. Package verification will return control back to here, + // and we will have call into PMS again to install package. + // + // For now, this is a no op. + } + } + }; + } else { + sessionVerificationObserver = null; + } + final UserHandle user; if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) { user = UserHandle.ALL; @@ -1877,7 +1905,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mRelinquished = true; return new PackageManagerService.ActiveInstallSession(mPackageName, stageDir, localObserver, - sessionId, params, mInstallerUid, mInstallSource, user, mSigningDetails); + sessionVerificationObserver, sessionId, params, mInstallerUid, mInstallSource, user, + mSigningDetails); } private static void maybeRenameFile(File from, File to) throws PackageManagerException { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index a8c587bb248ff..2bd38f3820ffe 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -12801,11 +12801,11 @@ public class PackageManagerService extends IPackageManager.Stub mHandler.sendMessage(msg); } - void installStage(List children) + void installStage(ActiveInstallSession parent, List children) throws PackageManagerException { final Message msg = mHandler.obtainMessage(INIT_COPY); final MultiPackageInstallParams params = - new MultiPackageInstallParams(UserHandle.ALL, children); + new MultiPackageInstallParams(UserHandle.ALL, parent, children); params.setTraceMethod("installStageMultiPackage") .setTraceCookie(System.identityHashCode(params)); msg.obj = params; @@ -14693,13 +14693,17 @@ public class PackageManagerService extends IPackageManager.Stub * committed together. */ class MultiPackageInstallParams extends HandlerParams { + private final IPackageInstallObserver2 mVerificationObserver; @NonNull private final ArrayList mChildParams; + // TODO(samiul): mCurrentState will relocated to a install-specific class in future @NonNull private final Map mCurrentState; + private final Map mVerificationState; MultiPackageInstallParams( @NonNull UserHandle user, + @NonNull ActiveInstallSession parent, @NonNull List activeInstallSessions) throws PackageManagerException { super(user); @@ -14713,6 +14717,8 @@ public class PackageManagerService extends IPackageManager.Stub this.mChildParams.add(childParams); } this.mCurrentState = new ArrayMap<>(mChildParams.size()); + this.mVerificationState = new ArrayMap<>(mChildParams.size()); + mVerificationObserver = parent.getVerificationObserver(); } @Override @@ -14729,6 +14735,7 @@ public class PackageManagerService extends IPackageManager.Stub } } + // TODO(samiul): this method will relocated to a install-specific class in future void tryProcessInstallRequest(InstallArgs args, int currentStatus) { mCurrentState.put(args, currentStatus); if (mCurrentState.size() != mChildParams.size()) { @@ -14752,6 +14759,28 @@ public class PackageManagerService extends IPackageManager.Stub completeStatus == PackageManager.INSTALL_SUCCEEDED, installRequests); } + + void trySendVerificationCompleteNotification(InstallParams child, int currentStatus) { + mVerificationState.put(child, currentStatus); + if (mVerificationState.size() != mChildParams.size()) { + return; + } + int completeStatus = PackageManager.INSTALL_SUCCEEDED; + for (Integer status : mVerificationState.values()) { + if (status == PackageManager.INSTALL_UNKNOWN) { + return; + } else if (status != PackageManager.INSTALL_SUCCEEDED) { + completeStatus = status; + break; + } + } + try { + mVerificationObserver.onPackageInstalled(null, completeStatus, + "Package Verification Result", new Bundle()); + } catch (RemoteException e) { + Slog.i(TAG, "Observer no longer exists."); + } + } } class InstallParams extends HandlerParams { @@ -14759,7 +14788,8 @@ public class PackageManagerService extends IPackageManager.Stub final OriginInfo origin; final MoveInfo move; - final IPackageInstallObserver2 observer; + final IPackageInstallObserver2 mInstallObserver; + private final IPackageInstallObserver2 mVerificationObserver; int installFlags; @NonNull final InstallSource installSource; final String volumeUuid; @@ -14781,7 +14811,7 @@ public class PackageManagerService extends IPackageManager.Stub final int mDataLoaderType; final int mSessionId; - InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer, + InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 installObserver, int installFlags, InstallSource installSource, String volumeUuid, VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride, String[] grantedPermissions, List whitelistedRestrictedPermissions, @@ -14791,7 +14821,8 @@ public class PackageManagerService extends IPackageManager.Stub super(user); this.origin = origin; this.move = move; - this.observer = observer; + this.mInstallObserver = installObserver; + this.mVerificationObserver = null; this.installFlags = installFlags; this.installSource = Preconditions.checkNotNull(installSource); this.volumeUuid = volumeUuid; @@ -14829,7 +14860,8 @@ public class PackageManagerService extends IPackageManager.Stub activeInstallSession.getInstallSource().installerPackageName, activeInstallSession.getInstallerUid(), sessionParams.installReason); - observer = activeInstallSession.getObserver(); + mInstallObserver = activeInstallSession.getInstallObserver(); + mVerificationObserver = activeInstallSession.getVerificationObserver(); installFlags = sessionParams.installFlags; installSource = activeInstallSession.getInstallSource(); volumeUuid = sessionParams.volumeUuid; @@ -15383,18 +15415,34 @@ public class PackageManagerService extends IPackageManager.Stub if ((installFlags & PackageManager.INSTALL_DRY_RUN) != 0) { try { - observer.onPackageInstalled(null, mRet, "Dry run", new Bundle()); + mInstallObserver.onPackageInstalled(null, mRet, "Dry run", new Bundle()); } catch (RemoteException e) { Slog.i(TAG, "Observer no longer exists."); } return; } + sendVerificationCompleteNotification(); + + // TODO(samiul): In future return once verification is complete InstallArgs args = createInstallArgs(this); if (mRet == PackageManager.INSTALL_SUCCEEDED) { mRet = args.copyApk(); } processPendingInstall(args, mRet); } + + private void sendVerificationCompleteNotification() { + if (mParentInstallParams != null) { + mParentInstallParams.trySendVerificationCompleteNotification(this, mRet); + } else { + try { + mVerificationObserver.onPackageInstalled(null, mRet, + "Package Verification Result", new Bundle()); + } catch (RemoteException e) { + Slog.i(TAG, "Observer no longer exists."); + } + } + } } private InstallArgs createInstallArgs(InstallParams params) { @@ -15476,7 +15524,7 @@ public class PackageManagerService extends IPackageManager.Stub /** New install */ InstallArgs(InstallParams params) { - this(params.origin, params.move, params.observer, params.installFlags, + this(params.origin, params.move, params.mInstallObserver, params.installFlags, params.installSource, params.volumeUuid, params.getUser(), null /*instructionSets*/, params.packageAbiOverride, params.grantedRuntimePermissions, params.whitelistedRestrictedPermissions, @@ -25497,7 +25545,10 @@ public class PackageManagerService extends IPackageManager.Stub static class ActiveInstallSession { private final String mPackageName; private final File mStagedDir; - private final IPackageInstallObserver2 mObserver; + private final IPackageInstallObserver2 mInstallObserver; + // TODO(samiul): We are temporarily assigning two observer to ActiveInstallSession. One for + // installation and one for verification. This will be fixed within next few CLs. + private final IPackageInstallObserver2 mVerificationObserver; private final int mSessionId; private final PackageInstaller.SessionParams mSessionParams; private final int mInstallerUid; @@ -25505,12 +25556,15 @@ public class PackageManagerService extends IPackageManager.Stub private final UserHandle mUser; private final SigningDetails mSigningDetails; - ActiveInstallSession(String packageName, File stagedDir, IPackageInstallObserver2 observer, + ActiveInstallSession(String packageName, File stagedDir, + IPackageInstallObserver2 installObserver, + IPackageInstallObserver2 verificationObserver, int sessionId, PackageInstaller.SessionParams sessionParams, int installerUid, InstallSource installSource, UserHandle user, SigningDetails signingDetails) { mPackageName = packageName; mStagedDir = stagedDir; - mObserver = observer; + mInstallObserver = installObserver; + mVerificationObserver = verificationObserver; mSessionId = sessionId; mSessionParams = sessionParams; mInstallerUid = installerUid; @@ -25527,8 +25581,12 @@ public class PackageManagerService extends IPackageManager.Stub return mStagedDir; } - public IPackageInstallObserver2 getObserver() { - return mObserver; + public IPackageInstallObserver2 getInstallObserver() { + return mInstallObserver; + } + + public IPackageInstallObserver2 getVerificationObserver() { + return mVerificationObserver; } public int getSessionId() {