Android 安装过程四 MSG_INSTALL消息的处理 安装之前的验证

  由Android 安装过程三文章知道,MSG_INSTALL消息的处理是调用的handleInstall(),看一下它的主要相关代码:

    private void handleInstall() {
    	…………
        if (params.isStaged) {
            mStagingManager.commitSession(mStagedSession);
            // TODO(b/136257624): CTS test fails if we don't send session finished broadcast, even
            //  though ideally, we just need to send session committed broadcast.
            dispatchSessionFinished(INSTALL_SUCCEEDED, "Session staged", null);
            return;
        }

        verify();
    }
    private void verify() {
        try {
            verifyNonStaged();
        } catch (PackageManagerException e) {
            final String completeMsg = ExceptionUtils.getCompleteMessage(e);
            onSessionVerificationFailure(e.error, completeMsg);
        }
    }

  params.isStaged代表这个安装是需要重启才执行安装。
  接着它就调用verifyNonStaged()。看一下verifyNonStaged()的代码:

    private void verifyNonStaged()
            throws PackageManagerException {
        final PackageManagerService.VerificationParams verifyingSession =
                prepareForVerification();
        if (verifyingSession == null) {
            return;
        }
        if (isMultiPackage()) {
            final List<PackageInstallerSession> childSessions;
            synchronized (mLock) {
                childSessions = getChildSessionsLocked();
            }
            // Spot check to reject a non-staged multi package install of APEXes and APKs.
            if (!params.isStaged && containsApkSession()
                    && sessionContains(s -> s.isApexSession())) {
                throw new PackageManagerException(
                    PackageManager.INSTALL_FAILED_SESSION_INVALID,
                    "Non-staged multi package install of APEX and APK packages is not supported");
            }
            List<PackageManagerService.VerificationParams> verifyingChildSessions =
                    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 PackageManagerService.VerificationParams verifyingChildSession =
                            session.prepareForVerification();
                    if (verifyingChildSession != null) {
                        verifyingChildSessions.add(verifyingChildSession);
                    }
                } catch (PackageManagerException e) {
                    failure = e;
                    success = false;
                }
            }
            if (!success) {
                final IntentSender statusReceiver;
                synchronized (mLock) {
                    statusReceiver = mRemoteStatusReceiver;
                }
                sendOnPackageInstalled(mContext, statusReceiver, sessionId,
                        isInstallerDeviceOwnerOrAffiliatedProfileOwner(), userId, null,
                        failure.error, failure.getLocalizedMessage(), null);
                return;
            }
            mPm.verifyStage(verifyingSession, verifyingChildSessions);
        } else {
            mPm.verifyStage(verifyingSession);
        }
    }

  它首先调用prepareForVerification()返回一个PackageManagerService.VerificationParams类型对象verifyingSession,即验证参数对象。如果它为null,直接返回,不再向下执行。
  接下来就分是多包安装还是单包安装。咱这里先暂时说单包安装的情况,也就是单apk文件安装。
  mPm是PackageManagerService的类对象,所以接下来就进入PackageManagerService的类,执行它的verifyStage(verifyingSession)方法,即具体的验证过程。
  下面首先看下生成验证参数对象,接着再看verifyStage(verifyingSession)方法。

生成验证参数对象

  看下prepareForVerification()的源代码:

    @Nullable
    private PackageManagerService.VerificationParams prepareForVerification()
            throws PackageManagerException {
        assertNotLocked("makeSessionActive");

        @UserActionRequirement
        int userActionRequirement = USER_ACTION_NOT_NEEDED;
        // TODO(b/159331446): Move this to makeSessionActiveForInstall and update javadoc
        if (!params.isMultiPackage) {
            userActionRequirement = computeUserActionRequirement();
            if (userActionRequirement == USER_ACTION_REQUIRED) {
                sendPendingUserActionIntent();
                return null;
            } // else, we'll wait until we parse to determine if we need to
        }

        boolean silentUpdatePolicyEnforceable = false;
        synchronized (mLock) {
            if (mRelinquished) {
                throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                        "Session relinquished");
            }
            if (mDestroyed) {
                throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                        "Session destroyed");
            }
            if (!mSealed) {
                throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                        "Session not sealed");
            }
            PackageLite result = parseApkLite();
            if (result != null) {
                mPackageLite = result;
                synchronized (mProgressLock) {
                    mInternalProgress = 0.5f;
                    computeProgressLocked(true);
                }

                extractNativeLibraries(
                        mPackageLite, stageDir, params.abiOverride, mayInheritNativeLibs());

                if (userActionRequirement == USER_ACTION_PENDING_APK_PARSING) {
                    if (result.getTargetSdk() < Build.VERSION_CODES.Q) {
                        sendPendingUserActionIntent();
                        return null;
                    }
                    if (params.requireUserAction == SessionParams.USER_ACTION_NOT_REQUIRED) {
                        silentUpdatePolicyEnforceable = true;
                    }
                }
            }
        }
        if (silentUpdatePolicyEnforceable) {
            if (!mSilentUpdatePolicy.isSilentUpdateAllowed(
                    getInstallerPackageName(), getPackageName())) {
                // Fall back to the non-silent update if a repeated installation is invoked within
                // the throttle time.
                sendPendingUserActionIntent();
                return null;
            }
            mSilentUpdatePolicy.track(getInstallerPackageName(), getPackageName());
        }
        synchronized (mLock) {
            return makeVerificationParamsLocked();
        }
    }

  对于单包安装的情况,它首先调用computeUserActionRequirement(),检查是否需要用户确认,得到结果存在变量userActionRequirement中。如果它的返回结果是USER_ACTION_REQUIRED,则会调用sendPendingUserActionIntent(),跳到确认界面(对应安装应用的InstallStart Activity,因为它的Action是"android.content.pm.action.CONFIRM_INSTALL"),并且不再向下执行。computeUserActionRequirement()下面详细再说,先看完整逻辑流程。
  接下来检查几个状态,如果mRelinquished为true,mDestroyed为true,mSealed为false,都会报PackageManagerException异常。
  mRelinquished会在下面执行过makeVerificationParamsLocked()之后变为true。mSealed是在Session封装完就为true。
  接着调用parseApkLite()得到解析的包,如果不为null,则会将它赋值给mPackageLite。并且将mInternalProgress = 0.5f,接着去算进度。继续提取本地库文件。如果变量userActionRequirement为USER_ACTION_PENDING_APK_PARSING,代表需要等到解析包后,所以现在需要判断。如果目标安装包的TargetSdk小于Build.VERSION_CODES.Q,也会则会调用sendPendingUserActionIntent(),跳到确认界面。除此外,如果参数requireUserAction为SessionParams.USER_ACTION_NOT_REQUIRED,则将silentUpdatePolicyEnforceable设置为true,代表可以强制静默升级。
  如果可以强制静默升级,但是不允许安装者和应用静默升级,也会跳去确认界面,等待用户确认。
  最后是调用makeVerificationParamsLocked()生成VerificationParams对象。

