由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签名、不是增量安装、系统配置的验证者。还有可能发送应用回退请求。
这些请求处理的流程都是相似的,对应的处理者处理完毕会发送应答。如果超时会有超时处理,这里面细节太多,需要好好理解揣摩,以上这些就是安装之前的验证过程。