// Getting the package setting may have a side-effect, so if we // are only checking if scan would succeed, stash a copy of the // old setting to restore at the end. staticfinalintSCAN_CHECK_ONLY=1<<15; staticfinalintSCAN_DONT_KILL_APP=1<<17; //与 DELETE_DONT_KILL_APP 关联, deletePackageX时不杀应用 staticfinalintSCAN_IGNORE_FROZEN=1<<18; // Sadly we don't know the package name yet to freeze it // Caller asked us to ignore frozen check for some reason; they // probably didn't know the package name // 不掉用 checkPackageFrozen
1.1.1.2.1. scanDirLI 函数
执行文件检查
1 2 3 4 5 6 7
finalbooleanisPackage= (isApkFile(file) || file.isDirectory()) // 排除stage file的情况, stage file不算 vmdl**.tmp smdl**.tmp smdl2tmp && !PackageInstallerService.isStageName(file.getName()); if (!isPackage) { // Ignore entries which are not packages continue; }
/** * Scans a package and returns the newly parsed package. * Returns {@code null} in case of errors and the error code is stored in mLastScanError */ private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags, long currentTime, UserHandle user)throws PackageManagerException { if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile); // 创建PackageParser PackageParserpp=newPackageParser(); pp.setSeparateProcesses(mSeparateProcesses); pp.setOnlyCoreApps(mOnlyCore); pp.setDisplayMetrics(mMetrics); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage"); final PackageParser.Package pkg; // 调用 parsePackage函数 pkg = pp. parsePackage函数(scanFile, parseFlags);
* Parse the package at the given location. Automatically detects if the * package is a monolithic style(single APK file) or cluster style // 聚合apk if (packageFile.isDirectory()) { return parseClusterPackage(packageFile, flags); } else { return parseMonolithicPackage(packageFile, flags); }
finalAssetManagerassets=newAssetManager(); try { // Load the base and all splits into the AssetManager // so that resources can be overriden when parsing the manifests. // 将lib库加载进 AssetManager 中 loadApkIntoAssetManager(assets, lite.baseCodePath, flags);
/* Set the global "forward lock" flag */ if ((flags & PARSE_FORWARD_LOCK) != 0) { pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK; }
/* Set the global "on SD card" flag */ if ((flags & PARSE_EXTERNAL_STORAGE) != 0) { pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE; }
// Resource boolean are -1, so 1 means we don't know the value. intsupportsSmallScreens=1; intsupportsNormalScreens=1; intsupportsLargeScreens=1; intsupportsXLargeScreens=1; intresizeable=1; intanyDensity=1;
intouterDepth= parser.getDepth(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; }
StringtagName= parser.getName();
...
if (tagName.equals(TAG_APPLICATION)) { // 只能有一个application节点 if (foundApp) { // 刚性解析,直接跳出 if (RIGID_PARSER) { outError[0] = "<manifest> has more than one <application>"; mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; returnnull; } else { Slog.w(TAG, "<manifest> has more than one <application>"); XmlUtils.skipCurrentTag(parser); continue; } }
if ((flags&PARSE_IS_SYSTEM) != 0) { // 只有 PARSE_IS_SYSTEM 标志的目录解析 带persistent的才会生效,常驻进程 if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_persistent, false)) { ai.flags |= ApplicationInfo.FLAG_PERSISTENT; } }
.... // debug标记 if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_debuggable, false)) { ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE; } ... // 默认为true. 除了特殊情况, An application would not have any code of its own only if it's using nothing but built-in component classes, 比如AliasActivity if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) { ai.flags |= ApplicationInfo.FLAG_HAS_CODE; }
if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData, true)) { ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA; }
// The parent package controls installation, hence specify test only installs. if (owner.parentPackage == null) { if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_testOnly, false)) { ai.flags |= ApplicationInfo.FLAG_TEST_ONLY; } }
if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_largeHeap, false)) { ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP; }
if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic, true)) { ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC; }
if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl, false/* default is no RTL support*/)) { ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL; }
if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_multiArch, false)) { ai.flags |= ApplicationInfo.FLAG_MULTIARCH; }
if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs, true)) { ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS; }
if (sa.getBoolean( R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage, false)) { ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE; } if (sa.getBoolean( R.styleable.AndroidManifestApplication_directBootAware, false)) { ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE; }
if (outError[0] == null) { CharSequence pname; if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) { pname = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifestApplication_process, Configuration.NATIVE_CONFIG_VERSION); } else { // Some older apps have been seen to use a resource reference // here that on older builds was ignored (with a warning). We // need to continue to do this for them so they don't break. pname = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestApplication_process); } //重设进程名? ai.processName = buildProcessName(ai.packageName, null, pname, flags, mSeparateProcesses, outError);
} elseif (tagName.equals("activity-alias")) { Activitya= parseActivityAlias(owner, res, parser, flags, outError); if (a == null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; returnfalse; }
owner.activities.add(a);
} elseif (parser.getName().equals("meta-data")) { // note: application meta-data is stored off to the side, so it can // remain null in the primary copy (we like to avoid extra copies because // it can be large) if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData, outError)) == null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; returnfalse; }
} elseif (tagName.equals("library")) { sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifestLibrary);
// Note: don't allow this value to be a reference to a resource // that may change. Stringlname= sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestLibrary_name);
sa.recycle();
if (lname != null) { lname = lname.intern(); if (!ArrayUtils.contains(owner.libraryNames, lname)) { owner.libraryNames = ArrayUtils.add(owner.libraryNames, lname); } }
XmlUtils.skipCurrentTag(parser);
} elseif (tagName.equals("uses-library")) { sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifestUsesLibrary);
// Note: don't allow this value to be a reference to a resource // that may change. Stringlname= sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestUsesLibrary_name); booleanreq= sa.getBoolean( com.android.internal.R.styleable.AndroidManifestUsesLibrary_required, true);
} elseif (tagName.equals("uses-package")) { // Dependencies for app installers; we don't currently try to // enforce this. XmlUtils.skipCurrentTag(parser);
} else { if (!RIGID_PARSER) { Slog.w(TAG, "Unknown element under <application>: " + tagName + " at " + mArchiveSourcePath + " " + parser.getPositionDescription()); XmlUtils.skipCurrentTag(parser); continue; } else { outError[0] = "Bad element under <application>: " + tagName; mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; returnfalse; } } }
An alias for an activity, named by the targetActivity attribute. The target must be in the same application as the alias and it must be declared before the alias in the manifest.
// Look to see if we already know about this package. StringoldName= mSettings.mRenamedPackages.get(pkg.packageName); if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) { // This package has been renamed to its original name. Let's // use that. ps = mSettings.peekPackageLPr(oldName); } // If there was no original package, see one for the real package name. if (ps == null) { ps = mSettings.peekPackageLPr(pkg.packageName); } // Check to see if this package could be hiding/updating a system // package. Must look for it either under the original or real // package name depending on our state. // 如果是hiding package updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName); if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg); }
if (ps != null && !ps.codePath.equals(scanFile)) { // The path has changed from what was last scanned... check the // version of the new path against what we have stored to determine // what to do. if (DEBUG_INSTALL) Slog.d(TAG, "Path changing from " + ps.codePath); // 当前扫描到的版本信息小于已安装版本信息 if (pkg.mVersionCode <= ps.versionCode) { // The system package has been updated and the code path does not match // Ignore entry. Skip it. if (DEBUG_INSTALL) Slog.i(TAG, "Package " + ps.name + " at " + scanFile + " ignored: updated version " + ps.versionCode + " better than this " + pkg.mVersionCode); if (!updatedPkg.codePath.equals(scanFile)) { Slog.w(PackageManagerService.TAG, "Code path for hidden system pkg " + ps.name + " changing from " + updatedPkg.codePathString + " to " + scanFile); // 更新path updatedPkg.codePath = scanFile; updatedPkg.codePathString = scanFile.toString(); updatedPkg.resourcePath = scanFile; updatedPkg.resourcePathString = scanFile.toString(); } updatedPkg.pkg = pkg; updatedPkg.versionCode = pkg.mVersionCode;
// Update the disabled system child packages to point to the package too. finalintchildCount= updatedPkg.childPackageNames != null ? updatedPkg.childPackageNames.size() : 0; for (inti=0; i < childCount; i++) { StringchildPackageName= updatedPkg.childPackageNames.get(i); PackageSettingupdatedChildPkg= mSettings.getDisabledSystemPkgLPr( childPackageName); if (updatedChildPkg != null) { updatedChildPkg.pkg = pkg; updatedChildPkg.versionCode = pkg.mVersionCode; } }
thrownewPackageManagerException(Log.WARN, "Package " + ps.name + " at " + scanFile + " ignored: updated version " + ps.versionCode + " better than this " + pkg.mVersionCode); }
if (updatedPkg != null) { // An updated system app will not have the PARSE_IS_SYSTEM flag set // initially policyFlags |= PackageParser.PARSE_IS_SYSTEM;
// An updated privileged app will not have the PARSE_IS_PRIVILEGED // flag set initially if ((updatedPkg.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) { policyFlags |= PackageParser.PARSE_IS_PRIVILEGED; } }
1.1.1.4.2.2. 进行证书验证
1 2
// Verify certificates against what was last scanned, 收集证书,并进行验证.验证文件内容和记录的hash值是否一致,不一致抛出异常. collectCertificatesLI(ps, pkg, scanFile, policyFlags);
if (!isSystemApp(pkg)) { // Only system apps can use these features. pkg.mOriginalPackages = null; pkg.mRealPackage = null; pkg.mAdoptPermissions = null; }
// mRenamedPackages 中保存了所有经过重命名的包名,以其realName为键值.保存了 original-package标签的名字. // mSetting对应过去的对象 finalStringrenamed= mSettings.mRenamedPackages.get(pkg.mRealPackage); // 当旧包名renamed包含在pkg. mOriginalPackages中时 if (pkg.mOriginalPackages.contains(renamed)) { // This package had originally been installed as the // original name, and we have already taken care of // transitioning to the new one. Just update the new // one to continue using the old name. realName = pkg.mRealPackage; // 如果当前包名不为 original-package , 就设为 original-package if (!pkg.packageName.equals(renamed)) { // Callers into this function may have already taken // care of renaming the package; only do it here if // it is not already done. // 沿用旧包名 pkg.setPackageName(renamed); } }
else { for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) { // 最终返回不符合下面条件的包名, origPackage后面构造PackageSetting时会用到 if ((origPackage = mSettings.peekPackageLPr( pkg.mOriginalPackages.get(i))) != null) { // We do have the package already installed under its // original name... should we use it? // 非系统目录返回失败,或者origPackage包当前已经安装的情况,会返回失败 if (!verifyPackageUpdateLPr(origPackage, pkg)) { // New package is not compatible with original. origPackage = null; continue; } elseif (origPackage.sharedUser != null) { // Make sure uid is compatible between packages. // sharedUserId项 和 之前的不匹配, if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) { Slog.w(TAG, "Unable to migrate data from " + origPackage.name + " to " + pkg.packageName + ": old uid " + origPackage.sharedUser.name + " differs from " + pkg.mSharedUserId); origPackage = null; continue; } // TODO: Add case when shared user id is added [b/28144775] } else { if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package " + pkg.packageName + " to old name " + origPackage.name); } break; } }
// 检查其upgradeKeySets是否有效 pkgSetting 作为olgPkg if (shouldCheckUpgradeKeySetLP(pkgSetting, scanFlags)) { // 检查PackageSettting和pkg中的签名是否一致 if (checkUpgradeKeySetLP(pkgSetting, pkg)) { // We just determined the app is signed correctly, so bring // over the latest parsed certs. pkgSetting.signatures.mSignatures = pkg.mSignatures; } else { // 不一致且为data app的情况. 抛出异常 if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { thrownewPackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package " + pkg.packageName + " upgrade keys do not match the " + "previously installed version"); } else { // 如果不一致,但pkg是system app, 直接替换掉旧签名 pkgSetting.signatures.mSignatures = pkg.mSignatures; Stringmsg="System package " + pkg.packageName + " signature changed; retaining data."; reportSettingsProblem(Log.WARN, msg); } } } else { // 包签名无效的情况, 验证签名 try { verifySignaturesLP(pkgSetting, pkg); // We just determined the app is signed correctly, so bring // over the latest parsed certs. // 验证通过,则替换到pkgSetting的签名为 pkg的签名 pkgSetting.signatures.mSignatures = pkg.mSignatures; } catch (PackageManagerException e) { if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { // data app直接往上抛异常 throw e; } // The signature has changed, but this package is in the system // image... let's recover! // 没有验证通过时, 如果为system app 仍然替换 pkgSetting.signatures.mSignatures = pkg.mSignatures; // However... if this package is part of a shared user, but it // doesn't match the signature of the shared user, let's fail. // What this means is that you can't change the signatures // associated with an overall shared user, which doesn't seem all // that unreasonable. if (pkgSetting.sharedUser != null) { // 如果其shareUserId不为空时, 如果shareuser 包对应的签名和当前pkg的签名不一致,抛出异常 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures, pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) { thrownewPackageManagerException( INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Signature mismatch for shared user: " + pkgSetting.sharedUser); } } }
// Some system apps still use directory structure for native libraries // in which case we might end up not detecting abi solely based on apk // structure. Try to detect abi based on directory structure. // 上面使用 derivePackageAbi 无效时, primaryCpuAbi 为null. 需要基于 目录结构 监测abi,并设定指令集 if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() && pkg.applicationInfo.primaryCpuAbi == null) { // 根据目录是否存在来设定指令集 setBundledAppAbisAndRoots(pkg, pkgSetting); // 更新 pkg.applicationinfo的 nativeLibraryRootDir nativeLibraryRootRequiresIsa nativeLibraryDir secondaryNativeLibraryDir setNativeLibraryPaths(pkg); }
} else { // 新安装的包的情况 if ((scanFlags & SCAN_MOVE) != 0) { // 为移动apk的场景时. 直接继承原来的abi // We haven't run dex-opt for this move (since we've moved the compiled output too) // but we already have this packages package info in the PackageSetting. We just // use that and derive the native library path based on the new codepath. pkg.applicationInfo.primaryCpuAbi = pkgSetting.primaryCpuAbiString; pkg.applicationInfo.secondaryCpuAbi = pkgSetting.secondaryCpuAbiString; }
// Set native library paths again. For moves, the path will be updated based on the // ABIs we've determined above. For non-moves, the path will be updated based on the // ABIs we determined during compilation, but the path will depend on the final // package path (after the rename away from the stage path). setNativeLibraryPaths(pkg); }
// This is a special case for the "system" package, where the ABI is // dictated by the zygote configuration (and init.rc). We should keep track // of this ABI so that we can deal with "normal" applications that run under // the same UID correctly. // framework-res.apk 初始化primaryCpuAbi if (mPlatformPackage == pkg) { pkg.applicationInfo.primaryCpuAbi = VMRuntime.getRuntime().is64Bit() ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0]; }
// We would never need to extract libs for forward-locked and external packages, // since the container service will do it for us. We shouldn't attempt to // extract libs from system app when it was not updated. if (pkg.isForwardLocked() || pkg.applicationInfo.isExternalAsec() || (isSystemApp(pkg) && !pkg.isUpdatedSystemApp())) { extractLibs = false; }
// Null out the abis so that they can be recalculated. pkg.applicationInfo.primaryCpuAbi = null; pkg.applicationInfo.secondaryCpuAbi = null; // 包含多个指令集的情况 if (isMultiArch(pkg.applicationInfo)) { // Warn if we've set an abiOverride for multi-lib packages.. // By definition, we need to copy both 32 and 64 bit libraries for // such packages. // install apk的参数 if (pkg.cpuAbiOverride != null && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) { Slog.w(TAG, "Ignoring abiOverride for multi arch application."); }
// Now that we've calculated the ABIs and determined if it's an internal app, // we will go ahead and populate the nativeLibraryPath. setNativeLibraryPaths(pkg); }
if ((scanFlags & SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) { // We don't do this here during boot because we can do it all // at once after scanning all existing packages. // // We also do this *before* we perform dexopt on this package, so that // we can avoid redundant dexopts, and also to make sure we've got the // code and package path correct. // boot阶段不进行该操作, 为shareUser 调整abi adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages, pkg, true/* boot complete */); } // bootComplete 已经开机完成,true 表明不是在boot阶段 // scannedPackage 为当前扫描的 包, // packagesForUser 同shareUser的包 privatevoidadjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser, PackageParser.Package scannedPackage, boolean bootComplete) {
PackageSettingrequirer=null; for (PackageSetting ps : packagesForUser) { // If packagesForUser contains scannedPackage, we skip it. This will happen // when scannedPackage is an update of an existing package. Without this check, // we will never be able to change the ABI of any package belonging to a shared // user, even if it's compatible with other packages. // shareUser 中的包名为当前包时略过 if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) { if (ps.primaryCpuAbiString == null) { continue; }
finalStringinstructionSet= VMRuntime.getInstructionSet(ps.primaryCpuAbiString); if (requiredInstructionSet != null && !instructionSet.equals(requiredInstructionSet)) { // We have a mismatch between instruction sets (say arm vs arm64) warn about // this but there's not much we can do. // 如果shareUser中其他包和当前包的需要的架构集不一致,打出log StringerrorMessage="Instruction set mismatch, " + ((requirer == null) ? "[caller]" : requirer) + " requires " + requiredInstructionSet + " whereas " + ps + " requires " + instructionSet; Slog.w(TAG, errorMessage); } // 如果当前包需要的架构集为空,则赋值为 shareUser中其他包的需要的架构集 if (requiredInstructionSet == null) { requiredInstructionSet = instructionSet; requirer = ps; } } }
if (requiredInstructionSet != null) { String adjustedAbi; if (requirer != null) { // requirer != null implies that either scannedPackage was null or that scannedPackage // did not require an ABI, in which case we have to adjust scannedPackage to match // the ABI of the set (which is the same as requirer's ABI) // 此时只对应当前包所需架构集为空,但shareUser中其他包 架构集不为空的情况, 该中情况下,更新当前包的 primaryCpuAbi 为 shareUser中对应包的架构集 adjustedAbi = requirer.primaryCpuAbiString; if (scannedPackage != null) { scannedPackage.applicationInfo.primaryCpuAbi = adjustedAbi; } } else { // requirer == null implies that we're updating all ABIs in the set to // match scannedPackage. // 当前包的requiredInstructionSet不为空, adjustedAbi 直接取当前包的 primaryCpuAbi adjustedAbi = scannedPackage.applicationInfo.primaryCpuAbi; }
// writer synchronized (mPackages) { if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { // Only system apps can add new shared libraries. if (pkg.libraryNames != null) { for (int i=0; i<pkg.libraryNames.size(); i++) { Stringname= pkg.libraryNames.get(i); booleanallowed=false; if (pkg.isUpdatedSystemApp()) { // 如果是package更新的场景,查找该包是否在系统禁用包中.如果该包在更新前在系统禁用包中, // 则对当前的shareLib单项进行判断是否匹配旧包的lib项.匹配才允许加到共享库中 finalPackageSettingsysPs= mSettings .getDisabledSystemPkgLPr(pkg.packageName); if (sysPs.pkg != null && sysPs.pkg.libraryNames != null) { for (int j=0; j<sysPs.pkg.libraryNames.size(); j++) { if (name.equals(sysPs.pkg.libraryNames.get(j))) { allowed = true; break; } } } // 没在系统禁用包中,或者lib项不匹配,allowed为false } else { allowed = true; } if (allowed) { if (!mSharedLibraries.containsKey(name)) { mSharedLibraries.put(name, newSharedLibraryEntry(null, pkg.packageName)); } elseif (!name.equals(pkg.packageName)) { Slog.w(TAG, "Package " + pkg.packageName + " library " + name + " already exists; skipping"); } } else { Slog.w(TAG, "Package " + pkg.packageName + " declares lib " + name + " that is not declared on system image; skipping"); } } if ((scanFlags & SCAN_BOOTING) == 0) { // If we are not booting, we need to update any applications // that are clients of our shared library. If we are booting, // this will all be done once the scan is complete. clientLibPkgs = updateAllSharedLibrariesLPw(pkg); } } } } // Also need to kill any apps that are dependent on the library. if (clientLibPkgs != null) { for (int i=0; i<clientLibPkgs.size(); i++) { PackageParser.PackageclientPkg= clientLibPkgs.get(i); // 杀死这些关联到该共享库的应用 killApplication(clientPkg.applicationInfo.packageName, clientPkg.applicationInfo.uid, "update lib"); } }
// Add the new setting to mSettings mSettings.insertPackageSettingLPw(pkgSetting, pkg); // Add the new setting to mPackages mPackages.put(pkg.applicationInfo.packageName, pkg); // Make sure we don't accidentally delete its data. final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator(); while (iter.hasNext()) { PackageCleanItemitem= iter.next(); if (pkgName.equals(item.packageName)) { iter.remove(); } }
// Take care of first install / last update times. if (currentTime != 0) { if (pkgSetting.firstInstallTime == 0) { pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime; } elseif ((scanFlags&SCAN_UPDATE_TIME) != 0) { pkgSetting.lastUpdateTime = currentTime; } } elseif (pkgSetting.firstInstallTime == 0) { // We need *something*. Take time time stamp of the file. pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime; } elseif ((policyFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) { if (scanFileTime != pkgSetting.timeStamp) { // A package on the system image has changed; consider this // to be an update. pkgSetting.lastUpdateTime = scanFileTime; } // Add the package's KeySets to the global KeySetManagerService ksms.addScannedPackageLPw(pkg);
遍历pkg.services,将其中的各个Service类型的元素添加到ServiceIntentResolver类型的PackageMamangerService.mServices的成员变量ServiceIntentResolver.mServices(HashMap<ComponentName, Service >类型)中。