检查是否需要用户确认

  看一下computeUserActionRequirement()方法,它的代码如下:

    @UserActionRequirement
    private int computeUserActionRequirement() {
        final String packageName;
        synchronized (mLock) {
            if (mPermissionsManuallyAccepted) {
                return USER_ACTION_NOT_NEEDED;
            }
            packageName = mPackageName;
        }

        final boolean forcePermissionPrompt =
                (params.installFlags & PackageManager.INSTALL_FORCE_PERMISSION_PROMPT) != 0
                        || params.requireUserAction == SessionParams.USER_ACTION_REQUIRED;
        if (forcePermissionPrompt) {
            return USER_ACTION_REQUIRED;
        }
        // It is safe to access mInstallerUid and mInstallSource without lock
        // because they are immutable after sealing.
        final boolean isInstallPermissionGranted =
                (mPm.checkUidPermission(android.Manifest.permission.INSTALL_PACKAGES,
                        mInstallerUid) == PackageManager.PERMISSION_GRANTED);
        final boolean isSelfUpdatePermissionGranted =
                (mPm.checkUidPermission(android.Manifest.permission.INSTALL_SELF_UPDATES,
                        mInstallerUid) == PackageManager.PERMISSION_GRANTED);
        final boolean isUpdatePermissionGranted =
                (mPm.checkUidPermission(android.Manifest.permission.INSTALL_PACKAGE_UPDATES,
                        mInstallerUid) == PackageManager.PERMISSION_GRANTED);
        final boolean isUpdateWithoutUserActionPermissionGranted = (mPm.checkUidPermission(
                android.Manifest.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION, mInstallerUid)
                == PackageManager.PERMISSION_GRANTED);
        final int targetPackageUid = mPm.getPackageUid(packageName, 0, userId);
        final boolean isUpdate = targetPackageUid != -1 || isApexSession();
        final InstallSourceInfo existingInstallSourceInfo = isUpdate
                ? mPm.getInstallSourceInfo(packageName)
                : null;
        final String existingInstallerPackageName = existingInstallSourceInfo != null
                ? existingInstallSourceInfo.getInstallingPackageName()
                : null;
        final boolean isInstallerOfRecord = isUpdate
                && Objects.equals(existingInstallerPackageName, getInstallerPackageName());
        final boolean isSelfUpdate = targetPackageUid == mInstallerUid;
        final boolean isPermissionGranted = isInstallPermissionGranted
                || (isUpdatePermissionGranted && isUpdate)
                || (isSelfUpdatePermissionGranted && isSelfUpdate);
        final boolean isInstallerRoot = (mInstallerUid == Process.ROOT_UID);
        final boolean isInstallerSystem = (mInstallerUid == Process.SYSTEM_UID);

        // Device owners and affiliated profile owners  are allowed to silently install packages, so
        // the permission check is waived if the installer is the device owner.
        final boolean noUserActionNecessary = isPermissionGranted || isInstallerRoot
                || isInstallerSystem || isInstallerDeviceOwnerOrAffiliatedProfileOwner();

        if (noUserActionNecessary) {
            return USER_ACTION_NOT_NEEDED;
        }

        if (mPm.isInstallDisabledForPackage(getInstallerPackageName(), mInstallerUid, userId)) {
            // show the installer to account for device poslicy or unknown sources use cases
            return USER_ACTION_REQUIRED;
        }

        if (params.requireUserAction == SessionParams.USER_ACTION_NOT_REQUIRED
                && isUpdateWithoutUserActionPermissionGranted
                && (isInstallerOfRecord || isSelfUpdate)) {
            return USER_ACTION_PENDING_APK_PARSING;
        }

        return USER_ACTION_REQUIRED;
    }

  变量mPermissionsManuallyAccepted代表权限被设置成不用检查了,所以直接返回USER_ACTION_NOT_NEEDED,代表不需要手动设置。
  如果Session对象的参数里的安装标识有INSTALL_FORCE_PERMISSION_PROMPT标识,或者params.requireUserAction等于SessionParams.USER_ACTION_REQUIRED,这俩代表需要用户来确认。
  接下来是要检查安装者应用权限。咱们的例子安装者应用就是安装进程应用。
  首先是INSTALL_PACKAGES权限,如果安装者应用有该权限,则isInstallPermissionGranted为true。
  接下来判断安装者应用是否有INSTALL_SELF_UPDATES、INSTALL_PACKAGE_UPDATES、UPDATE_PACKAGES_WITHOUT_USER_ACTION权限。
  targetPackageUid是安装应用的Uid。如果它为-1,则是首次安装;如果不是-1,代表它是一个升级。
  existingInstallSourceInfo是已经安装应用的安装源信息。existingInstallerPackageName是已经安装应用的安装者的包名,isInstallerOfRecord为true,代表安装者没有发生变化。
  isSelfUpdate为true,代表自己安装自己。
  返回USER_ACTION_NOT_NEEDED,代表不需要用户来确认。所以可以看到安装者有INSTALL_PACKAGES权限,或者有INSTALL_PACKAGE_UPDATES权限并且是更新安装的情况,或者有INSTALL_SELF_UPDATES权限并且自己安装自己的情况下,都不需要用户来确认。
  在安装者是root或者system应用时,也不需要用户来确认。
  另外,在安装者是这个设备所有者或者附属于这个设备时,也是不需要用户来检查。直接返回USER_ACTION_NOT_NEEDED。
  如果用户有明显的安装未知来源的应用的限制,这种情况需要用户来确认。mPm.isInstallDisabledForPackage(getInstallerPackageName(), mInstallerUid, userId)就是来检查这种情况的。
  这里还会有返回USER_ACTION_PENDING_APK_PARSING的情况,对于它的理解,应该是等待APK解析之后再看情况。它是在参数的requireUserAction等于SessionParams.USER_ACTION_NOT_REQUIRED,并且安装者有UPDATE_PACKAGES_WITHOUT_USER_ACTION权限,并且在安装者没有变化或者是自己更新自己的情况下,会返回USER_ACTION_PENDING_APK_PARSING结果。等到下面解析包之后,我们还能看到它的使用。
  这些代码分析完了,像我们的例子,安装者是安装进程应用,它是属于哪种情况呢?它属于拥有INSTALL_PACKAGES权限的情况。安装进程应用是系统私有预安装的,它在预安装时,权限就分配给它了。

