分析 PackageManagerService
的构造方法,主要是扫描已存在的应用并建立应用信息库用于查询
PackageManagerService
构造过程
- 涉及文件
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
frameworks/base/services/core/java/com/android/server/pm/Settings.java
frameworks/base/core/java/com/android/server/SystemConfig.java
frameworks/base/services/core/java/com/android/server/pm/ParallelPackageParser.java
frameworks/base/core/java/android/content/pm/PackageParser.java
frameworks/base/services/core/java/com/android/server/pm/PackageSetting.java
PackageManagerService()
|
|
Settings.class
建立 Android 体系与 Linux 内核的用户权限对应关系
Settings()
|
|
addSharedUserLPw()
|
|
在 Settings
中 mSharedUsers
是一个 map
对象,利用名称作为索引管理 SharedUserSettings
对象。 Settings
中的 mOtherUserIds
和 mUserIds
,均是利用 userId
作为索引管理 SharedUserSettings
对象。不同的是 mOtherUserIds
是 SparseArray
,以系统 uid
作为键值;=mUserIds= 是 ArrayList
,普通 APK 的 uid
为 ArrayList
的下标。 SharedUserSettings
将持有一组 PackageSetting
。
AndroidManifest.xml
中 android:sharedUserId
的属性就是应用的 UserId
其与 Linux 的 UID 相关联,而 Linux 的权限是建立再用户的基础上的,从而建立应用的权限体系。
SystemConfig.class
从文件读取系统配置
SystemConfig()
|
|
readPermissions()
|
|
扫描已安装应用信息并保存
scanDirTracedLI()
|
|
ParallelPackageParser.class
这是一个辅助类用于并行解析安装包
|
|
PackageParser.class
安装包解析类
parsePackage()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
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 { // 这次是 true,如果从缓存中找到直接返回该对象 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null; if (parsed != null) { return parsed; } long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0; // 目录和单个文件调用的方法不同,但大同小异; // Android 目前默认都是文件夹;那我这里也就只分析解析文件夹的方法 if (packageFile.isDirectory()) { parsed = parseClusterPackage(packageFile, flags); } else { parsed = parseMonolithicPackage(packageFile, flags); } long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0; // 缓存解析结果 cacheResult(packageFile, flags, parsed); if (LOG_PARSE_TIMINGS) { parseTime = cacheTime - parseTime; cacheTime = SystemClock.uptimeMillis() - cacheTime; if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) { Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime + "ms, update_cache=" + cacheTime + " ms"); } } return parsed; }
parseClusterPackage()
解析文件夹```java /**
- Parse all APKs contained in the given directory, treating them as a
- single package. This also performs sanity checking, such as requiring
- identical package name and version codes, a single base APK, and unique
- split names.
- Note that this does not perform signature verification; that
must be done separately in {@link #collectCertificates(Package, int)}. */ private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException { // 解析出所有 apk 信息 <3> final PackageLite lite = parseClusterPackageLite(packageDir, 0); if (mOnlyCoreApps && !lite.coreApp) { throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, “Not a coreApp: “ + packageDir); }
// Build the split dependency tree. // 构建子包依赖树 SparseArray
splitDependencies = null; final SplitAssetLoader assetLoader; if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) { try { splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite); assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags); } catch (SplitAssetDependencyLoader.IllegalDependencyException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage()); } } else { assetLoader = new DefaultSplitAssetLoader(lite, flags); } try { // 解析母 apk <5> final AssetManager assets = assetLoader.getBaseAssetManager(); final File baseApk = new File(lite.baseCodePath); final Package pkg = parseBaseApk(baseApk, assets, flags); if (pkg == null) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, “Failed to parse base APK: “ + baseApk); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
if (!ArrayUtils.isEmpty(lite.splitNames)) { final int num = lite.splitNames.length; pkg.splitNames = lite.splitNames; pkg.splitCodePaths = lite.splitCodePaths; pkg.splitRevisionCodes = lite.splitRevisionCodes; pkg.splitFlags = new int[num]; pkg.splitPrivateFlags = new int[num]; pkg.applicationInfo.splitNames = pkg.splitNames; pkg.applicationInfo.splitDependencies = splitDependencies; pkg.applicationInfo.splitClassLoaderNames = new String[num]; for (int i = 0; i < num; i++) { // 解析子 apk,过程类似母 apk final AssetManager splitAssets = assetLoader.getSplitAssetManager(i); parseSplitApk(pkg, i, splitAssets, flags); } } pkg.setCodePath(packageDir.getCanonicalPath()); pkg.setUse32bitAbi(lite.use32bitAbi); return pkg;
} catch (IOException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, “Failed to get path: “ + lite.baseCodePath, e); } finally { IoUtils.closeQuietly(assetLoader); } } ```
parseClusterPackageLite()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
// PackageLite 的构造方法,主要是保存应用的信息 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames, boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit, String[] splitCodePaths, int[] splitRevisionCodes) { this.packageName = baseApk.packageName; this.versionCode = baseApk.versionCode; this.versionCodeMajor = baseApk.versionCodeMajor; this.installLocation = baseApk.installLocation; this.verifiers = baseApk.verifiers; this.splitNames = splitNames; this.isFeatureSplits = isFeatureSplits; this.usesSplitNames = usesSplitNames; this.configForSplit = configForSplit; this.codePath = codePath; this.baseCodePath = baseApk.codePath; this.splitCodePaths = splitCodePaths; this.baseRevisionCode = baseApk.revisionCode; this.splitRevisionCodes = splitRevisionCodes; this.coreApp = baseApk.coreApp; this.debuggable = baseApk.debuggable; this.multiArch = baseApk.multiArch; this.use32bitAbi = baseApk.use32bitAbi; this.extractNativeLibs = baseApk.extractNativeLibs; this.isolatedSplits = baseApk.isolatedSplits; } static PackageLite parseClusterPackageLite(File packageDir, int flags) throws PackageParserException { final File[] files = packageDir.listFiles(); if (ArrayUtils.isEmpty(files)) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "No packages found in split"); } String packageName = null; int versionCode = 0; Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite"); final ArrayMap<String, ApkLite> apks = new ArrayMap<>(); for (File file : files) { if (isApkFile(file)) { // 解析单个 APK 文件 final ApkLite lite = parseApkLite(file, flags); // Assert that all package names and version codes are // consistent with the first one we encounter. if (packageName == null) { packageName = lite.packageName; versionCode = lite.versionCode; } else { // 检查包名是否一致 if (!packageName.equals(lite.packageName)) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Inconsistent package " + lite.packageName + " in " + file + "; expected " + packageName); } // 检查版本号是否一致 if (versionCode != lite.versionCode) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Inconsistent version " + lite.versionCode + " in " + file + "; expected " + versionCode); } } // 检查子包的唯一性 // Assert that each split is defined only once if (apks.put(lite.splitName, lite) != null) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Split name " + lite.splitName + " defined more than once; most recent was " + file); } } } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); // 因为 baseApk.splitName=null,所以移除 null 返回 baseApk final ApkLite baseApk = apks.remove(null); if (baseApk == null) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Missing base APK in " + packageDir); } // Always apply deterministic ordering based on splitName final int size = apks.size(); String[] splitNames = null; boolean[] isFeatureSplits = null; String[] usesSplitNames = null; String[] configForSplits = null; String[] splitCodePaths = null; int[] splitRevisionCodes = null; String[] splitClassLoaderNames = null; if (size > 0) { splitNames = new String[size]; isFeatureSplits = new boolean[size]; usesSplitNames = new String[size]; configForSplits = new String[size]; splitCodePaths = new String[size]; splitRevisionCodes = new int[size]; // 子包排序储存 splitNames = apks.keySet().toArray(splitNames); Arrays.sort(splitNames, sSplitNameComparator); for (int i = 0; i < size; i++) { final ApkLite apk = apks.get(splitNames[i]); usesSplitNames[i] = apk.usesSplitName; isFeatureSplits[i] = apk.isFeatureSplit; configForSplits[i] = apk.configForSplit; splitCodePaths[i] = apk.codePath; splitRevisionCodes[i] = apk.revisionCode; } } final String codePath = packageDir.getAbsolutePath(); // 构建 PackageLite 对象并返回 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames, configForSplits, splitCodePaths, splitRevisionCodes); }
parseApkLite()
```java /**
- Utility method that retrieves lightweight details about a single APK
- file, including package name, split name, and install location. *
- @param apkFile path to a single APK
- @param flags optional parse flags, such as
- {@link #PARSE_COLLECT_CERTIFICATES} */ public static ApkLite parseApkLite(File apkFile, int flags) throws PackageParserException { return parseApkLiteInner(apkFile, null, null, flags); }
private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName, int flags) throws PackageParserException { // 这里 fd、debugPathName 都是 null // 这个获得 apk 绝对路径 final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
XmlResourceParser parser = null; try { final ApkAssets apkAssets; try { // 从 apk 中加载 AndroidManifest.xml 文件 apkAssets = fd != null ? ApkAssets.loadFromFd(fd, debugPathName, false, false) : ApkAssets.loadFromPath(apkPath); } catch (IOException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "Failed to parse " + apkPath); } // 准备解析 AndroidManifest.xml 文件 parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME); final SigningDetails signingDetails; if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) { // TODO: factor signature related items out of Package object final Package tempPkg = new Package((String) null); // 系统签名 apk 跳过签名相关 final boolean skipVerify = (flags & PARSE_IS_SYSTEM_DIR) != 0; Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); try { // 获取签名信息 collectCertificates(tempPkg, apkFile, skipVerify); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } signingDetails = tempPkg.mSigningDetails; } else { signingDetails = SigningDetails.UNKNOWN; } //XmlResourceParser 是 AttributeSet 的子类 final AttributeSet attrs = parser; return parseApkLite(apkPath, parser, attrs, signingDetails); } catch (XmlPullParserException | IOException | RuntimeException e) { Slog.w(TAG, "Failed to parse " + apkPath, e); throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, "Failed to parse " + apkPath, e); } finally { IoUtils.closeQuietly(parser); // TODO(b/72056911): Implement and call close() on ApkAssets. }
} // 主要解析 AndroidManifest.xml 文件,并将结果保存到 ApkLite 对象中 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs, SigningDetails signingDetails) throws IOException, XmlPullParserException, PackageParserException { final Pair
packageSplit = parsePackageSplitNames(parser, attrs); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
int installLocation = PARSE_DEFAULT_INSTALL_LOCATION; int versionCode = 0; int versionCodeMajor = 0; int revisionCode = 0; boolean coreApp = false; boolean debuggable = false; boolean multiArch = false; boolean use32bitAbi = false; boolean extractNativeLibs = true; boolean isolatedSplits = false; boolean isFeatureSplit = false; String configForSplit = null; String usesSplitName = null; // 从 AndroidManifest.xml 中解析上述变量的值 // ...... // 构建 ApkLite 对象并返回 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit, configForSplit, usesSplitName, versionCode, versionCodeMajor, revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable, multiArch, use32bitAbi, extractNativeLibs, isolatedSplits);
} ```
parseBaseApk()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
private Package parseBaseApk(File apkFile, AssetManager assets, int flags) throws PackageParserException { final String apkPath = apkFile.getAbsolutePath(); String volumeUuid = null; if (apkPath.startsWith(MNT_EXPAND)) { final int end = apkPath.indexOf('/', MNT_EXPAND.length()); volumeUuid = apkPath.substring(MNT_EXPAND.length(), end); } mParseError = PackageManager.INSTALL_SUCCEEDED; mArchiveSourcePath = apkFile.getAbsolutePath(); if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath); XmlResourceParser parser = null; try { // 根据 apk 路径获取资源管理器中的 AndroidManifest.xml final int cookie = assets.findCookieForPath(apkPath); if (cookie == 0) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Failed adding asset path: " + apkPath); } 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; } catch (PackageParserException e) { throw e; } catch (Exception e) { throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, "Failed to read manifest from " + apkPath, e); } finally { IoUtils.closeQuietly(parser); } } private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { // Make sure we have a valid child package name // 包名 String childPackageName = parser.getAttributeValue(null, "package"); if (validateName(childPackageName, true, false) != null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; return false; } // Child packages must be unique // 包名唯一 if (childPackageName.equals(parentPkg.packageName)) { String message = "Child package name cannot be equal to parent package name: " + parentPkg.packageName; Slog.w(TAG, message); outError[0] = message; mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; } // Child packages must be unique if (parentPkg.hasChildPackage(childPackageName)) { String message = "Duplicate child package:" + childPackageName; Slog.w(TAG, message); outError[0] = message; mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; } // Go ahead and parse the child Package childPkg = new Package(childPackageName); // Child package inherits parent version code/name/target SDK // 解析出:版本号、名称、SDK 版本等信息 childPkg.mVersionCode = parentPkg.mVersionCode; childPkg.baseRevisionCode = parentPkg.baseRevisionCode; childPkg.mVersionName = parentPkg.mVersionName; childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion; childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion; childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError); if (childPkg == null) { // If we got null then error was set during child parsing return false; } // Set the parent-child relation if (parentPkg.childPackages == null) { parentPkg.childPackages = new ArrayList<>(); } parentPkg.childPackages.add(childPkg); childPkg.parentPackage = parentPkg; return true; }
scanPackageChildLI()
|
|
addForInitLI()
这个方法比较长,主要作用是把扫描到的应用包信息存储到
PackageManagerService
,由于以后查询,Intent
行为主要依赖次信息库;在此过程中也会附加检查,如果包与先前已知的包相同,则发生基本验证[例如确保匹配签名,检查版本代码等]。 如果程序包未通过签名检查,则将删除/data
上安装的版本。 如果新软件包的版本小于或等于/data
上的版本,则将忽略它。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
private PackageParser.Package addForInitLI(PackageParser.Package pkg, @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) throws PackageManagerException { // 系统内置的即非 data 分区 final boolean scanSystemPartition = (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0; final String renamedPkgName; final PackageSetting disabledPkgSetting; final boolean isSystemPkgUpdated; final boolean pkgAlreadyExists; PackageSetting pkgSetting; // NOTE: installPackageLI() has the same code to setup the package's // application info. This probably should be done lower in the call // stack [such as scanPackageOnly()]. However, we verify the application // info prior to that [in scanPackageNew()] and thus have to setup // the application info early. pkg.setApplicationVolumeUuid(pkg.volumeUuid); pkg.setApplicationInfoCodePath(pkg.codePath); pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath); pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths); pkg.setApplicationInfoResourcePath(pkg.codePath); pkg.setApplicationInfoBaseResourcePath(pkg.baseCodePath); pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths); synchronized (mPackages) { // 获取自首次安装以来已重命名的软件包的原始包名。 键是包的新名称,值是原始名称。 renamedPkgName = mSettings.getRenamedPackageLPr(pkg.mRealPackage); final String realPkgName = getRealPackageName(pkg, renamedPkgName); if (realPkgName != null) { // 更改为原始包名 ensurePackageRenamed(pkg, renamedPkgName); } //获取原始包配置,原始包必须以相同的方式签名,且必须具有相同的名称和共享用户[如果有]。 final PackageSetting originalPkgSetting = getOriginalPackageLocked(pkg, renamedPkgName); // 获取当前包配置 final PackageSetting installedPkgSetting = mSettings.getPackageLPr(pkg.packageName); pkgSetting = originalPkgSetting == null ? installedPkgSetting : originalPkgSetting; // 判断当前应用包是否已经存在 pkgAlreadyExists = pkgSetting != null; final String disabledPkgName = pkgAlreadyExists ? pkgSetting.name : pkg.packageName; // 获取被当前应用包替换的系统应用包配置 disabledPkgSetting = mSettings.getDisabledSystemPkgLPr(disabledPkgName); // 是否是系统应用的升级包 isSystemPkgUpdated = disabledPkgSetting != null; final SharedUserSetting sharedUserSetting = (pkg.mSharedUserId != null) ? mSettings.getSharedUserLPw(pkg.mSharedUserId, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true) : null; if (scanSystemPartition) { // Potentially prune child packages. If the application on the /system // partition has been updated via OTA, but, is still disabled by a // version on /data, cycle through all of its children packages and // remove children that are no longer defined. // 如果 /system 分区上的应用程序已通过 OTA 更新,但仍然被 /data 上的版本禁用,则循环遍历其所有子程序包并删除不再定义的子项。 if (isSystemPkgUpdated) { final int scannedChildCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; final int disabledChildCount = disabledPkgSetting.childPackageNames != null ? disabledPkgSetting.childPackageNames.size() : 0; for (int i = 0; i < disabledChildCount; i++) { String disabledChildPackageName = disabledPkgSetting.childPackageNames.get(i); boolean disabledPackageAvailable = false; for (int j = 0; j < scannedChildCount; j++) { PackageParser.Package childPkg = pkg.childPackages.get(j); if (childPkg.packageName.equals(disabledChildPackageName)) { disabledPackageAvailable = true; break; } } if (!disabledPackageAvailable) { mSettings.removeDisabledSystemPackageLPw(disabledChildPackageName); } } // we're updating the disabled package, so, scan it as the package setting final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, null, disabledPkgSetting /* pkgSetting */, null /* disabledPkgSetting */, null /* originalPkgSetting */, null, parseFlags, scanFlags, (pkg == mPlatformPackage), user); applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage); scanPackageOnlyLI(request, mFactoryTest, -1L); } } } // 新包安装路径是否改变 final boolean newPkgChangedPaths = pkgAlreadyExists && !pkgSetting.codePathString.equals(pkg.codePath); // 新包版本是否升级 final boolean newPkgVersionGreater = pkgAlreadyExists && pkg.getLongVersionCode() > pkgSetting.versionCode; // 系统包是否有升级 final boolean isSystemPkgBetter = scanSystemPartition && isSystemPkgUpdated && newPkgChangedPaths && newPkgVersionGreater; if (isSystemPkgBetter) { // The version of the application on /system is greater than the version on // /data. Switch back to the application on /system. // It's safe to assume the application on /system will correctly scan. If not, // there won't be a working copy of the application. // /system 上的应用程序版本大于 /data 上的版本。 切换回 /system 上的应用程序。 synchronized (mPackages) { // just remove the loaded entries from package lists mPackages.remove(pkgSetting.name); } final InstallArgs args = createInstallArgsForExisting( packageFlagsToInstallFlags(pkgSetting), pkgSetting.codePathString, pkgSetting.resourcePathString, getAppDexInstructionSets(pkgSetting)); // 清理资源文件 args.cleanUpResourcesLI(); synchronized (mPackages) { // 重新启用系统分区上的应用包 mSettings.enableSystemPackageLPw(pkgSetting.name); } } if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) { // The version of the application on the /system partition is less than or // equal to the version on the /data partition. Even though the disabled system package // is likely to be replaced by a version on the /data partition, we make assumptions // that it's part of the mPackages collection during package manager initialization. So, // add it to mPackages if there isn't already a package in the collection and then throw // an exception to use the application already installed on the /data partition. // /system 分区上的应用程序版本小于或等于 /data 分区上的版本。仍然使用 /data 分区上的版本,但仍将改包加入到应用管理器 synchronized (mPackages) { if (!mPackages.containsKey(pkg.packageName)) { mPackages.put(pkg.packageName, pkg); } } } // Verify certificates against what was last scanned. If it is an updated priv app, we will // force re-collecting certificate. // 根据上次扫描的内容验证证书。 如果它是更新 priv-app 下的应用程序,我们将强制重新收集证书。 final boolean forceCollect = PackageManagerServiceUtils.isApkVerificationForced( disabledPkgSetting); // Full APK verification can be skipped during certificate collection, only if the file is // in verified partition, or can be verified on access (when apk verity is enabled). In both // cases, only data in Signing Block is verified instead of the whole file. // 只有当文件位于已验证的分区中,或者可以在访问时验证(apk 启用访问验证时), //才能在证书收集期间跳过完整的 APK 验证。 在这两种情况下,仅验证签名块中的数据而不是整个文件。 final boolean skipVerify = ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) || (forceCollect && canSkipFullPackageVerification(pkg)); collectCertificatesLI(pkgSetting, pkg, forceCollect, skipVerify); // Reset profile if the application version is changed maybeClearProfilesForUpgradesLI(pkgSetting, pkg); /* * A new system app appeared, but we already had a non-system one of the * same name installed earlier. */ // 出现了一个新的系统应用程序,但我们之前已经安装了一个同名的非系统应用程序。 boolean shouldHideSystemApp = false; // A new application appeared on /system, but, we already have a copy of // the application installed on /data. if (scanSystemPartition && !isSystemPkgUpdated && pkgAlreadyExists && !pkgSetting.isSystem()) { if (!pkg.mSigningDetails.checkCapability(pkgSetting.signatures.mSigningDetails, PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA) && !pkgSetting.signatures.mSigningDetails.checkCapability( pkg.mSigningDetails, PackageParser.SigningDetails.CertCapabilities.ROLLBACK)) { // 签名不匹配,删除改包 try (PackageFreezer freezer = freezePackage(pkg.packageName, "scanPackageInternalLI")) { deletePackageLIF(pkg.packageName, null, true, null, 0, null, false, null); } pkgSetting = null; } else if (newPkgVersionGreater) { // The application on /system is newer than the application on /data. // Simply remove the application on /data [keeping application data] // and replace it with the version on /system. // 系统新包版本更高,移除 /data 上的应用包但保留应用数据 InstallArgs args = createInstallArgsForExisting( packageFlagsToInstallFlags(pkgSetting), pkgSetting.codePathString, pkgSetting.resourcePathString, getAppDexInstructionSets(pkgSetting)); synchronized (mInstallLock) { args.cleanUpResourcesLI(); } } else { // The application on /system is older than the application on /data. Hide // the application on /system and the version on /data will be scanned later // and re-added like an update. // /system 上的应用程序比 /data 上的应用程序旧。 隐藏 /system 上的应用程序,稍后将扫描 /data 上的版本,并像更新一样重新添加。 shouldHideSystemApp = true; } } // 下一步 <2> final PackageParser.Package scannedPkg = scanPackageNewLI(pkg, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user); if (shouldHideSystemApp) { synchronized (mPackages) { // 停用需要隐藏的系统包 mSettings.disableSystemPackageLPw(pkg.packageName, true); } } return scannedPkg; }
scanPackageNewLI()
这个方法主要是有新应用包时(比如 ota 引入)确认是否要替换原应用包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
@GuardedBy("mInstallLock") private PackageParser.Package scanPackageNewLI(@NonNull PackageParser.Package pkg, final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) throws PackageManagerException { final String renamedPkgName = mSettings.getRenamedPackageLPr(pkg.mRealPackage); final String realPkgName = getRealPackageName(pkg, renamedPkgName); if (realPkgName != null) { ensurePackageRenamed(pkg, renamedPkgName); } final PackageSetting originalPkgSetting = getOriginalPackageLocked(pkg, renamedPkgName); final PackageSetting pkgSetting = mSettings.getPackageLPr(pkg.packageName); final PackageSetting disabledPkgSetting = mSettings.getDisabledSystemPkgLPr(pkg.packageName); // 调整扫描参数 scanFlags = adjustScanFlags(scanFlags, pkgSetting, disabledPkgSetting, user, pkg); synchronized (mPackages) { // 根据给定的策略标志将策略应用于已解析的包。 applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage); // 断言解析的包根据给定的策略有效。 如果包无效,无论出于何种原因,抛出 PackageManagerException。 assertPackageIsValid(pkg, parseFlags, scanFlags); SharedUserSetting sharedUserSetting = null; if (pkg.mSharedUserId != null) { // SIDE EFFECTS; may potentially allocate a new shared user // 如果不存在则新建 sharedUserSetting = mSettings.getSharedUserLPw( pkg.mSharedUserId, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true /*create*/); } boolean scanSucceeded = false; try { final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, pkgSetting == null ? null : pkgSetting.pkg, pkgSetting, disabledPkgSetting, originalPkgSetting, realPkgName, parseFlags, scanFlags, (pkg == mPlatformPackage), user); // 前面主要是解析 AndroidManifest.xm 获取应用的基本信息;同时确定应用使用的版本 // 这个方法将解析四大组件相关信息,并储存以供以后查询,比如 Intent 相关 <3> final ScanResult result = scanPackageOnlyLI(request, mFactoryTest, currentTime); if (result.success) { // 提交结果 <4> commitScanResultsLocked(request, result); } scanSucceeded = true; } finally { if (!scanSucceeded && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) { // DELETE_DATA_ON_FAILURES is only used by frozen paths // 失败则清理无效数据 destroyAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); destroyAppProfilesLIF(pkg, UserHandle.USER_ALL); } } } return pkg; }
scanPackageOnlyLI()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
@GuardedBy("mInstallLock") private static @NonNull ScanResult scanPackageOnlyLI(@NonNull ScanRequest request, boolean isUnderFactoryTest, long currentTime) throws PackageManagerException { final PackageParser.Package pkg = request.pkg; PackageSetting pkgSetting = request.pkgSetting; final PackageSetting disabledPkgSetting = request.disabledPkgSetting; final PackageSetting originalPkgSetting = request.originalPkgSetting; final @ParseFlags int parseFlags = request.parseFlags; final @ScanFlags int scanFlags = request.scanFlags; final String realPkgName = request.realPkgName; final SharedUserSetting sharedUserSetting = request.sharedUserSetting; final UserHandle user = request.user; final boolean isPlatformPackage = request.isPlatformPackage; List<String> changedAbiCodePath = null; DexManager.maybeLogUnexpectedPackageDetails(pkg); // Initialize package source and resource directories // 初始化资源、源码目录 final File scanFile = new File(pkg.codePath); final File destCodeFile = new File(pkg.applicationInfo.getCodePath()); final File destResourceFile = new File(pkg.applicationInfo.getResourcePath()); // We keep references to the derived CPU Abis from settings in oder to reuse // them in the case where we're not upgrading or booting for the first time. // 如果不是系统升级或首次开机可以使用以前保存的 CPU Abis 的引用 String primaryCpuAbiFromSettings = null; String secondaryCpuAbiFromSettings = null; // 需要生成 abi 引用 boolean needToDeriveAbi = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0; if (!needToDeriveAbi) { // 不需要生成 abi 引用时,确保是否有旧的存在,没有则要生成 if (pkgSetting != null) { primaryCpuAbiFromSettings = pkgSetting.primaryCpuAbiString; secondaryCpuAbiFromSettings = pkgSetting.secondaryCpuAbiString; } else { // Re-scanning a system package after uninstalling updates; need to derive ABI needToDeriveAbi = true; } } // sharedUser 不一致,需要重新生成 PackageSetting if (pkgSetting != null && pkgSetting.sharedUser != sharedUserSetting) { PackageManagerService.reportSettingsProblem(Log.WARN, "Package " + pkg.packageName + " shared user changed from " + (pkgSetting.sharedUser != null ? pkgSetting.sharedUser.name : "<nothing>") + " to " + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>") + "; replacing with new"); pkgSetting = null; } String[] usesStaticLibraries = null; if (pkg.usesStaticLibraries != null) { usesStaticLibraries = new String[pkg.usesStaticLibraries.size()]; pkg.usesStaticLibraries.toArray(usesStaticLibraries); } // 更新 PackageSetting 没有则要生成 final boolean createNewPackage = (pkgSetting == null); if (createNewPackage) { final String parentPackageName = (pkg.parentPackage != null) ? pkg.parentPackage.packageName : null; final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0; final boolean virtualPreload = (scanFlags & SCAN_AS_VIRTUAL_PRELOAD) != 0; // REMOVE SharedUserSetting from method; update in a separate call pkgSetting = Settings.createNewSetting(pkg.packageName, originalPkgSetting, disabledPkgSetting, realPkgName, sharedUserSetting, destCodeFile, destResourceFile, pkg.applicationInfo.nativeLibraryRootDir, pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi, pkg.mVersionCode, pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags, user, true /*allowInstall*/, instantApp, virtualPreload, parentPackageName, pkg.getChildPackageNames(), UserManagerService.getInstance(), usesStaticLibraries, pkg.usesStaticLibrariesVersions); } else { // REMOVE SharedUserSetting from method; update in a separate call. // // TODO(narayan): This update is bogus. nativeLibraryDir & primaryCpuAbi, // secondaryCpuAbi are not known at this point so we always update them // to null here, only to reset them at a later point. Settings.updatePackageSetting(pkgSetting, disabledPkgSetting, sharedUserSetting, destCodeFile, destResourceFile, pkg.applicationInfo.nativeLibraryDir, pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi, pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags, pkg.getChildPackageNames(), UserManagerService.getInstance(), usesStaticLibraries, pkg.usesStaticLibrariesVersions); } if (createNewPackage && originalPkgSetting != null) { // This is the initial transition from the original package, so, // fix up the new package's name now. We must do this after looking // up the package under its new name, so getPackageLP takes care of // fiddling things correctly. pkg.setPackageName(originalPkgSetting.name); // File a report about this. String msg = "New package " + pkgSetting.realName + " renamed to replace old package " + pkgSetting.name; reportSettingsProblem(Log.WARN, msg); } final int userId = (user == null ? UserHandle.USER_SYSTEM : user.getIdentifier()); // for existing packages, change the install state; but, only if it's explicitly specified // 更改已存在应用包的安装状态 if (!createNewPackage) { final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0; final boolean fullApp = (scanFlags & SCAN_AS_FULL_APP) != 0; setInstantAppForUser(pkgSetting, userId, instantApp, fullApp); } if (disabledPkgSetting != null) { pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; } // Apps which share a sharedUserId must be placed in the same selinux domain. If this // package is the first app installed as this shared user, set seInfoTargetSdkVersion to its // targetSdkVersion. These are later adjusted in PackageManagerService's constructor to be // the lowest targetSdkVersion of all apps within the shared user, which corresponds to the // least restrictive selinux domain. // NOTE: As new packages are installed / updated, the shared user's seinfoTargetSdkVersion // will NOT be modified until next boot, even if a lower targetSdkVersion is used. This // ensures that all packages continue to run in the same selinux domain. // 共享 sharedUserId 的应用必须放在同一个 selinux 域中。 如果此程序包是作为此共享用户安装的第一个应用程序, // 请将 seInfoTargetSdkVersion 设置为其 targetSdkVersion。 这些稍后在 PackageManagerService 的构造函 // 数中调整为共享用户中所有应用程序的最低 targetSdkVersion,这对应于限制性最小的 selinux 域。 // 注意:在安装/更新新软件包时,即使使用较低的 targetSdkVersion,共享用户的 seinfoTargetSdkVersion // 也不会被修改,直到下次引导。 这可确保所有包继续在同一 selinux 域中运行。 final int targetSdkVersion = ((sharedUserSetting != null) && (sharedUserSetting.packages.size() != 0)) ? sharedUserSetting.seInfoTargetSdkVersion : pkg.applicationInfo.targetSdkVersion; // TODO(b/71593002): isPrivileged for sharedUser and appInfo should never be out of sync. // They currently can be if the sharedUser apps are signed with the platform key. final boolean isPrivileged = (sharedUserSetting != null) ? sharedUserSetting.isPrivileged() | pkg.isPrivileged() : pkg.isPrivileged(); pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged, pkg.applicationInfo.targetSandboxVersion, targetSdkVersion); pkg.applicationInfo.seInfoUser = SELinuxUtil.assignSeinfoUser(pkgSetting.readUserState( userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId)); pkg.mExtras = pkgSetting; pkg.applicationInfo.processName = fixProcessName( pkg.applicationInfo.packageName, pkg.applicationInfo.processName); if (!isPlatformPackage) { // Get all of our default paths setup pkg.applicationInfo.initForUser(UserHandle.USER_SYSTEM); } // 更新 abi 引用 final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting); if ((scanFlags & SCAN_NEW_INSTALL) == 0) { if (needToDeriveAbi) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi"); final boolean extractNativeLibs = !pkg.isLibrary(); derivePackageAbi(pkg, cpuAbiOverride, extractNativeLibs); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); // 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. if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() && pkg.applicationInfo.primaryCpuAbi == null) { setBundledAppAbisAndRoots(pkg, pkgSetting); setNativeLibraryPaths(pkg, sAppLib32InstallDir); } } else { // This is not a first boot or an upgrade, don't bother deriving the // ABI during the scan. Instead, trust the value that was stored in the // package setting. pkg.applicationInfo.primaryCpuAbi = primaryCpuAbiFromSettings; pkg.applicationInfo.secondaryCpuAbi = secondaryCpuAbiFromSettings; setNativeLibraryPaths(pkg, sAppLib32InstallDir); if (DEBUG_ABI_SELECTION) { Slog.i(TAG, "Using ABIS and native lib paths from settings : " + pkg.packageName + " " + pkg.applicationInfo.primaryCpuAbi + ", " + pkg.applicationInfo.secondaryCpuAbi); } } } else { if ((scanFlags & SCAN_MOVE) != 0) { // 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, sAppLib32InstallDir); } // 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. if (isPlatformPackage) { pkg.applicationInfo.primaryCpuAbi = VMRuntime.getRuntime().is64Bit() ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0]; } // If there's a mismatch between the abi-override in the package setting // and the abiOverride specified for the install. Warn about this because we // would've already compiled the app without taking the package setting into // account. if ((scanFlags & SCAN_NO_DEX) == 0 && (scanFlags & SCAN_NEW_INSTALL) != 0) { if (cpuAbiOverride == null && pkg.packageName != null) { Slog.w(TAG, "Ignoring persisted ABI override " + cpuAbiOverride + " for package " + pkg.packageName); } } pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi; pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi; pkgSetting.cpuAbiOverrideString = cpuAbiOverride; // Copy the derived override back to the parsed package, so that we can // update the package settings accordingly. pkg.cpuAbiOverride = cpuAbiOverride; // Push the derived path down into PackageSettings so we know what to // clean up at uninstall time. pkgSetting.legacyNativeLibraryPathString = pkg.applicationInfo.nativeLibraryRootDir; 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. changedAbiCodePath = adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages, pkg); } if (isUnderFactoryTest && pkg.requestedPermissions.contains( android.Manifest.permission.FACTORY_TEST)) { pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST; } if (isSystemApp(pkg)) { pkgSetting.isOrphaned = true; } // Take care of first install / last update times. // 记录首次安装时间和最后更新时间 final long scanFileTime = getLastModifiedTime(pkg); if (currentTime != 0) { if (pkgSetting.firstInstallTime == 0) { pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime; } else if ((scanFlags & SCAN_UPDATE_TIME) != 0) { pkgSetting.lastUpdateTime = currentTime; } } else if (pkgSetting.firstInstallTime == 0) { // We need *something*. Take time time stamp of the file. pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime; } else if ((parseFlags & 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; } } pkgSetting.setTimeStamp(scanFileTime); pkgSetting.pkg = pkg; pkgSetting.pkgFlags = pkg.applicationInfo.flags; if (pkg.getLongVersionCode() != pkgSetting.versionCode) { pkgSetting.versionCode = pkg.getLongVersionCode(); } // Update volume if needed final String volumeUuid = pkg.applicationInfo.volumeUuid; if (!Objects.equals(volumeUuid, pkgSetting.volumeUuid)) { Slog.i(PackageManagerService.TAG, "Update" + (pkgSetting.isSystem() ? " system" : "") + " package " + pkg.packageName + " volume from " + pkgSetting.volumeUuid + " to " + volumeUuid); pkgSetting.volumeUuid = volumeUuid; } return new ScanResult(true, pkgSetting, changedAbiCodePath); }
commitScanResultsLocked()
提交包扫描并修改系统状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
@GuardedBy("mPackages") private void commitScanResultsLocked(@NonNull ScanRequest request, @NonNull ScanResult result) throws PackageManagerException { final PackageParser.Package pkg = request.pkg; final PackageParser.Package oldPkg = request.oldPkg; final @ParseFlags int parseFlags = request.parseFlags; final @ScanFlags int scanFlags = request.scanFlags; final PackageSetting oldPkgSetting = request.oldPkgSetting; final PackageSetting originalPkgSetting = request.originalPkgSetting; final PackageSetting disabledPkgSetting = request.disabledPkgSetting; final UserHandle user = request.user; final String realPkgName = request.realPkgName; final PackageSetting pkgSetting = result.pkgSetting; final List<String> changedAbiCodePath = result.changedAbiCodePath; final boolean newPkgSettingCreated = (result.pkgSetting != request.pkgSetting); // 新旧包 sharedUser 不一致 if (newPkgSettingCreated) { if (originalPkgSetting != null) { mSettings.addRenamedPackageLPw(pkg.packageName, originalPkgSetting.name); } // 新建用户 mSettings.addUserToSettingLPw(pkgSetting); // 原应用包数据传给新包,原包数据将不会保留 if (originalPkgSetting != null && (scanFlags & SCAN_CHECK_ONLY) == 0) { mTransferedPackages.add(originalPkgSetting.name); } } pkg.applicationInfo.uid = pkgSetting.appId; // 更新用户状态 mSettings.writeUserRestrictionsLPw(pkgSetting, oldPkgSetting); if ((scanFlags & SCAN_CHECK_ONLY) == 0 && realPkgName != null) { mTransferedPackages.add(pkg.packageName); } if ((scanFlags & SCAN_BOOTING) == 0 && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { // Check all shared libraries and map to their actual file path. // We only do this here for apps not on a system dir, because those // are the only ones that can fail an install due to this. We // will take care of the system apps by updating all of their // library paths after the scan is done. Also during the initial // scan don't update any libs as we do this wholesale after all // apps are scanned to avoid dependency based scanning. // 检查所有非系统目录上的共享库并映射到它们的实际文件路径。 updateSharedLibrariesLPr(pkg, null); } // All versions of a static shared library are referenced with the same // package name. Internally, we use a synthetic package name to allow // multiple versions of the same shared library to be installed. So, // we need to generate the synthetic package name of the latest shared // library in order to compare signatures. // 使用相同的包名称引用静态共享库的所有版本。 在内部,我们使用合成包名称来允许安装同一共享库的多个版本。 // 因此,我们需要生成最新共享库的合成包名称,以便比较签名。 // 以下处理应用包的签名信息 PackageSetting signatureCheckPs = pkgSetting; if (pkg.applicationInfo.isStaticSharedLibrary()) { SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg); if (libraryEntry != null) { signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk); } } final KeySetManagerService ksms = mSettings.mKeySetManagerService; if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) { if (ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) { // We just determined the app is signed correctly, so bring // over the latest parsed certs. pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails; } else { if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package " + pkg.packageName + " upgrade keys do not match the " + "previously installed version"); } else { pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails; String msg = "System package " + pkg.packageName + " signature changed; retaining data."; reportSettingsProblem(Log.WARN, msg); } } } else { try { final boolean compareCompat = isCompatSignatureUpdateNeeded(pkg); final boolean compareRecover = isRecoverSignatureUpdateNeeded(pkg); final boolean compatMatch = verifySignatures(signatureCheckPs, disabledPkgSetting, pkg.mSigningDetails, compareCompat, compareRecover); // The new KeySets will be re-added later in the scanning process. if (compatMatch) { synchronized (mPackages) { ksms.removeAppKeySetDataLPw(pkg.packageName); } } // We just determined the app is signed correctly, so bring // over the latest parsed certs. pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails; // if this is is a sharedUser, check to see if the new package is signed by a newer // signing certificate than the existing one, and if so, copy over the new details if (signatureCheckPs.sharedUser != null) { if (pkg.mSigningDetails.hasAncestor( signatureCheckPs.sharedUser.signatures.mSigningDetails)) { signatureCheckPs.sharedUser.signatures.mSigningDetails = pkg.mSigningDetails; } if (signatureCheckPs.sharedUser.signaturesChanged == null) { signatureCheckPs.sharedUser.signaturesChanged = Boolean.FALSE; } } } catch (PackageManagerException e) { if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { throw e; } // The signature has changed, but this package is in the system // image... let's recover! pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails; // If the system app is part of a shared user we allow that shared user to change // signatures as well as part of an OTA. We still need to verify that the signatures // are consistent within the shared user for a given boot, so only allow updating // the signatures on the first package scanned for the shared user (i.e. if the // signaturesChanged state hasn't been initialized yet in SharedUserSetting). // OTA 更改了签名信息,更新签名信息 if (signatureCheckPs.sharedUser != null) { if (signatureCheckPs.sharedUser.signaturesChanged != null && compareSignatures( signatureCheckPs.sharedUser.signatures.mSigningDetails.signatures, pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH) { throw new PackageManagerException( INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Signature mismatch for shared user: " + pkgSetting.sharedUser); } signatureCheckPs.sharedUser.signatures.mSigningDetails = pkg.mSigningDetails; signatureCheckPs.sharedUser.signaturesChanged = Boolean.TRUE; } // File a report about this. String msg = "System package " + pkg.packageName + " signature changed; retaining data."; reportSettingsProblem(Log.WARN, msg); } catch (IllegalArgumentException e) { } } // 权限相关 if ((scanFlags & SCAN_CHECK_ONLY) == 0 && pkg.mAdoptPermissions != null) { // This package wants to adopt ownership of permissions from // another package. for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) { final String origName = pkg.mAdoptPermissions.get(i); final PackageSetting orig = mSettings.getPackageLPr(origName); if (orig != null) { if (verifyPackageUpdateLPr(orig, pkg)) { Slog.i(TAG, "Adopting permissions from " + origName + " to " + pkg.packageName); mSettings.mPermissions.transferPermissions(origName, pkg.packageName); } } } } // 处理 cpu abi if (changedAbiCodePath != null && changedAbiCodePath.size() > 0) { for (int i = changedAbiCodePath.size() - 1; i >= 0; --i) { final String codePathString = changedAbiCodePath.get(i); try { mInstaller.rmdex(codePathString, getDexCodeInstructionSet(getPreferredInstructionSet())); } catch (InstallerException ignored) { } } } if ((scanFlags & SCAN_CHECK_ONLY) != 0) { if (oldPkgSetting != null) { synchronized (mPackages) { mSettings.mPackages.put(oldPkgSetting.name, oldPkgSetting); } } } else { final int userId = user == null ? 0 : user.getIdentifier(); // Modify state for the given package setting // 提交扫描结果到 PackageManagerService commitPackageSettings(pkg, oldPkg, pkgSetting, user, scanFlags, (parseFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/); if (pkgSetting.getInstantApp(userId)) { mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId); } } }
commitPackageSettings()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
private void commitPackageSettings(PackageParser.Package pkg, @Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting, UserHandle user, final @ScanFlags int scanFlags, boolean chatty) { final String pkgName = pkg.packageName; // mCustomResolverComponentName 定义于:R.string.config_customResolverActivity if (mCustomResolverComponentName != null && mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) { // 用自定义的替换默认的 ResolverActivity;前面说过 ResolverActivity 的用处 // Intent 有多个匹配项时,展示这些匹配项供用户选择一个 setUpCustomResolverActivity(pkg); } // 处理特殊包名:android if (pkg.packageName.equals("android")) { synchronized (mPackages) { if ((scanFlags & SCAN_CHECK_ONLY) == 0) { // Set up information for our fall-back user intent resolution activity. // 系统应用包 mPlatformPackage = pkg; pkg.mVersionCode = mSdkVersion; pkg.mVersionCodeMajor = 0; mAndroidApplication = pkg.applicationInfo; // 没有自定义 ResolverActivity;初始化默认 ResolverActivity if (!mResolverReplaced) { mResolveActivity.applicationInfo = mAndroidApplication; mResolveActivity.name = ResolverActivity.class.getName(); mResolveActivity.packageName = mAndroidApplication.packageName; mResolveActivity.processName = "system:ui"; mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER; mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; mResolveActivity.theme = R.style.Theme_Material_Dialog_Alert; mResolveActivity.exported = true; mResolveActivity.enabled = true; mResolveActivity.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE; mResolveActivity.configChanges = ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ORIENTATION | ActivityInfo.CONFIG_KEYBOARD | ActivityInfo.CONFIG_KEYBOARD_HIDDEN; mResolveInfo.activityInfo = mResolveActivity; mResolveInfo.priority = 0; mResolveInfo.preferredOrder = 0; mResolveInfo.match = 0; mResolveComponentName = new ComponentName( mAndroidApplication.packageName, mResolveActivity.name); } } } } ArrayList<PackageParser.Package> clientLibPkgs = null; // writer synchronized (mPackages) { boolean hasStaticSharedLibs = false; // Any app can add new static shared libraries // 更新链接库信息 if (pkg.staticSharedLibName != null) { // Static shared libs don't allow renaming as they have synthetic package // names to allow install of multiple versions, so use name from manifest. if (addSharedLibraryLPw(null, pkg.packageName, pkg.staticSharedLibName, pkg.staticSharedLibVersion, SharedLibraryInfo.TYPE_STATIC, pkg.manifestPackageName, pkg.getLongVersionCode())) { hasStaticSharedLibs = true; } else { Slog.w(TAG, "Package " + pkg.packageName + " library " + pkg.staticSharedLibName + " already exists; skipping"); } // Static shared libs cannot be updated once installed since they // use synthetic package name which includes the version code, so // not need to update other packages's shared lib dependencies. } // 系统应用包更新时,链接库相关更新 if (!hasStaticSharedLibs && (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { // Only system apps can add new dynamic shared libraries. if (pkg.libraryNames != null) { for (int i = 0; i < pkg.libraryNames.size(); i++) { String name = pkg.libraryNames.get(i); boolean allowed = false; if (pkg.isUpdatedSystemApp()) { // New library entries can only be added through the // system image. This is important to get rid of a lot // of nasty edge cases: for example if we allowed a non- // system update of the app to add a library, then uninstalling // the update would make the library go away, and assumptions // we made such as through app install filtering would now // have allowed apps on the device which aren't compatible // with it. Better to just have the restriction here, be // conservative, and create many fewer cases that can negatively // impact the user experience. final PackageSetting sysPs = 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; } } } } else { allowed = true; } 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); } } } } if ((scanFlags & SCAN_BOOTING) != 0) { // No apps can run during boot scan, so they don't need to be frozen } else if ((scanFlags & SCAN_DONT_KILL_APP) != 0) { // Caller asked to not kill app, so it's probably not frozen } else if ((scanFlags & SCAN_IGNORE_FROZEN) != 0) { // Caller asked us to ignore frozen check for some reason; they // probably didn't know the package name } else { // We're doing major surgery on this package, so it better be frozen // right now to keep it from launching checkPackageFrozen(pkgName); } // Also need to kill any apps that are dependent on the library. if (clientLibPkgs != null) { for (int i=0; i<clientLibPkgs.size(); i++) { PackageParser.Package clientPkg = clientLibPkgs.get(i); killApplication(clientPkg.applicationInfo.packageName, clientPkg.applicationInfo.uid, "update lib"); } } // writer Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings"); // PackageManagerService 存储四大组件信息 synchronized (mPackages) { // We don't expect installation to fail beyond this point // 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()) { PackageCleanItem item = iter.next(); if (pkgName.equals(item.packageName)) { iter.remove(); } } // Add the package's KeySets to the global KeySetManagerService KeySetManagerService ksms = mSettings.mKeySetManagerService; ksms.addScannedPackageLPw(pkg); // Provider int N = pkg.providers.size(); StringBuilder r = null; int i; for (i=0; i<N; i++) { PackageParser.Provider p = pkg.providers.get(i); // ...... } // Service N = pkg.services.size(); r = null; for (i=0; i<N; i++) { PackageParser.Service s = pkg.services.get(i); s.info.processName = fixProcessName(pkg.applicationInfo.processName, s.info.processName); mServices.addService(s); if (chatty) { if (r == null) { r = new StringBuilder(256); } else { r.append(' '); } r.append(s.info.name); } } // Receiver N = pkg.receivers.size(); r = null; for (i=0; i<N; i++) { PackageParser.Activity a = pkg.receivers.get(i); a.info.processName = fixProcessName(pkg.applicationInfo.processName, a.info.processName); mReceivers.addActivity(a, "receiver"); if (chatty) { if (r == null) { r = new StringBuilder(256); } else { r.append(' '); } r.append(a.info.name); } } // Activity N = pkg.activities.size(); r = null; for (i=0; i<N; i++) { PackageParser.Activity a = pkg.activities.get(i); a.info.processName = fixProcessName(pkg.applicationInfo.processName, a.info.processName); mActivities.addActivity(a, "activity"); if (chatty) { if (r == null) { r = new StringBuilder(256); } else { r.append(' '); } r.append(a.info.name); } } // Permission 不允许临时应用程序定义新权限和权限组。 // Don't allow ephemeral applications to define new permissions groups. if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) { } else { mPermissionManager.addAllPermissionGroups(pkg, chatty); } // Don't allow ephemeral applications to define new permissions. if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) { } else { mPermissionManager.addAllPermissions(pkg, chatty); } // Instrumentation N = pkg.instrumentation.size(); r = null; for (i=0; i<N; i++) { PackageParser.Instrumentation a = pkg.instrumentation.get(i); a.info.packageName = pkg.applicationInfo.packageName; a.info.sourceDir = pkg.applicationInfo.sourceDir; a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir; a.info.splitNames = pkg.splitNames; a.info.splitSourceDirs = pkg.applicationInfo.splitSourceDirs; a.info.splitPublicSourceDirs = pkg.applicationInfo.splitPublicSourceDirs; a.info.splitDependencies = pkg.applicationInfo.splitDependencies; a.info.dataDir = pkg.applicationInfo.dataDir; a.info.deviceProtectedDataDir = pkg.applicationInfo.deviceProtectedDataDir; a.info.credentialProtectedDataDir = pkg.applicationInfo.credentialProtectedDataDir; a.info.primaryCpuAbi = pkg.applicationInfo.primaryCpuAbi; a.info.secondaryCpuAbi = pkg.applicationInfo.secondaryCpuAbi; a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir; a.info.secondaryNativeLibraryDir = pkg.applicationInfo.secondaryNativeLibraryDir; mInstrumentation.put(a.getComponentName(), a); if (chatty) { if (r == null) { r = new StringBuilder(256); } else { r.append(' '); } r.append(a.info.name); } } // Protected Broadcast if (pkg.protectedBroadcasts != null) { N = pkg.protectedBroadcasts.size(); synchronized (mProtectedBroadcasts) { for (i = 0; i < N; i++) { mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i)); } } } }