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

2024-06-17 07:28

本文主要是介绍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()的源代码:

    @Nullableprivate PackageManagerService.VerificationParams prepareForVerification()throws PackageManagerException {assertNotLocked("makeSessionActive");@UserActionRequirementint userActionRequirement = USER_ACTION_NOT_NEEDED;// TODO(b/159331446): Move this to makeSessionActiveForInstall and update javadocif (!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()方法,它的代码如下:

    @UserActionRequirementprivate 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 casesreturn 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()的代码:

    @Nullableprivate 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 necessaryif (!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() {@Overridepublic void onUserActionRequired(Intent intent) {throw new IllegalStateException();}@Overridepublic 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 StagingManagermRet = 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() {@Overridepublic 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 appUserHandle 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 statefinal 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() {@Overridepublic 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 ADBif ((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 installsif ((installFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0) {synchronized (mLock) {if (mSettings.getPackageLPr(pkgInfoLite.packageName) == null) {// Always verify fresh installreturn true;}}// Only skip when apk is debuggablereturn !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()方法:

        @Overridevoid 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() {@Overridepublic void onUserActionRequired(Intent intent) {throw new IllegalStateException();}@Overridepublic 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 bootif (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 rebootreturn;}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 bridgesfor (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() {@Overridepublic 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签名、不是增量安装、系统配置的验证者。还有可能发送应用回退请求。
  这些请求处理的流程都是相似的,对应的处理者处理完毕会发送应答。如果超时会有超时处理,这里面细节太多,需要好好理解揣摩,以上这些就是安装之前的验证过程。

这篇关于Android 安装过程四 MSG_INSTALL消息的处理 安装之前的验证的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1068812

相关文章

ESP32 esp-idf esp-adf环境安装及.a库创建与编译

简介 ESP32 功能丰富的 Wi-Fi & 蓝牙 MCU, 适用于多样的物联网应用。使用freertos操作系统。 ESP-IDF 官方物联网开发框架。 ESP-ADF 官方音频开发框架。 文档参照 https://espressif-docs.readthedocs-hosted.com/projects/esp-adf/zh-cn/latest/get-started/index

Linux 安装、配置Tomcat 的HTTPS

Linux 安装 、配置Tomcat的HTTPS 安装Tomcat 这里选择的是 tomcat 10.X ,需要Java 11及更高版本 Binary Distributions ->Core->选择 tar.gz包 下载、上传到内网服务器 /opt 目录tar -xzf 解压将解压的根目录改名为 tomat-10 并移动到 /opt 下, 形成个人习惯的路径 /opt/tomcat-10

C/C++的编译和链接过程

目录 从源文件生成可执行文件(书中第2章) 1.Preprocessing预处理——预处理器cpp 2.Compilation编译——编译器cll ps:vs中优化选项设置 3.Assembly汇编——汇编器as ps:vs中汇编输出文件设置 4.Linking链接——链接器ld 符号 模块,库 链接过程——链接器 链接过程 1.简单链接的例子 2.链接过程 3.地址和

VMware9.0详细安装

双击VMware-workstation-full-9.0.0-812388.exe文件: 直接点Next; 这里,我选择了Typical(标准安装)。 因为服务器上只要C盘,所以我选择安装在C盘下的vmware文件夹下面,然后点击Next; 这里我把√取消了,每次启动不检查更新。然后Next; 点击Next; 创建快捷方式等,点击Next; 继续Cont

vcpkg安装opencv中的特殊问题记录(无法找到opencv_corexd.dll)

我是按照网上的vcpkg安装opencv方法进行的(比如这篇:从0开始在visual studio上安装opencv(超详细,针对小白)),但是中间出现了一些别人没有遇到的问题,虽然原因没有找到,但是本人给出一些暂时的解决办法: 问题1: 我在安装库命令行使用的是 .\vcpkg.exe install opencv 我的电脑是x64,vcpkg在这条命令后默认下载的也是opencv2:x6

【服务器运维】CentOS6 minimal 离线安装MySQL5.7

1.准备安装包(版本因人而异,所以下面的命令中版本省略,实际操作中用Tab自动补全就好了) cloog-ppl-0.15.7-1.2.el6.x86_64.rpmcpp-4.4.7-23.el6.x86_64.rpmgcc-4.4.7-23.el6.x86_64.rpmgcc-c++-4.4.7-23.el6.x86_64.rpmglibc-2.12-1.212.el6.x86_64.r

【服务器运维】CentOS7 minimal 离线安装 gcc perl vmware-tools

0. 本机在有网的情况下,下载CentOS镜像 https://www.centos.org/download/ 1. 取出rpm 有的情况可能不需要net-tools,但是如果出现跟ifconfig相关的错误,就把它安装上。另外如果不想升级内核版本的话,就找对应内核版本的rpm版本安装 perl-Time-Local-1.2300-2.el7.noarch.rpmperl-Tim

Windows/macOS/Linux 安装 Redis 和 Redis Desktop Manager 可视化工具

本文所有安装都在macOS High Sierra 10.13.4进行,Windows安装相对容易些,Linux安装与macOS类似,文中会做区分讲解 1. Redis安装 1.下载Redis https://redis.io/download 把下载的源码更名为redis-4.0.9-source,我喜欢跟maven、Tomcat放在一起,就放到/Users/zhan/Documents

Ubuntu20.04离线安装Docker

1.下载3个docker离线安装包,下载网址: https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/ 2.把3个离线安装包拷贝到ubuntu本地执行以下命令 sudo dpkg -i containerd.io_1.4.6-1_amd64.deb sudo dpkg -i docker-ce-c

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开