解析包parseApkLite()

  看一下parseApkLite()的代码:

    @Nullable
    private PackageLite parseApkLite() throws PackageManagerException {


        // TODO(b/136257624): Some logic in this if block probably belongs in
        //  makeInstallParams().
        if (!isMultiPackage() && !isApexSession()) {
            Objects.requireNonNull(mPackageName);
            Objects.requireNonNull(mSigningDetails);
            Objects.requireNonNull(mResolvedBaseFile);

            // If we haven't already parsed, inherit any packages and native libraries from existing
            // install that haven't been overridden.
            if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
                try {
                    final List<File> fromFiles = mResolvedInheritedFiles;
                    final File toDir = stageDir;

                    if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
                    if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
                        throw new IllegalStateException("mInheritedFilesBase == null");
                    }

                    if (isLinkPossible(fromFiles, toDir)) {
                        if (!mResolvedInstructionSets.isEmpty()) {
                            final File oatDir = new File(toDir, "oat");
                            createOatDirs(mResolvedInstructionSets, oatDir);
                        }
                        // pre-create lib dirs for linking if necessary
                        if (!mResolvedNativeLibPaths.isEmpty()) {
                            for (String libPath : mResolvedNativeLibPaths) {
                                // "/lib/arm64" -> ["lib", "arm64"]
                                final int splitIndex = libPath.lastIndexOf('/');
                                if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
                                    Slog.e(TAG,
                                            "Skipping native library creation for linking due"
                                                    + " to invalid path: " + libPath);
                                    continue;
                                }
                                final String libDirPath = libPath.substring(1, splitIndex);
                                final File libDir = new File(toDir, libDirPath);
                                if (!libDir.exists()) {
                                    NativeLibraryHelper.createNativeLibrarySubdir(libDir);
                                }
                                final String archDirPath = libPath.substring(splitIndex + 1);
                                NativeLibraryHelper.createNativeLibrarySubdir(
                                        new File(libDir, archDirPath));
                            }
                        }
                        linkFiles(fromFiles, toDir, mInheritedFilesBase);
                    } else {
                        // TODO: this should delegate to DCS so the system process
                        // avoids holding open FDs into containers.
                        copyFiles(fromFiles, toDir);
                    }
                } catch (IOException e) {
                    throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
                            "Failed to inherit existing install", e);
                }
            }
            // For mode inherit existing, it would link/copy existing files to stage dir in the
            // above block. Therefore, we need to parse the complete package in stage dir here.
            // Besides, PackageLite may be null for staged sessions that don't complete pre-reboot
            // verification.
            return getOrParsePackageLiteLocked(stageDir, /* flags */ 0);
        }
        return null;
    }

  安装分两种模式,一个是全部安装(MODE_FULL_INSTALL),一个则是部分安装(MODE_INHERIT_EXISTING)。解析安装文件的包,在全部安装模式时,在前面处理MSG_STREAM_VALIDATE_AND_COMMIT消息,检测相关内容的一致性时已经解析过,将它放到成员变量mPackageLite 中,见 Android 安装过程三 MSG_ON_SESSION_SEALED、MSG_STREAM_VALIDATE_AND_COMMIT的处理。但是部分安装模式,当时只是将需要继承使用的文件添加到mResolvedInheritedFiles中,所以,这里就需要处理模式为SessionParams.MODE_INHERIT_EXISTING的情况。
  在部分安装时,如果mResolvedInheritedFiles中的文件都可以创建软链接,这时会先将相关的目录给建立。然后创建软链接。如果不能,则将mResolvedInheritedFiles中的文件拷贝到stageDir目录中。
  接着调用getOrParsePackageLiteLocked(stageDir, /* flags */ 0)得到解析的包对象。看一下它的代码:

    @GuardedBy("mLock")
    private PackageLite getOrParsePackageLiteLocked(File packageFile, int flags)
            throws PackageManagerException {
        if (mPackageLite != null) {
            return mPackageLite;
        }

        final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
        final ParseResult<PackageLite> result =
                ApkLiteParseUtils.parsePackageLite(input, packageFile, flags);
        if (result.isError()) {
            throw new PackageManagerException(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
                    result.getErrorMessage(), result.getException());
        }
        return result.getResult();
    }

  看到如果mPackageLite 不为null的情况下,直接返回,不用再次进行解析,该种情况对应完全安装模式。接下来就是调用ApkLiteParseUtils.parsePackageLite(input, packageFile, flags)进行解析,在这里参数packageFile是目录stageDir对象。
  解析过程可以参考这篇文章 Android 解析APK包

生成验证参数对象

  生成VerificationParams对象,是makeVerificationParamsLocked()实现的,看一下它的代码:

    @GuardedBy("mLock")
    @Nullable
    /**
     * Returns a {@link com.android.server.pm.PackageManagerService.VerificationParams}
     */
    private PackageManagerService.VerificationParams makeVerificationParamsLocked() {
        final IPackageInstallObserver2 localObserver;
        if (!hasParentSessionId()) {
            // Avoid attaching this observer to child session since they won't use it.
            localObserver = 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 == INSTALL_SUCCEEDED) {
                        onVerificationComplete();
                    } else {
                        onSessionVerificationFailure(returnCode, msg);
                    }
                }
            };
        } else {
            localObserver = null;
        }

        final UserHandle user;
        if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
            user = UserHandle.ALL;
        } else {
            user = new UserHandle(userId);
        }

        mRelinquished = true;

        // TODO(b/169375643): Remove this workaround once b/161121612 is fixed.
        PackageInstaller.SessionParams copiedParams = params.copy();
        if (params.isStaged) {
            // This is called by the pre-reboot verification. Don't enable rollback here since
            // it has been enabled when pre-reboot verification starts.
            copiedParams.installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
        }
        return mPm.new VerificationParams(user, stageDir, localObserver, copiedParams,
                mInstallSource, mInstallerUid, mSigningDetails, sessionId, mPackageLite);
    }

  hasParentSessionId()代表有父SessionId,它是检查它的成员变量mParentSessionId != SessionInfo.INVALID_ID来判断的。父SessionId是用在多包安装时,而生成的localObserver对象,是用来回调使用,如果是子Session是不需要设置的。验证完毕之后,会调用localObserver对象的onPackageInstalled接口。
  如果参数的安装标志有INSTALL_ALL_USERS,则用户设置为UserHandle.ALL。不然设置为对应userId的用户。
  然后将Session对象的mRelinquished = true。并且将参数生成一份copy。
  再接着就是生成验证参数对象VerificationParams。看一下它的构造函数,

        VerificationParams(UserHandle user, File stagedDir, IPackageInstallObserver2 observer,
                PackageInstaller.SessionParams sessionParams, InstallSource installSource,
                int installerUid, SigningDetails signingDetails, int sessionId, PackageLite lite) {
            super(user);
            origin = OriginInfo.fromStagedFile(stagedDir);
            this.observer = observer;
            installFlags = sessionParams.installFlags;
            this.installSource = installSource;
            packageAbiOverride = sessionParams.abiOverride;
            verificationInfo = new VerificationInfo(
                    sessionParams.originatingUri,
                    sessionParams.referrerUri,
                    sessionParams.originatingUid,
                    installerUid
            );
            this.signingDetails = signingDetails;
            requiredInstalledVersionCode = sessionParams.requiredInstalledVersionCode;
            mDataLoaderType = (sessionParams.dataLoaderParams != null)
                    ? sessionParams.dataLoaderParams.getType() : DataLoaderType.NONE;
            mSessionId = sessionId;
            mPackageLite = lite;
        }

  这里的origin 是OriginInfo对象,它里面存放安装目录。
  verificationInfo 是VerificationInfo对象,这里sessionParams.originatingUid是调用安装进程应用安装的应用Uid,installerUid则是安装进程应用的Uid。其他的都是赋值给它的成员变量。

验证APK

  进入PackageManagerService中的verifyStage(VerificationParams params)方法中,看下它的代码:

    void verifyStage(VerificationParams params) {
        mHandler.post(()-> {
            params.startCopy();
        });
    }

  这里的mHandler是一个PackageHandler实例,它发送的消息,是在叫"PackageManager"的线程中执行的。该线程实现在ServiceThread类中。
  所以在"PackageManager"的线程中执行VerificationParams 类的startCopy()。而VerificationParams 继承HandlerParams。它的相关实现:

        final void startCopy() {
            if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
            handleStartCopy();
            handleReturnCode();
        }

  它分别执行handleStartCopy()和handleReturnCode(),而这俩方法实现在子类VerificationParams 中。
  看一下VerificationParams的handleStartCopy()方法:

        public void handleStartCopy() {
            if ((installFlags & PackageManager.INSTALL_APEX) != 0) {
                // Apex packages get verified in StagingManager currently.
                // TODO(b/136257624): Move apex verification logic out of StagingManager
                mRet = INSTALL_SUCCEEDED;
                return;
            }

            PackageInfoLite pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
                    mPackageLite, origin.resolvedPath, installFlags, packageAbiOverride);

            mRet = verifyReplacingVersionCode(pkgLite, requiredInstalledVersionCode, installFlags);
            if (mRet != INSTALL_SUCCEEDED) {
                return;
            }

            // Perform package verification and enable rollback (unless we are simply moving the
            // package).
            if (!origin.existing) {
                sendApkVerificationRequest(pkgLite);
                if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
                    sendEnableRollbackRequest();
                }
            }
        }

  origin.resolvedPath是安装目录,packageAbiOverride为ABI架构,通过它来计算安装文件大小。通过PackageManagerServiceUtils.getMinimalPackageInfo()得到包信息对象pkgLite。
  接着调用verifyReplacingVersionCode()验证已经安装过的应用的版本号。如果是首次安装,是直接返回成功结果。在其中还会进行降版本安装的检查。
  构造origin对象时,existing为false,所以接着会调用sendApkVerificationRequest(pkgLite)执行验证请求。如果安装标识存在INSTALL_ENABLE_ROLLBACK,也会调用sendEnableRollbackRequest()。

发送APK验证请求

  看下sendApkVerificationRequest(pkgLite)的代码:

        void sendApkVerificationRequest(PackageInfoLite pkgLite) {
            final int verificationId = mPendingVerificationToken++;

            PackageVerificationState verificationState =
                    new PackageVerificationState(this);
            mPendingVerification.append(verificationId, verificationState);

            sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
            mRet = sendPackageVerificationRequest(
                    verificationId, pkgLite, verificationState);

            // If both verifications are skipped, we should remove the state.
            if (verificationState.areAllVerificationsComplete()) {
                mPendingVerification.remove(verificationId);
            }
        }

  先得到验证id verificationId。然后生成一个PackageVerificationState 对象。这里的this是VerificationParams对象。接着会将验证id和verificationState放到mPendingVerification中。
  再接着调用sendIntegrityVerificationRequest()发送完整验证的请求。
  继续通过sendPackageVerificationRequest(),如果有必要,向验证者发送验证请求。并且将验证结果,赋值给mRet。
  接下来判断,如果verificationState.areAllVerificationsComplete()为true。则将前面添加到mPendingVerification中的verificationState删除。前面两个请求如果不满足条件,有可能会跳过。像这种跳过的情况,verificationState.areAllVerificationsComplete()就为true。

发送完整验证的请求

  看下sendIntegrityVerificationRequest()的源代码:

        void sendIntegrityVerificationRequest(
                int verificationId,
                PackageInfoLite pkgLite,
                PackageVerificationState verificationState) {
            if (!isIntegrityVerificationEnabled()) {
                // Consider the integrity check as passed.
                verificationState.setIntegrityVerificationResult(
                        PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
                return;
            }

            final Intent integrityVerification =
                    new Intent(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);

            integrityVerification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
                    PACKAGE_MIME_TYPE);

            final int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_RECEIVER_REGISTERED_ONLY
                    | Intent.FLAG_RECEIVER_FOREGROUND;
            integrityVerification.addFlags(flags);

            integrityVerification.putExtra(EXTRA_VERIFICATION_ID, verificationId);
            integrityVerification.putExtra(EXTRA_PACKAGE_NAME, pkgLite.packageName);
            integrityVerification.putExtra(EXTRA_VERSION_CODE, pkgLite.versionCode);
            integrityVerification.putExtra(EXTRA_LONG_VERSION_CODE, pkgLite.getLongVersionCode());
            populateInstallerExtras(integrityVerification);

            // send to integrity component only.
            integrityVerification.setPackage("android");

            final BroadcastOptions options = BroadcastOptions.makeBasic();

            mContext.sendOrderedBroadcastAsUser(integrityVerification, UserHandle.SYSTEM,
                    /* receiverPermission= */ null,
                    /* appOp= */ AppOpsManager.OP_NONE,
                    /* options= */ options.toBundle(),
                    new BroadcastReceiver() {
                        @Override
                        public void onReceive(Context context, Intent intent) {
                            final Message msg =
                                    mHandler.obtainMessage(CHECK_PENDING_INTEGRITY_VERIFICATION);
                            msg.arg1 = verificationId;
                            mHandler.sendMessageDelayed(msg, getIntegrityVerificationTimeout());
                        }
                    }, /* scheduler= */ null,
                    /* initialCode= */ 0,
                    /* initialData= */ null,
                    /* initialExtras= */ null);

            Trace.asyncTraceBegin(
                    TRACE_TAG_PACKAGE_MANAGER, "integrity_verification", verificationId);

            // stop the copy until verification succeeds.
            mWaitForIntegrityVerificationToComplete = true;
        }

  isIntegrityVerificationEnabled()就是用来控制是否做完整性请求的。它是通过变量DEFAULT_INTEGRITY_VERIFY_ENABLE来实现的,目前它的值为true。所以需要做完整性请求。如果它为false,会设置verificationState中的状态,以供下面检测。
  接下来,就是发送广播ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION。它是一个保护的广播,只能被系统发送。它还会向intent中添加,好多数据。其中origin.resolvedPath则为文件的路径。
  它是通过sendOrderedBroadcastAsUser()发送的顺序广播,发送广播最后一个接收的则是参数里的BroadcastReceiver的函数onReceive()。完整性广播的接收在源码中没有找到,所以看下参数中的接收器。它会发送一个CHECK_PENDING_INTEGRITY_VERIFICATION消息,在延迟getIntegrityVerificationTimeout()时间会处理该消息。getIntegrityVerificationTimeout()的最小值目前是30秒。
  如果发送了广播,会将VerificationParams对象的成员变量mWaitForIntegrityVerificationToComplete设置为true。代表它在等待完整性的验证完成。
  下面看下CHECK_PENDING_INTEGRITY_VERIFICATION消息的处理,

                case CHECK_PENDING_INTEGRITY_VERIFICATION: {
                    final int verificationId = msg.arg1;
                    final PackageVerificationState state = mPendingVerification.get(verificationId);

                    if (state != null && !state.isIntegrityVerificationComplete()) {
                        final VerificationParams params = state.getVerificationParams();
                        final Uri originUri = Uri.fromFile(params.origin.resolvedFile);

                        Slog.i(TAG, "Integrity verification timed out for " + originUri);

                        state.setIntegrityVerificationResult(
                                getDefaultIntegrityVerificationResponse());

                        if (getDefaultIntegrityVerificationResponse()
                                == PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW) {
                            Slog.i(TAG, "Integrity check times out, continuing with " + originUri);
                        } else {
                            params.setReturnCode(
                                    PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
                        }

                        if (state.areAllVerificationsComplete()) {
                            mPendingVerification.remove(verificationId);
                        }

                        Trace.asyncTraceEnd(
                                TRACE_TAG_PACKAGE_MANAGER,
                                "integrity_verification",
                                verificationId);

                        params.handleIntegrityVerificationFinished();
                    }
                    break;
                }

  前面说了,发送广播ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION,如果有处理之后,会将完整性验证的状态置为完成,它是通过消息INTEGRITY_VERIFICATION_COMPLETE来实现的。但是,因为没找到对应的广播处理,在这就看CHECK_PENDING_INTEGRITY_VERIFICATION消息的处理了。
  首先取得验证id和验证状态对象state。如果完整性验证还没完成,state调用setIntegrityVerificationResult()将验证完整性状态设置为完成。getDefaultIntegrityVerificationResponse()为VERIFICATION_REJECT,所以参数params.setReturnCode(PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE).。
  接着判断,所有验证都完成,就从mPendingVerification去除该验证。接着会调用验证参数对象handleIntegrityVerificationFinished()来处理验证完整性完成。

        void handleIntegrityVerificationFinished() {
            mWaitForIntegrityVerificationToComplete = false;
            handleReturnCode();
        }
        void handleReturnCode() {
            if (mWaitForVerificationToComplete || mWaitForIntegrityVerificationToComplete
                    || mWaitForEnableRollbackToComplete) {
                return;
            }
            sendVerificationCompleteNotification();
        }

  它会将mWaitForIntegrityVerificationToComplete = false,代表不用等待完整性验证完成。
  handleReturnCode()在三个变量任一为true,都不向下执行。mWaitForIntegrityVerificationToComplete我们说过了,它代表等待完整性验证。其他两个下面再说。
  

向验证者发送验证请求

  相关源代码如下:

        int sendPackageVerificationRequest(
                int verificationId,
                PackageInfoLite pkgLite,
                PackageVerificationState verificationState) {
            int ret = INSTALL_SUCCEEDED;

            // TODO: http://b/22976637
            // Apps installed for "all" users use the device owner to verify the app
            UserHandle verifierUser = getUser();
            if (verifierUser == UserHandle.ALL) {
                verifierUser = UserHandle.SYSTEM;
            }

            /*
             * Determine if we have any installed package verifiers. If we
             * do, then we'll defer to them to verify the packages.
             */
            final int requiredUid = mRequiredVerifierPackage == null ? -1
                    : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
                            verifierUser.getIdentifier());
            verificationState.setRequiredVerifierUid(requiredUid);
            final int installerUid =
                    verificationInfo == null ? -1 : verificationInfo.installerUid;
            final boolean isVerificationEnabled = isVerificationEnabled(
                    pkgLite, verifierUser.getIdentifier(), installFlags, installerUid);
            final boolean isV4Signed =
                    (signingDetails.signatureSchemeVersion == SIGNING_BLOCK_V4);
            final boolean isIncrementalInstall =
                    (mDataLoaderType == DataLoaderType.INCREMENTAL);
            // NOTE: We purposefully skip verification for only incremental installs when there's
            // a v4 signature block. Otherwise, proceed with verification as usual.
            if (!origin.existing
                    && isVerificationEnabled
                    && (!isIncrementalInstall || !isV4Signed)) {
                final Intent verification = new Intent(
                        Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
                verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
                        PACKAGE_MIME_TYPE);
                verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                // Query all live verifiers based on current user state
                final List<ResolveInfo> receivers = queryIntentReceiversInternal(verification,
                        PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier(),
                        false /*allowDynamicSplits*/);

                if (DEBUG_VERIFY) {
                    Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
                            + verification.toString() + " with " + pkgLite.verifiers.length
                            + " optional verifiers");
                }

                verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);

                verification.putExtra(
                        PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, installFlags);

                verification.putExtra(
                        PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME, pkgLite.packageName);

                verification.putExtra(
                        PackageManager.EXTRA_VERIFICATION_VERSION_CODE, pkgLite.versionCode);

                verification.putExtra(
                        PackageManager.EXTRA_VERIFICATION_LONG_VERSION_CODE,
                        pkgLite.getLongVersionCode());

                populateInstallerExtras(verification);

                final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
                        receivers, verificationState);

                DeviceIdleInternal idleController =
                        mInjector.getLocalService(DeviceIdleInternal.class);
                final long idleDuration = getVerificationTimeout();
                final BroadcastOptions options = BroadcastOptions.makeBasic();
                options.setTemporaryAppAllowlist(idleDuration,
                        TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                        REASON_PACKAGE_VERIFIER, "");

                /*
                 * If any sufficient verifiers were listed in the package
                 * manifest, attempt to ask them.
                 */
                if (sufficientVerifiers != null) {
                    final int n = sufficientVerifiers.size();
                    if (n == 0) {
                        Slog.i(TAG, "Additional verifiers required, but none installed.");
                        ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
                    } else {
                        for (int i = 0; i < n; i++) {
                            final ComponentName verifierComponent = sufficientVerifiers.get(i);
                            idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
                                    verifierComponent.getPackageName(), idleDuration,
                                    verifierUser.getIdentifier(), false,
                                    REASON_PACKAGE_VERIFIER,"package verifier");

                            final Intent sufficientIntent = new Intent(verification);
                            sufficientIntent.setComponent(verifierComponent);
                            mContext.sendBroadcastAsUser(sufficientIntent, verifierUser,
                                    /* receiverPermission= */ null,
                                    options.toBundle());
                        }
                    }
                }

                if (mRequiredVerifierPackage != null) {
                    final ComponentName requiredVerifierComponent = matchComponentForVerifier(
                            mRequiredVerifierPackage, receivers);
                    /*
                     * Send the intent to the required verification agent,
                     * but only start the verification timeout after the
                     * target BroadcastReceivers have run.
                     */
                    verification.setComponent(requiredVerifierComponent);
                    idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
                            mRequiredVerifierPackage, idleDuration,
                            verifierUser.getIdentifier(), false,
                            REASON_PACKAGE_VERIFIER, "package verifier");
                    mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
                            android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
                            /* appOp= */ AppOpsManager.OP_NONE,
                            /* options= */ options.toBundle(),
                            new BroadcastReceiver() {
                                @Override
                                public void onReceive(Context context, Intent intent) {
                                    final Message msg = mHandler
                                            .obtainMessage(CHECK_PENDING_VERIFICATION);
                                    msg.arg1 = verificationId;
                                    mHandler.sendMessageDelayed(msg, getVerificationTimeout());
                                }
                            }, null, 0, null, null);

                    Trace.asyncTraceBegin(
                            TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);

                    /*
                     * We don't want the copy to proceed until verification
                     * succeeds.
                     */
                    mWaitForVerificationToComplete = true;
                }
            } else {
                verificationState.setVerifierResponse(
                        requiredUid, PackageManager.VERIFICATION_ALLOW);
            }
            return ret;
        }

  mRequiredVerifierPackage它为已经安装的包的验证者。它是一个包名,代表一个应用,如果在应用中注册了Intent.ACTION_PACKAGE_NEEDS_VERIFICATION广播监听,则该应用为包的验证者。
  如果它不为null,则存在包的验证者,然后得到它的uid requiredUid。installerUid为安装应用的uid。  isVerificationEnabled()方法来得到验证是否需要。后面再分析它,先往下看。
  isV4Signed表示是否是存在v4签名块。isIncrementalInstall代表是增量安装。这俩变量都为true,代表使用流式安装,不用做验证。
  下面就是进入if条件判断,满足该情况,即进行验证。
  可以看到和前面发送完整性验证有些相似,在这里的验证者分配置在安装包文件中和系统中预安装的。在安装包文件中验证者,是在Manifest文件中的"package-verifier"标签下的。在该标签下,有属性"name"和"publicKey",分别为验证者应用的名字和公钥。而系统中预安装的验证者,即为变量mRequiredVerifierPackage的包名。当然,这些都需要在系统中注册了Intent.ACTION_PACKAGE_NEEDS_VERIFICATION广播接收,所以需要进行筛选。筛选匹配工作分别是matchVerifiers()和matchComponentForVerifier()做的。
  可以看到,如果应用文件中配置了验证者,并且筛选成功的话,会先向它们发送验证广播。
  如果系统中有预安装的,也会向他发送验证广播。这个广播接收者,需要android.Manifest.permission.PACKAGE_VERIFICATION_AGENT权限。同样,在发送验证广播之后,它也会发送一个延迟消息CHECK_PENDING_VERIFICATION,这个延迟时间最小为10秒。
  如果系统中有预安装的验证者,之后,会将mWaitForVerificationToComplete = true。代表目前是在等待验证完成。
  这时需要验证,并且存在验证者的情况下,如果不存在验证者的情况下,就直接返回INSTALL_SUCCEEDED。
  同时,如果不需要验证,会直接调用verificationState的setVerifierResponse(),直接设置验证完成的状态值。
  下面看下发送验证的条件

