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。