Android 安装应用-提交阶段之后剩下的操作
/**
* On successful install, executes remaining steps after commit completes and the package lock
* is released. These are typically more expensive or require calls to installd, which often
* locks on {@link #mLock}.
*/
private void executePostCommitSteps(CommitRequest commitRequest) {
final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>();
for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
final boolean instantApp = ((reconciledPkg.scanResult.request.scanFlags
& PackageManagerService.SCAN_AS_INSTANT_APP) != 0);
final AndroidPackage pkg = reconciledPkg.pkgSetting.pkg;
final String packageName = pkg.getPackageName();
final String codePath = pkg.getPath();
final boolean onIncremental = mIncrementalManager != null
&& isIncrementalPath(codePath);
if (onIncremental) {
IncrementalStorage storage = mIncrementalManager.openStorage(codePath);
if (storage == null) {
throw new IllegalArgumentException(
"Install: null storage for incremental package " + packageName);
}
incrementalStorages.add(storage);
}
prepareAppDataAfterInstallLIF(pkg);
if (reconciledPkg.prepareResult.clearCodeCache) {
clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
| FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
if (reconciledPkg.prepareResult.replace) {
mDexManager.notifyPackageUpdated(pkg.getPackageName(),
pkg.getBaseApkPath(), pkg.getSplitCodePaths());
}
// Prepare the application profiles for the new code paths.
// This needs to be done before invoking dexopt so that any install-time profile
// can be used for optimizations.
mArtManagerService.prepareAppProfiles(
pkg,
resolveUserIds(reconciledPkg.installArgs.user.getIdentifier()),
/* updateReferenceProfileContent= */ true);
// Compute the compilation reason from the installation scenario.
final int compilationReason = mDexManager.getCompilationReasonForInstallScenario(
reconciledPkg.installArgs.mInstallScenario);
// Construct the DexoptOptions early to see if we should skip running 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.
final boolean isBackupOrRestore =
reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_RESTORE
|| reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_SETUP;
final int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE
| DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE
| (isBackupOrRestore ? DexoptOptions.DEXOPT_FOR_RESTORE : 0);
DexoptOptions dexoptOptions =
new DexoptOptions(packageName, compilationReason, dexoptFlags);
// Check whether we need to dexopt the app.
//
// NOTE: it is IMPORTANT to call dexopt:
// - after doRename which will sync the package data from AndroidPackage and
// its corresponding ApplicationInfo.
// - after installNewPackageLIF or replacePackageLIF which will update result with the
// uid of the application (pkg.applicationInfo.uid).
// This update happens in place!
//
// We only need to dexopt if the package meets ALL of the following conditions:
// 1) it is not an instant app or if it is then dexopt is enabled via gservices.
// 2) it is not debuggable.
// 3) it is not on Incremental File System.
//
// Note that we do not dexopt instant apps by default. dexopt can take some time to
// complete, so we skip this step during installation. Instead, we'll take extra time
// the first time the instant app starts. It's preferred to do it this way to provide
// continuous progress to the useur instead of mysteriously blocking somewhere in the
// middle of running an instant app. The default behaviour can be overridden
// via gservices.
//
// Furthermore, dexopt may be skipped, depending on the install scenario and current
// state of the device.
//
// TODO(b/174695087): instantApp and onIncremental should be removed and their install
// path moved to SCENARIO_FAST.
final boolean performDexopt =
(!instantApp || Global.getInt(mContext.getContentResolver(),
Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
&& !pkg.isDebuggable()
&& (!onIncremental)
&& dexoptOptions.isCompilationEnabled();
if (performDexopt) {
// Compile the layout resources.
if (SystemProperties.getBoolean(PRECOMPILE_LAYOUTS, false)) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "compileLayouts");
mViewCompiler.compileLayouts(pkg);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
ScanResult result = reconciledPkg.scanResult;
// This mirrors logic from commitReconciledScanResultLocked, where the library files
// needed for dexopt are assigned.
// TODO: Fix this to have 1 mutable PackageSetting for scan/install. If the previous
// setting needs to be passed to have a comparison, hide it behind an immutable
// interface. There's no good reason to have 3 different ways to access the real
// PackageSetting object, only one of which is actually correct.
PackageSetting realPkgSetting = result.existingSettingCopied
? result.request.pkgSetting : result.pkgSetting;
if (realPkgSetting == null) {
realPkgSetting = reconciledPkg.pkgSetting;
}
// Unfortunately, the updated system app flag is only tracked on this PackageSetting
boolean isUpdatedSystemApp = reconciledPkg.pkgSetting.getPkgState()
.isUpdatedSystemApp();
realPkgSetting.getPkgState().setUpdatedSystemApp(isUpdatedSystemApp);
mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,
null /* instructionSets */,
getOrCreateCompilerPackageStats(pkg),
mDexManager.getPackageUseInfoOrDefault(packageName),
dexoptOptions);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
// Notify BackgroundDexOptService that the package has been changed.
// If this is an update of a package which used to fail to compile,
// BackgroundDexOptService will remove it from its denylist.
// TODO: Layering violation
BackgroundDexOptService.notifyPackageChanged(packageName);
notifyPackageChangeObserversOnUpdate(reconciledPkg);
}
waitForNativeBinariesExtraction(incrementalStorages);
}