是否需要发送验证

  验证是否需要
看一下它的代码:

    private boolean isVerificationEnabled(
            PackageInfoLite pkgInfoLite, int userId, int installFlags, int installerUid) {
        if (!DEFAULT_VERIFY_ENABLE) {
            return false;
        }

        // Check if installing from ADB
        if ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0) {
            if (isUserRestricted(userId, UserManager.ENSURE_VERIFY_APPS)) {
                return true;
            }
            // Check if the developer wants to skip verification for ADB installs
            if ((installFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0) {
                synchronized (mLock) {
                    if (mSettings.getPackageLPr(pkgInfoLite.packageName) == null) {
                        // Always verify fresh install
                        return true;
                    }
                }
                // Only skip when apk is debuggable
                return !pkgInfoLite.debuggable;
            }
            return Global.getInt(mContext.getContentResolver(),
                    Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) != 0;
        }

        // only when not installed from ADB, skip verification for instant apps when
        // the installer and verifier are the same.
        if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
            if (mInstantAppInstallerActivity != null
                    && mInstantAppInstallerActivity.packageName.equals(
                            mRequiredVerifierPackage)) {
                try {
                    mInjector.getSystemService(AppOpsManager.class)
                            .checkPackage(installerUid, mRequiredVerifierPackage);
                    if (DEBUG_VERIFY) {
                        Slog.i(TAG, "disable verification for instant app");
                    }
                    return false;
                } catch (SecurityException ignore) { }
            }
        }
        return true;
    }

  DEFAULT_VERIFY_ENABLE可以用来开关,目前它是设置为true。
  如果是adb安装,用户如果存在ENSURE_VERIFY_APPS限制,则返回true,代表需要验证。如果安装标识中存在INSTALL_DISABLE_VERIFICATION,第一次安装依然需要验证;其他的情况根据apk是否是debuggable来做决定,如果它为false,则需要验证,如果为true,则不需要验证。
  如果是adb安装,除了上面说的情况,其余的根据Global.PACKAGE_VERIFIER_INCLUDE_ADB属性的值来做验证,如果它不为0,则需要验证。
  还有一种instant安装,如果安装者和验证者是同一应用,则跳过验证。
  其余的情况,均需要验证。

