0. PackageManagerService 启动

SystemServer 的 startBootStrapServices() 方法中调用 PackageManagerService 的静态方法 main()。第四个参数 mOnlyCore 跟全盘加密相关,如果 cryptStateENCRYPTING_STATEENCRYPTED_STATEmOnlyCoretrue

1. 扫描目录

main() 方法中创建 PackageManagerService 对象。构造方法中会调用 scanDirTracedLI() 方法扫描文件夹,扫描的顺序如下所示,从上至下。

scanDirTracedLI(File dir, int parseFlags, int scanFlags, long currentTime)

/vender/overlay
/system/framework
/system/priv-app
/system/app
/vendor/app
/oem/app

如果 mOnlyCorefalse,则扫描 /data/app/data/app-private。扫描这两个目录时的 scanFlags 带有 SCAN_REQUIRE_KNOWN flag,这个 flag 表明扫描的 APK 必须是已知的,即在 /data/system/packages.xml 中存在。

2. packages.xml 文件

packages.xml 文件类似于注册表,已经扫描(安装)过的 APK 会写入该文件。而 /data/app 就是三方应用的 APK 文件存放地(三方应用安装的时候会把 APK 文件拷贝到此目录),所以如果把未经过安装的 APK 放入 /data/app 目录是会扫描失败(安装加载 )的,有点死循环。

3. PackageParser 的解析

scanDirTracedLI() 调用 scanDirLI() 方法,它会遍历目录下的文件。如果是 APK 文件,则调用 ParallelPackageParser 的 submit() 方法。ParrallelPackageParser 会并发解析 APK 文件返回 ParseResult 对象。

parallelPackageParser.submit(file, parseFlags);

ParrallelPackageParser 解析时会创建一个 PackageParser 对象,然后调用 parserPackage() 方法解析 APK 文件。parserPackage() 方法就是解析资源文件、签名等等,返回 PackageParser.Package 对象。

ParserResult pr = new ParseResult();
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
pp.setCacheDir(mCacheDir);
pp.setCallback(mPackageParserCallback);
pr.scanFile = scanFile;
pr.pkg = parsePackage(pp, scanFile, parseFlags);

4. 验证 Package 的有效性

如果解析没问题,则调用 scanPackageLI() 方法,它调用 scanPackageInternalLI(),它扫描后返回新解析的 Package 对象。解析是调用 scanPackageLI()

PackageParser.Package scannedPkg = scanPackageLI(pkg, policyFlags, scanFlags
        | SCAN_UPDATE_SIGNATURE, currentTime, user);

scanPackageLI() 调用 scanPackageDirtyLI(),它会调用 assertPackageIsValid() 方法检查 Package 对象在 policyFlags 下是否可用。

privste void assertPackageIsValid(PackgeParser.Package pkg, int policyFlags, int scanFlags)
        throws PackageManagerException {
    if ((scanFlags & SCAN_REQUIRE_KNOWN) != 0) {
        PackageSetting known = mSettings.getPackageLPr(pkg.packageName);
        if (known != null) {
        } else {
            throw new PackageMannagerException(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                    "Application package " + pkg.packageName
                    + " not found; ignoring.");
}}}

如果 scanFlags() 包含 SCAN_REQUIRE_KNOWN 需要检查是否是已知的 Package,即在 /data/system/packages.xml 中存在。否则抛出 PackageManagerException。