// [InstallParams.handleStartCopy]
if (origin.staged) {if (origin.file != null) {installFlags |= PackageManager.INSTALL_INTERNAL;installFlags &= ~PackageManager.INSTALL_EXTERNAL;} else if (origin.cid != null) {installFlags |= PackageManager.INSTALL_EXTERNAL;installFlags &= ~PackageManager.INSTALL_INTERNAL;} else {throw new IllegalStateException("Invalid stage location");}
}
3 然后檢查空間大小,如果空間不夠則釋放無用空間。
// [InstallParams.handleStartCopy]
if (!origin.staged && pkgLite.recommendedInstallLocation== PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {// TODO: focus freeing disk space on the target devicefinal StorageManager storage = StorageManager.from(mContext);final long lowThreshold = storage.getStorageLowBytes(Environment.getDataDirectory());final long sizeBytes = mContainerService.calculateInstalledSize(origin.resolvedPath, isForwardLocked(), packageAbiOverride);try {mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0);pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath,installFlags, packageAbiOverride);} catch (InstallerException e) {Slog.w(TAG, "Failed to free cache", e);}if (pkgLite.recommendedInstallLocation== PackageHelper.RECOMMEND_FAILED_INVALID_URI) {pkgLite.recommendedInstallLocation= PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;}
}
4 覆蓋原有安裝位置的文件,并根據返回結果來確定函數的返回值,并設置installFlags。
// [InstallParams.handleStartCopy]
// Override with defaults if needed.
loc = installLocationPolicy(pkgLite);
if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
} else if (!onSd && !onInt) {// Override install location with flagsif (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {// Set the flag to install on external media.installFlags |= PackageManager.INSTALL_EXTERNAL;installFlags &= ~PackageManager.INSTALL_INTERNAL;} else if (loc == PackageHelper.RECOMMEND_INSTALL_EPHEMERAL) {if (DEBUG_EPHEMERAL) {Slog.v(TAG, "...setting INSTALL_EPHEMERAL install flag");}installFlags |= PackageManager.INSTALL_INSTANT_APP;installFlags &= ~(PackageManager.INSTALL_EXTERNAL|PackageManager.INSTALL_INTERNAL);} else {// Make sure the flag for installing on external// media is unsetinstallFlags |= PackageManager.INSTALL_INTERNAL;installFlags &= ~PackageManager.INSTALL_EXTERNAL;}
}
private void processPendingInstall(final InstallArgs args, final int currentStatus) {// Queue up an async operation since the package installation may take a little while.mHandler.post(new Runnable() {public void run() {mHandler.removeCallbacks(this);// Result object to be returnedPackageInstalledInfo res = new PackageInstalledInfo();res.setReturnCode(currentStatus);res.uid = -1;res.pkg = null;res.removedInfo = null;if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {args.doPreInstall(res.returnCode);synchronized (mInstallLock) {installPackageTracedLI(args, res);}args.doPostInstall(res.returnCode, res.uid);//......
}
//[PMS.installPackageLI]
//檢查SDK版本和沙箱版本
if (instantApp && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {Slog.w(TAG, "Instant app package " + pkg.packageName + " does not target O");res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,"Instant app package must target O");return;
}
if (instantApp && pkg.applicationInfo.targetSandboxVersion != 2) {Slog.w(TAG, "Instant app package " + pkg.packageName+ " does not target targetSandboxVersion 2");res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,"Instant app package must use targetSanboxVersion 2");return;
}
//檢查是否有靜態共享庫
if (pkg.applicationInfo.isStaticSharedLibrary()) {// Static shared libraries have synthetic package namesrenameStaticSharedLibraryPackage(pkg);// No static shared libs on external storageif (onExternal) {Slog.i(TAG, "Static shared libs can only be installed on internal storage.");res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,"Packages declaring static-shared libs cannot be updated");return;}
}
4 檢查是否有子安裝包,如有則子安裝包也需要檢測。
//[PMS.installPackageLI]
// If we are installing a clustered package add results for the children
if (pkg.childPackages != null) {synchronized (mPackages) {final int childCount = pkg.childPackages.size();for (int i = 0; i < childCount; i++) {PackageParser.Package childPkg = pkg.childPackages.get(i);PackageInstalledInfo childRes = new PackageInstalledInfo();childRes.setReturnCode(PackageManager.INSTALL_SUCCEEDED);childRes.pkg = childPkg;childRes.name = childPkg.packageName;PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);if (childPs != null) {childRes.origUsers = childPs.queryInstalledUsers(sUserManager.getUserIds(), true);}if ((mPackages.containsKey(childPkg.packageName))) {childRes.removedInfo = new PackageRemovedInfo(this);childRes.removedInfo.removedPackage = childPkg.packageName;childRes.removedInfo.installerPackageName = childPs.installerPackageName;}if (res.addedChildPackages == null) {res.addedChildPackages = new ArrayMap<>();}res.addedChildPackages.put(childPkg.packageName, childRes);}}
}
5 檢查安裝包是否已存在,如已存在則需要檢查舊的父包、沙箱、sdk等是否已為空,否則會報錯。
6 校驗安裝包簽名
//[PMS.installPackageLI]
PackageSetting signatureCheckPs = ps;
if (pkg.applicationInfo.isStaticSharedLibrary()) {SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);if (libraryEntry != null) {signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);}
}// Quick sanity check that we're signed correctly if updating;
// we'll check this again later when scanning, but we want to
// bail early here before tripping over redefined permissions.
if (shouldCheckUpgradeKeySetLP(signatureCheckPs, scanFlags)) {if (!checkUpgradeKeySetLP(signatureCheckPs, pkg)) {res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "+ pkg.packageName + " upgrade keys do not match the "+ "previously installed version");return;}
} else {try {verifySignaturesLP(signatureCheckPs, pkg);} catch (PackageManagerException e) {res.setError(e.error, e.getMessage());return;}
}
7 設置相關的全向,包括生成權限、移植權限等
8 如果這是一個系統應用,則檢查是否在外部存儲上或是是否被其他應用替換等
//[PMS.installPackageLI]
if (systemApp) {if (onExternal) {// Abort update; system app can't be replaced with app on sdcardres.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,"Cannot install updates to system apps on sdcard");return;} else if (instantApp) {// Abort update; system app can't be replaced with an instant appres.setError(INSTALL_FAILED_INSTANT_APP_INVALID,"Cannot update a system app with an instant app");return;}
}
//[PMS.installPackageLI]
final boolean performDexopt = (res.returnCode == PackageManager.INSTALL_SUCCEEDED)&& !forwardLocked&& !pkg.applicationInfo.isExternalAsec()&& (!instantApp || Global.getInt(mContext.getContentResolver(),Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)&& ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0);if (performDexopt) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
// Do not run PackageDexOptimizer through the local performDexOpt
// method because `pkg` may not be in `mPackages` yet.
//
// Also, don't fail application installs if the dexopt step fails.
DexoptOptions dexoptOptions = new DexoptOptions(pkg.packageName,REASON_INSTALL,DexoptOptions.DEXOPT_BOOT_COMPLETE |DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE);
mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,null /* instructionSets */,getOrCreateCompilerPackageStats(pkg),mDexManager.getPackageUseInfoOrDefault(pkg.packageName),dexoptOptions);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,"installPackageLI")) {if (replace) {if (pkg.applicationInfo.isStaticSharedLibrary()) {// Static libs have a synthetic package name containing the version// and cannot be updated as an update would get a new package name,// unless this is the exact same version code which is useful for// development.PackageParser.Package existingPkg = mPackages.get(pkg.packageName);if (existingPkg != null && existingPkg.mVersionCode != pkg.mVersionCode) {res.setError(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring "+ "static-shared libs cannot be updated");return;}}replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,installerPackageName, res, args.installReason);} else {installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,args.user, installerPackageName, volumeUuid, res, args.installReason);}
}
private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,PackageInstalledInfo res, int installReason) {Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");// Remember this for later, in case we need to rollback this installString pkgName = pkg.packageName;if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);synchronized(mPackages) {final String renamedPackage = mSettings.getRenamedPackageLPr(pkgName);if (renamedPackage != null) {// 如果已有相同包名的應用,則報錯res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName+ " without first uninstalling package running as "+ renamedPackage);return;}if (mPackages.containsKey(pkgName)) {// Don't allow installation over an existing package with the same name.res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName+ " without first uninstalling.");return;}}try {PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags, System.currentTimeMillis(), user);updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason);if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {prepareAppDataAfterInstallLIF(newPackage);} else {// Remove package from internal structures, but keep around any// data that might have already existeddeletePackageLIF(pkgName, UserHandle.ALL, false, null,PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);}} catch (PackageManagerException e) {res.setError("Package couldn't be installed in " + pkg.codePath, e);}Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
14 然后為已安裝的應用準備數據目錄,其依次的順序是
PMS.prepareAppDataAfterInstallLIF
PMS.prepareAppDataLIF
PMS.prepareAppDataLeafLIF
Installer.createAppData
這個方法是PMS與Installer交互的接口函數,這里的數據目錄是CE類型。
private void prepareAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {if (DEBUG_APP_DATA) {Slog.v(TAG, "prepareAppData for " + pkg.packageName + " u" + userId + " 0x"+ Integer.toHexString(flags));}final String volumeUuid = pkg.volumeUuid;final String packageName = pkg.packageName;final ApplicationInfo app = pkg.applicationInfo;final int appId = UserHandle.getAppId(app.uid);Preconditions.checkNotNull(app.seInfo);long ceDataInode = -1;try {// 調用Installd守護進程的入口ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,appId, app.seInfo, app.targetSdkVersion);} catch (InstallerException e) {//......}// Prepare the application profiles.mArtManagerService.prepareAppProfiles(pkg, userId);if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) {// TODO: mark this structure as dirty so we persist it!synchronized (mPackages) {final PackageSetting ps = mSettings.mPackages.get(packageName);if (ps != null) {ps.setCeDataInode(ceDataInode, userId);}}}prepareAppDataContentsLeafLIF(pkg, userId, flags);
}
@Override
protected void onResume() {super.onResume();// This is the first onResume in a single life of the activityif (mInstallingTask == null) {PackageInstaller installer = getPackageManager().getPackageInstaller();PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);//如果session非空,則執行AsyncTaskif (sessionInfo != null && !sessionInfo.isActive()) {mInstallingTask = new InstallingAsyncTask();mInstallingTask.execute();} else {// we will receive a broadcast when the install is finishedmCancelButton.setEnabled(false);setFinishOnTouchOutside(false);}}
}