CHECK_PENDING_VERIFICATION消息的处理

  相关代码如下:

                case CHECK_PENDING_VERIFICATION: {
                    final int verificationId = msg.arg1;
                    final PackageVerificationState state = mPendingVerification.get(verificationId);

                    if ((state != null) && !state.isVerificationComplete()
                            && !state.timeoutExtended()) {
                        final VerificationParams params = state.getVerificationParams();
                        final Uri originUri = Uri.fromFile(params.origin.resolvedFile);

                        Slog.i(TAG, "Verification timed out for " + originUri);

                        final UserHandle user = params.getUser();
                        if (getDefaultVerificationResponse(user)
                                == PackageManager.VERIFICATION_ALLOW) {
                            Slog.i(TAG, "Continuing with installation of " + originUri);
                            state.setVerifierResponse(Binder.getCallingUid(),
                                    PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
                            broadcastPackageVerified(verificationId, originUri,
                                    PackageManager.VERIFICATION_ALLOW, null, params.mDataLoaderType,
                                    user);
                        } else {
                            broadcastPackageVerified(verificationId, originUri,
                                    PackageManager.VERIFICATION_REJECT, null,
                                    params.mDataLoaderType, user);
                            params.setReturnCode(
                                    PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
                            state.setVerifierResponse(Binder.getCallingUid(),
                                    PackageManager.VERIFICATION_REJECT);
                        }

                        if (state.areAllVerificationsComplete()) {
                            mPendingVerification.remove(verificationId);
                        }

                        Trace.asyncTraceEnd(
                                TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);

                        params.handleVerificationFinished();

                    }
                    break;
                }

  延迟时间到了,就会处理CHECK_PENDING_VERIFICATION消息。当然如果验证者验证完毕之后,会发送PACKAGE_VERIFIED消息,它会进行验证完之后的状态处理。
  所以CHECK_PENDING_VERIFICATION消息处理首先判断对应的状态,state.isVerificationComplete()代表验证完成。state.timeoutExtended()代表超时延长。如果都没有,进行处理。
  getDefaultVerificationResponse(user)根据用户的配置,可能等于VERIFICATION_ALLOW或者VERIFICATION_REJECT。broadcastPackageVerified()是发送Intent.ACTION_PACKAGE_VERIFIED广播,通知验证结果。如果state.areAllVerificationsComplete()为true,则删除对应的对象状态。
  最后,调用VerificationParams对象params的handleVerificationFinished()方法。

        void handleVerificationFinished() {
            mWaitForVerificationToComplete = false;
            handleReturnCode();
        }

  可见也是将mWaitForVerificationToComplete = false,代表验证完成。
  再看一下VerificationParams的handleReturnCode()方法:

        @Override
        void handleReturnCode() {
            if (mWaitForVerificationToComplete || mWaitForIntegrityVerificationToComplete
                    || mWaitForEnableRollbackToComplete) {
                return;
            }
            sendVerificationCompleteNotification();
        }

  mWaitForVerificationToComplete 、mWaitForIntegrityVerificationToComplete这俩咱们知道是什么意思了,mWaitForEnableRollbackToComplete呢?它是发送回退是否完成。
  它和系统服务RollbackManagerService相关,实现在RollbackManagerServiceImpl类中。在它里面会注册Intent.ACTION_PACKAGE_ENABLE_ROLLBACK广播。
  应用如果安装过程中设置了PackageManager.INSTALL_ENABLE_ROLLBACK标识,它会发送Intent.ACTION_PACKAGE_ENABLE_ROLLBACK广播,这样在RollbackManagerServiceImpl类中会收到广播,它会检查对应应用的相关状态。哪些条件,允许呢?第一种情况,安装者被授权MANAGE_ROLLBACKS权限并且被安装的应用要么在系统配置白名单中、要么是模块。除了第一种情况允许安装之外,还有安装者被授权TEST_MANAGE_ROLLBACKS权限。
  当这些检查完毕,得到结果之后,会调用PackageManagerService中的setEnableRollbackCode(int token, int enableRollbackCode)方法,来通知PackageManagerService结果。
  PackageManagerService收到结果之后,会将mWaitForEnableRollbackToComplete设置为true。

验证完毕之后回调

  等这些结果都检测完毕之后,会调用VerificationParams对象的成员observer的函数onPackageInstalled方法,通知之前PackageInstallerSession对象验证结果。看一下相关代码:

            localObserver = 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 == INSTALL_SUCCEEDED) {
                        onVerificationComplete();
                    } else {
                        onSessionVerificationFailure(returnCode, msg);
                    }
                }
            };

  可以看到验证成功之后,会调用onVerificationComplete();验证失败调用onSessionVerificationFailure(returnCode, msg)。
  看一下成功的代码:

    private void onVerificationComplete() {
        // Staged sessions will be installed later during boot
        if (isStaged()) {
            // TODO(b/136257624): Remove this once all verification logic has been transferred out
            //  of StagingManager.
            mStagingManager.notifyPreRebootVerification_Apk_Complete(mStagedSession);
            // TODO(b/136257624): We also need to destroy internals for verified staged session,
            //  otherwise file descriptors are never closed for verified staged session until reboot
            return;
        }

        install();
    }

  它接着调用install()即将进行正式的安装过程了。
  再看一下,验证失败执行的代码:

    private void onSessionVerificationFailure(int error, String msg) {
        final String msgWithErrorCode = PackageManager.installStatusToString(error, msg);
        Slog.e(TAG, "Failed to verify session " + sessionId + " [" + msgWithErrorCode + "]");
        // Session is sealed and committed but could not be verified, we need to destroy it.
        destroyInternal();
        if (isStaged()) {
            mStagedSession.setSessionFailed(
                    SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, msgWithErrorCode);
            // TODO(b/136257624): Remove this once all verification logic has been transferred out
            //  of StagingManager.
            mStagingManager.notifyVerificationComplete(mStagedSession);
        } else {
            // Dispatch message to remove session from PackageInstallerService.
            dispatchSessionFinished(error, msg, null);
        }
    }

  先调用destroyInternal(),清除一些状态和文件,然后调用dispatchSessionFinished(error, msg, null),将结果进行通知。
  先看下destroyInternal(),

    private void destroyInternal() {
        final IncrementalFileStorages incrementalFileStorages;
        synchronized (mLock) {
            mSealed = true;
            if (!params.isStaged) {
                mDestroyed = true;
            }
            // Force shut down all bridges
            for (RevocableFileDescriptor fd : mFds) {
                fd.revoke();
            }
            for (FileBridge bridge : mBridges) {
                bridge.forceClose();
            }
            incrementalFileStorages = mIncrementalFileStorages;
            mIncrementalFileStorages = null;
        }
        // For staged sessions, we don't delete the directory where the packages have been copied,
        // since these packages are supposed to be read on reboot.
        // Those dirs are deleted when the staged session has reached a final state.
        if (stageDir != null && !params.isStaged) {
            try {
                if (incrementalFileStorages != null) {
                    incrementalFileStorages.cleanUpAndMarkComplete();
                }
                mPm.mInstaller.rmPackageDir(stageDir.getAbsolutePath());
            } catch (InstallerException ignored) {
            }
        }
    }

  将mSealed = true,如果不是缓存安装,会将mDestroyed = true。
  接着会将复制文件使用的mFds撤销。mBridges关闭。
  如果不是缓存安装,会将安装目录中的文件进行删除。
  再看下dispatchSessionFinished(error, msg, null)的实现:

    private void dispatchSessionFinished(int returnCode, String msg, Bundle extras) {
        sendUpdateToRemoteStatusReceiver(returnCode, msg, extras);

        synchronized (mLock) {
            mFinalStatus = returnCode;
            mFinalMessage = msg;
        }

        final boolean success = (returnCode == INSTALL_SUCCEEDED);

        // Send broadcast to default launcher only if it's a new install
        // TODO(b/144270665): Secure the usage of this broadcast.
        final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING);
        if (success && isNewInstall && mPm.mInstallerService.okToSendBroadcasts()) {
            mPm.sendSessionCommitBroadcast(generateInfoScrubbed(true /*icon*/), userId);
        }

        mCallback.onSessionFinished(this, success);
        if (isDataLoaderInstallation()) {
            logDataLoaderInstallationSession(returnCode);
        }
    }

  sendUpdateToRemoteStatusReceiver(returnCode, msg, extras)是向应用方通知对应的结果了。我们知道,在安装进程中Activity InstallInstalling中显示安装界面时,它会生成PendingIntent对象,并且将它commit到系统进程中,它在进程中对应的代理对象是PackageInstallerSession对象的成员mRemoteStatusReceiver。现在可以通过它向应用进程发送结果通知。而这里通过sendUpdateToRemoteStatusReceiver(returnCode, msg, extras)实现。
  并会将成员变量mFinalStatus和mFinalMessage 设置为对应值。
  接下来,如果是新的安装成功,会向Launcher发送确认广播。mPm.sendSessionCommitBroadcast(generateInfoScrubbed(true /icon/), userId)就是用来做这个的。
  然后,调用回调mCallback的onSessionFinished()方法。mCallback的定义实现在PackageInstallerService类文件中。看下它的代码实现:

        public void onSessionFinished(final PackageInstallerSession session, boolean success) {
            mCallbacks.notifySessionFinished(session.sessionId, session.userId, success);

            mInstallHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (session.isStaged() && !success) {
                        mStagingManager.abortSession(session.mStagedSession);
                    }
                    synchronized (mSessions) {
                        if (!session.isStaged() || !success) {
                            mSessions.remove(session.sessionId);
                        }
                        addHistoricalSessionLocked(session);

                        final File appIconFile = buildAppIconFile(session.sessionId);
                        if (appIconFile.exists()) {
                            appIconFile.delete();
                        }

                        mSettingsWriteRequest.runNow();
                    }
                }
            });
        }

  mCallbacks是Callbacks类型。如果其他调用PackageInstallerService对象的register(IPackageInstallerCallback callback, IntPredicate userCheck),则现在会通过对应的回调通知它。
  接着如果安装session不是缓存,则会将它从mSessions中删除。如果是缓存,并且是失败情况,也会删除掉它。
  addHistoricalSessionLocked()会将安装者的安装次数记录在mHistoricalSessionsByInstaller中。
  然后将app的icon文件删除。
  接着调用mSettingsWriteRequest.runNow(),立即执行写入操作,它会将session相关信息从文件中去除。

总结

  首先会将相关安装信息封装成一个VerificationParams对象,然后会发送完整性验证、有可能发送包验证请求,之所以说是有可能,是因为它是有条件的。这些条件包括不是V4签名、不是增量安装、系统配置的验证者。还有可能发送应用回退请求。
  这些请求处理的流程都是相似的,对应的处理者处理完毕会发送应答。如果超时会有超时处理,这里面细节太多,需要好好理解揣摩,以上这些就是安装之前的验证过程。

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值