installPackagesLI
private void installPackagesTracedLI(List requests) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
installPackagesLI(requests);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
private void installPackagesLI(List requests) {
....
try {
for (InstallRequest request : requests) {
....
final PrepareResult prepareResult;
try {
//1.成功准备好的安装软件包所需的数据集。这包括将用于扫描和协调包的数据。
prepareResult = preparePackageLI(request.args, request.installResult);
}
....
try {
//2.根据prepare中收集的上下文查询解析后的包
final List scanResults = scanPackageTracedLI(
prepareResult.packageToScan, prepareResult.parseFlags,
prepareResult.scanFlags, System.currentTimeMillis(),
request.args.user);
....
} catch (PackageManagerException e) {
request.installResult.setError("Scanning Failed.", e);
return;
}
}
//3.协调,检查安装包状态确保安装成功
ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
installResults,
prepareResults,
mSharedLibraries,
Collections.unmodifiableMap(mPackages), versionInfos,
lastStaticSharedLibSettings);
CommitRequest commitRequest = null;
synchronized (mPackages) {
Map reconciledPackages;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
reconciledPackages = reconcilePackagesLocked(
reconcileRequest, mSettings.mKeySetManagerService);
}
....
}
//4.提交
executePostCommitSteps(commitRequest);
}
....
}
private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
throws PrepareFailure {
.....
//解析包AndroidManifest.xml文件,签名信息等。
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setDisplayMetrics(mMetrics);
pp.setCallback(mPackageParserCallback);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
final PackageParser.Package pkg;
try {
pkg = pp.parsePackage(tmpPackageFile, parseFlags);
DexMetadataHelper.validatePackageDexMetadata(pkg);
} catch (PackageParserException e) {
throw new PrepareFailure("Failed parse during installPackageLI", e);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
.....
//冻结安装包
final PackageFreezer freezer =
freezePackageForInstall(pkgName, installFlags, "installPackageLI");
boolean shouldCloseFreezerBeforeReturn = true;
try {
if (replace) {
//更新包配置
...
//如果是更新包还会判断是不是系统APP
sysPkg = (isSystemApp(oldPackage));
if (sysPkg) {
...
}
} else {
//新包安装配置
...
}
....
//返回安装包的数据集
return new PrepareResult(args.installReason, targetVolumeUuid, installerPackageName,
args.user, replace, targetScanFlags, targetParseFlags, existingPackage, pkg,
replace /* clearCodeCache */, sysPkg, renamedPackage, freezer,
ps, disabledPs, childPackages);
}
preparePackageLI最主要的是
pkg = pp.parsePackage(tmpPackageFile, parseFlags);
\frameworks\base\core\java\android\content\pm\PackageParser.java
public Package parsePackage(File packageFile, int flags) throws PackageParserException {
return parsePackage(packageFile, flags, false /* useCaches */);
}
public Package parsePackage(File packageFile, int flags, boolean useCaches)
throws PackageParserException {
....
if (packageFile.isDirectory()) {
parsed = parseClusterPackage(packageFile, flags);
} else {
//只有一个包走这里
parsed = parseMonolithicPackage(packageFile, flags);
}
....
return parsed;
}
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
....
try {
final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
pkg.setCodePath(apkFile.getCanonicalPath());
pkg.setUse32bitAbi(lite.use32bitAbi);
return pkg;
}
....
}
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
try {
....
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final Resources res = new Resources(assets, mMetrics, null);
final String[] outError = new String[1];
final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
if (pkg == null) {
throw new PackageParserException(mParseError,
apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
}
pkg.setVolumeUuid(volumeUuid);
pkg.setApplicationVolumeUuid(volumeUuid);
pkg.setBaseCodePath(apkPath);
pkg.setSigningDetails(SigningDetails.UNKNOWN);
return pkg;
}
....
}
parseBaseApk是具体的解析方法,这里的ANDROID_MANIFEST_FILENAME就是manifest文件了
public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
这里也去解析了资源文件等,最后都赋给了pkg这个Package对象,和Android四大组件相关的信息分别由activites、receivers、providers、services的list保存。
根据prepare中收集的上下文查询已解析的包。
扫描阶段会填充PackageSetting对象,PackageSetting生成之后会被记录到文件中,以后每次系统启动都会重新加载。
验证安装包状态,以确保安装成功。协调新旧包,删除旧的package。
private void commitPackagesLocked(final CommitRequest request) {
for (ReconciledPackage reconciledPkg : request.reconciledPackages.values()) {
if (reconciledPkg.prepareResult.replace) {
PackageParser.Package oldPackage = mPackages.get(packageName);
// 1.设置安装和更新时间
PackageSetting deletedPkgSetting = (PackageSetting) oldPackage.mExtras;
setInstallAndUpdateTime(pkg, deletedPkgSetting.firstInstallTime,
System.currentTimeMillis());
//系统应用
if (reconciledPkg.prepareResult.system) {
// 2.系统应用-移除现有包,后面还会移除子包(已省略)
removePackageLI(oldPackage, true);
.....
}
} else {
try {
//3.非系统应用-删除包
executeDeletePackageLIF(reconciledPkg.deletePackageAction, packageName,
true, request.mAllUsers, true, pkg);
}
....
}
}
//4.提交包扫描并修改系统状态
commitReconciledScanResultLocked(reconciledPkg);
updateSettingsLI(pkg, reconciledPkg.installArgs.installerPackageName, request.mAllUsers,
res, reconciledPkg.installArgs.user, reconciledPkg.installArgs.installReason);
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null) {
res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
ps.setUpdateAvailable(false /*updateAvailable*/);
}
....
}
}
提交阶段第4步比较关键。前面3阶段填充了Package对象和PackageSetting对象数据,现在需要将这些数据提交。
4.4 commitReconciledScanResultLocked(reconciledPkg);
private void commitReconciledScanResultLocked(@NonNull ReconciledPackage reconciledPkg) {
....
commitPackageSettings(pkg, oldPkg, pkgSetting, scanFlags,
(parseFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/, reconciledPkg);
....
}
//将扫描包添加到系统中。当这个方法完成时,包将会可用于查询,解决等…
private void commitPackageSettings(PackageParser.Package pkg,
@Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting,
final @ScanFlags int scanFlags, boolean chatty, ReconciledPackage reconciledPkg) {
....
synchronized (mPackages) {
//添加新的设置到mSettings
mSettings.insertPackageSettingLPw(pkgSetting, pkg);
//将新设置添加到mPackages中
mPackages.put(pkg.applicationInfo.packageName, pkg);
//将包的键集添加到全局KeySetManagerService
KeySetManagerService ksms = mSettings.mKeySetManagerService;
ksms.addScannedPackageLPw(pkg);
mComponentResolver.addAllComponents(pkg, chatty);
.....
}
}
在此之前,四大组件信息等安装包信息都属于Package的私有财产,现在需要把它们登记注册到PKMS内部的财产管理对象中。这样,PKMS就可对外提供统一的组件信息,而不必拘泥于具体的Package。
private void executePostCommitSteps(CommitRequest commitRequest) {
for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
.....
//1.安装并准备/data/data下的文件夹
prepareAppDataAfterInstallLIF(pkg);
....
//2.dex2oat操作,用来将apk中的dex文件转换为oat文件
final boolean performDexopt =
(!instantApp || Global.getInt(mContext.getContentResolver(),
Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
&& ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0);
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");
// 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(packageName,
REASON_INSTALL,
DexoptOptions.DEXOPT_BOOT_COMPLETE
| DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE);
mPackageDexOptimizer.performDexOpt(pkg,
null /* instructionSets */,
getOrCreateCompilerPackageStats(pkg),
mDexManager.getPackageUseInfoOrDefault(packageName),
dexoptOptions);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
...
}
}
prepareAppDataAfterInstallLIF(pkg);
private void prepareAppDataAfterInstallLIF(PackageParser.Package pkg) {
....
final UserManagerService um = sUserManager;
UserManagerInternal umInternal = getUserManagerInternal();
for (UserInfo user : um.getUsers(false /* excludeDying */)) {
final int flags;
if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
} else if (umInternal.isUserRunning(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE;
} else {
continue;
}
if (ps.getInstalled(user.id)) {
// TODO: when user data is locked, mark that we're still dirty
prepareAppDataLIF(pkg, user.id, flags);
}
}
}
private void prepareAppDataLIF(PackageParser.Package pkg, int userId, int flags) {
if (pkg == null) {
Slog.wtf(TAG, "Package was null!", new Throwable());
return;
}
prepareAppDataLeafLIF(pkg, userId, flags);
....
}
private void prepareAppDataAndMigrateLIF(PackageParser.Package pkg, int userId, int flags,
boolean maybeMigrateAppData) {
prepareAppDataLIF(pkg, userId, flags);
if (maybeMigrateAppData && maybeMigrateAppDataLIF(pkg, userId)) {
// We may have just shuffled around app data directories, so
// prepare them one more time
prepareAppDataLIF(pkg, userId, flags);
}
}
private void prepareAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
...
try {
ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
appId, seInfo, app.targetSdkVersion);
}
...
}
跟到最后发现是交给mInstaller去做的,这里的mInstaller是个Binder代理对象,具体实现在\frameworks\native\cmds\installd\InstalldNativeService.cpp
std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) {
std::string data(create_data_path(volume_uuid));
if (volume_uuid == nullptr && userid == 0) {
std::string legacy = StringPrintf("%s/data", data.c_str());
struct stat sb;
if (lstat(legacy.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) {
/* /data/data is dir, return /data/data for legacy system */
return legacy;
}
}
return StringPrintf("%s/user/%u", data.c_str(), userid);
}
这里返回data/data
第5步executePostCommitSteps就是去建立用户数据文件夹,data/data;使用 dex2oat 把App编译成 oat 文件,并保存在 dalvik-cache 目录里;发送ACTION_PACKAGE_ADDED、ACTION_PACKAGE_REPLACED广播等等操作。