SystemServer 的 startBootStrapServices() 方法中调用 PackageManagerService 的静态方法 main()。第四个参数 mOnlyCore 跟全盘加密相关,如果 cryptState 是 ENCRYPTING_STATE 或 ENCRYPTED_STATE,mOnlyCore 为 true。
在 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
如果 mOnlyCore 为 false,则扫描 /data/app 和 /data/app-private。扫描这两个目录时的 scanFlags 带有 SCAN_REQUIRE_KNOWN flag,这个 flag 表明扫描的 APK 必须是已知的,即在 /data/system/packages.xml 中存在。
packages.xml 文件类似于注册表,已经扫描(安装)过的 APK 会写入该文件。而 /data/app 就是三方应用的 APK 文件存放地(三方应用安装的时候会把 APK 文件拷贝到此目录),所以如果把未经过安装的 APK 放入 /data/app 目录是会扫描失败(安装加载 )的,有点死循环。
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);
如果解析没问题,则调用 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。