PackageManagerService 系列文章以下(基于 Android 9.0 源码)
🍁 Framework 核心服务之 PackageManagerService 钻研(1)- 启动流程
🍁 Framework 核心服务之 PackageManagerService 钻研(2)- 构造函数
🍁 Framework 核心服务之 PackageManagerService 钻研(3)- PackageManager
🍁 Framework 核心服务之 PackageManagerService 钻研(4)- PackageInstaller
🍁 Framework 核心服务之 PackageManagerService 钻研(5)- APK 安装流程(PackageInstaller)
🍁 Framework 核心服务之 PackageManagerService 钻研(6)- APK 安装流程(PMS)
🍁 Framework 核心服务之 PackageManagerService 钻研(7)- PackageParserhtml
关键类 | 路径 |
---|---|
PackageParser.java | frameworks/base/core/java/android/content/pm/PackageParser.java |
PackageManagerService.java | frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java |
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) { ... ... PackageParser pp = new PackageParser(); // 建立 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); // 解析APK DexMetadataHelper.validatePackageDexMetadata(pkg); } catch (PackageParserException e) { res.setError("Failed parse during installPackageLI", e); return; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } ... ... }
在分析 PackageParser 解析 APK 以前,咱们先要了解一下 Split APK 机制!java
Split APK 是 Google 为解决 65536 上限,以及 APK 安装包愈来愈大等问题,在 Android L 中引入的机制。
Split APK 能够将一个庞大的 APK,按屏幕密度,ABI 等形式拆分红多个独立的 APK,在应用程序更新时,没必要下载整个 APK,只需单独下载某个模块便可安装更新。
Split APK 将原来一个 APK 中多个模块共享同一份资源的模型分离成多个 APK 使用各自的资源,而且能够继承 Base APK 中的资源,多个 APK 有相同的 data,cache 目录。android
在引入了 Split APK 机制后,APK 有两种分类 :segmentfault
Single APK:安装文件为一个完整的 APK,即 Base APK。Android 称其为 Monolithic。
Mutiple APK:安装文件在一个文件目录中,其内部有多个被拆分的 APK,这些 APK 由一个 Base APK 和一个或多个Split APK组成。Android 称其为 Cluster。cookie
/** * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}. */ public Package parsePackage(File packageFile, int flags) throws PackageParserException { return parsePackage(packageFile, flags, false /* useCaches */); }
新增一个 useCaches 参数:app
public Package parsePackage(File packageFile, int flags, boolean useCaches) throws PackageParserException { Package parsed = useCaches ? getCachedResult(packageFile, flags) : null; if (parsed != null) { return parsed; } long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0; // 若是解析的 packageFile 是一个目录,则调用 parseClusterPackage if (packageFile.isDirectory()) { parsed = parseClusterPackage(packageFile, flags); } else { // 若是是单个 APK 文件,则调用 parseMonolithicPackage 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 做为分析的分支,当你搞懂这个方法的具体逻辑,单个 APK 的分析天然更简单了。ide
一块儿来瞅瞅源码:函数
private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException { /* * 调用 parseClusterPackageLite 方法用于轻量级解析目录文件, * 之因此要轻量级解析是由于解析APK是一个复杂耗时的操做,这里的逻辑并不须要APK全部的信息。 */ final PackageLite lite = parseClusterPackageLite(packageDir, 0); /* * mOnlyCoreApps 用来指示 PackageParser 是否只解析“核心”应用, * “核心”应用指的是 AndroidManifest 中属性 coreApp 值为 true,只解析“核心”应用是为了建立一个极简的启动环境, * 能够经过 PackageParser 的 setOnlyCoreApps 方法来设置 mOnlyCoreApps 的值。 * * lite.coreApp 表示当前包是否包含“核心”应用,若是不知足条件就会抛出异常。 */ if (mOnlyCoreApps && !lite.coreApp) { throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, "Not a coreApp: " + packageDir); } // Build the split dependency tree. SparseArray<int[]> 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 { final AssetManager assets = assetLoader.getBaseAssetManager(); final File baseApk = new File(lite.baseCodePath); // 解析 base APK final Package pkg = parseBaseApk(baseApk, assets, flags); if (pkg == null) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "Failed to parse base APK: " + baseApk); } if (!ArrayUtils.isEmpty(lite.splitNames)) { // 获取 split APK 的数量 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++) { final AssetManager splitAssets = assetLoader.getSplitAssetManager(i); // 解析每一个 split APK 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); } }
static PackageLite parseClusterPackageLite(File packageDir, int flags) throws PackageParserException { ... ... for (File file : files) { if (isApkFile(file)) { // 经过 parseApkLite 方法解析每一个 Mutiple APK,获得每一个 Mutiple APK 对应的 ApkLite(轻量级 APK 信息) final ApkLite lite = parseApkLite(file, flags); ... ... } } ... ... final String codePath = packageDir.getAbsolutePath(); // 将这些 ApkLite 封装为一个 PackageLite(轻量级包信息)并返回 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames, configForSplits, splitCodePaths, splitRevisionCodes); }
private static final String MNT_EXPAND = "/mnt/expand/"; 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()); // 若是 APK 的路径以 /mnt/expand/ 开头,就截取该路径获取 volumeUuid 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 { 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]; // 再次调用 parseBaseApk 方法 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); // 用于之后标识这个解析后的 Package pkg.setApplicationVolumeUuid(volumeUuid); // 用于标识该 App 所在的存储卷 UUID 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); } }
咱们发现,上面代码中再次调用了 parseBaseApk 的重载方法,能够看出当前的 parseBaseApk 方法主要是为了获取和设置 volumeUuid。ui
private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { final String splitName; final String pkgName; ... ... // 建立 Package 对象 final Package pkg = new Package(pkgName); //从资源中提取自定义属性集 com.android.internal.R.styleable.AndroidManifest 获得 TypedArray TypedArray sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifest); // 使用 typedarray 获取 AndroidManifest 中的 versionCode 赋值给 Package 的对应属性 pkg.mVersionCode = sa.getInteger( com.android.internal.R.styleable.AndroidManifest_versionCode, 0); pkg.mVersionCodeMajor = sa.getInteger( com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0); pkg.applicationInfo.setVersionCode(pkg.getLongVersionCode()); pkg.baseRevisionCode = sa.getInteger( com.android.internal.R.styleable.AndroidManifest_revisionCode, 0); pkg.mVersionName = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifest_versionName, 0); if (pkg.mVersionName != null) { pkg.mVersionName = pkg.mVersionName.intern(); } // 读取 APK 的 AndroidManifest 中的 coreApp 的值 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false); pkg.mCompileSdkVersion = sa.getInteger( com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0); pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion; pkg.mCompileSdkVersionCodename = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifest_compileSdkVersionCodename, 0); if (pkg.mCompileSdkVersionCodename != null) { pkg.mCompileSdkVersionCodename = pkg.mCompileSdkVersionCodename.intern(); } pkg.applicationInfo.compileSdkVersionCodename = pkg.mCompileSdkVersionCodename; // 获取资源后要回收 sa.recycle(); return parseBaseApkCommon(pkg, null, res, parser, flags, outError); }
最终调用了 parseBaseApkCommon 方法,这个方法主要用来解析APK的AndroidManifest中的各个标签,好比 application、permission、uses-sdk、feature-group 等等。spa
private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { ... ... while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { ... ... // private static final String TAG_APPLICATION = "application"; if (tagName.equals(TAG_APPLICATION)) { if (foundApp) { if (RIGID_PARSER) { outError[0] = "<manifest> has more than one <application>"; mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return null; } else { Slog.w(TAG, "<manifest> has more than one <application>"); XmlUtils.skipCurrentTag(parser); continue; } } foundApp = true; // 其中四大组件的标签在 application 标签下,解析 application 标签的方法为 parseBaseApplication。 if (!parseBaseApplication(pkg, res, parser, flags, outError)) { return null; } } else if (tagName.equals(TAG_OVERLAY)) { ... ... } ... ... }
// parseBaseApplication 方法很长,咱们这里只截取了解析四大组件相关的代码。 private boolean parseBaseApplication(Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { ... ... while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } String tagName = parser.getName(); if (tagName.equals("activity")) { // 调用 parseActivity 方法解析 activity 标签并获得一个 Activity 对象(PackageParser 的静态内部类) Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false, owner.baseHardwareAccelerated); if (a == null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; } hasActivityOrder |= (a.order != 0); // 将解析获得的 Activity 对象保存在 Package 的列表 activities 中 owner.activities.add(a); } else if (tagName.equals("receiver")) { Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, true, false); if (a == null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; } hasReceiverOrder |= (a.order != 0); owner.receivers.add(a); } else if (tagName.equals("service")) { Service s = parseService(owner, res, parser, flags, outError, cachedArgs); if (s == null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; } hasServiceOrder |= (s.order != 0); owner.services.add(s); } else if (tagName.equals("provider")) { Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs); if (p == null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; } owner.providers.add(p); } ... ... } ... ... }
PackageParser 解析 APK 的代码逻辑很是庞大,基本了解本文所讲的就足够了,若是有兴趣能够自行看源码。
parseBaseApk方法主要的解析结构能够理解为如下简图: