开篇
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)- PackageParser
核心源码
关键类 | 路径 |
---|---|
SystemServer.java | frameworks/base/services/java/com/android/server/SystemServer.java |
PackageManagerService.java | frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java |
Process.java | frameworks/base/core/java/android/os/Process.java |
SystemConfig.java | frameworks/base/core/java/com/android/server/SystemConfig.java |
Settings.java | frameworks/base/services/core/java/com/android/server/pm/Settings.java |
简介
PackageManagerService(PMS)是 SystemServer 启动后的第一个核心服务,也是 Android 系统中最常用的服务之一。它负责系统中 Package 的管理,应用程序的安装、卸载、信息查询等。如果你是面向 Android 系统开发的工程师,基础概念我也不需要再多赘述,我们直接跟源码。
构造函数分析 – 扫描Package
PMS 构造函数第二阶段的工作就是扫描系统中的 APK 了。由于需要逐个扫描文件,因此手机上装的程序越多,PMS 的工作量就越大,系统启动速度也就越慢,这就是为什么你的手机启动速度有快慢的原因。
系统库的 dex 优化
接着上面的 PMS 构造函数继续分析源码:
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
... ...
// DEX 优化
mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
"*dexopt*");
mDexManager = new DexManager(this, mPackageDexOptimizer, installer, mInstallLock);
synchronized (mPackages) {
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
mHandler = new PackageHandler(mHandlerThread.getLooper());
mProcessLoggingHandler = new ProcessLoggingHandler();
Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
mDefaultPermissionPolicy = new DefaultPermissionGrantPolicy(this);
mInstantAppRegistry = new InstantAppRegistry(this);
// 为 data/ 目录下的某些子目录生成File实例
File dataDir = Environment.getDataDirectory();
// data/app 存放第三方应用
mAppInstallDir = new File(dataDir, "app");
mAppLib32InstallDir = new File(dataDir, "app-lib");
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
// data/app-private 存放 drm 保护的应用
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
sUserManager = new UserManagerService(context, this,
new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
// 获取 SystemConfig 中解析到的 <permission> 标签标识的 permission 信息,保存到 Settings::mPermissions
ArrayMap<String, SystemConfig.PermissionEntry> permConfig
= systemConfig.getPermissions();
for (int i=0; i<permConfig.size(); i++) {
SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
BasePermission bp = mSettings.mPermissions.get(perm.name);
if (bp == null) {
bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
mSettings.mPermissions.put(perm.name, bp);
}
if (perm.gids != null) {
bp.setGids(perm.gids, perm.perUser);
}
}
// 得到除 framework 之外的系统中的共享库列表,从 SystemConfig 获取解析到的数据
ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
final int builtInLibCount = libConfig.size();
for (int i = 0; i < builtInLibCount; i++) {
String name = libConfig.keyAt(i);
String path = libConfig.valueAt(i);
addSharedLibraryLPw(path, null, name, SharedLibraryInfo.VERSION_UNDEFINED,
SharedLibraryInfo.TYPE_BUILTIN, PLATFORM_PACKAGE_NAME, 0);
}
mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
// 读取packages.xml的内容,并对mSettings::mPackages等成员进行赋值;packages.xml文件中的内容是上一次扫描apk目录的结果;
// 当前这一次扫描的结果是保存在PackageManagerService::mPackages列表中;
// 对比上次扫描的结果来检查本次扫描到的应用中是否有被升级包覆盖的系统应用,如果有则从PackageManagerService::mPackages中移除;
// 这样,PackageManagerService::mPackages的记录就和mSettings::mPackages的一致了;
// 系统最终会将本次apk扫描的结果重新写入packages.xml中
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
// Clean up orphaned packages for which the code path doesn't exist
// and they are an update to a system app - caused by bug/32321269
final int packageSettingCount = mSettings.mPackages.size();
// 清理那些代码路径不存在的异常 package
for (int i = packageSettingCount - 1; i >= 0; i--) {
PackageSetting ps = mSettings.mPackages.valueAt(i);
if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
&& mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
mSettings.mPackages.removeAt(i);
mSettings.enableSystemPackageLPw(ps.name);
}
}
if (mFirstBoot) {
requestCopyPreoptedFiles();
}
// 设置模块来代替 framework-res.apk 中缺省的 ResolverActivity
String customResolverActivity = Resources.getSystem().getString(
R.string.config_customResolverActivity);
if (TextUtils.isEmpty(customResolverActivity)) {
customResolverActivity = null;
} else {
mCustomResolverComponentName = ComponentName.unflattenFromString(
customResolverActivity);
}
long startTime = SystemClock.uptimeMillis(); // 记录扫描开始的时间
// 需要系统提前加载的一些 jar
final String bootClassPath = System.getenv("BOOTCLASSPATH");
final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
if (bootClassPath == null) {
Slog.w(TAG, "No BOOTCLASSPATH found!");
}
if (systemServerClassPath == null) {
Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!");
}
扫描系统 Package
清空 cache 文件后,PMS 终于进入重点段了。接下来看 PMS 第二阶段工作的核心内容,即扫描 Package,相关代码如下:
// PackageManagerService.java
// 定义 frameworkDir 指向 /system/frameworks 目录
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
final VersionInfo ver = mSettings.getInternalVersion();
mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
// when upgrading from pre-M, promote system app permissions from install to runtime
mPromoteSystemApps =
mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;
// When upgrading from pre-N, we need to handle package extraction like first boot,
// as there is no profiling data available.
mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;
mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
// save off the names of pre-existing system packages prior to scanning; we don't
// want to automatically grant runtime permissions for new system apps
// 是否需要提升权限
if (mPromoteSystemApps) {
Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
while (pkgSettingIter.hasNext()) {
PackageSetting ps = pkgSettingIter.next();
if (isSystemApp(ps)) {
// 遍历Settings::mPackages集合,将系统APP加入到PackageManagerService::mExistingSystemPackages
mExistingSystemPackages.add(ps.name);
}
}
}
mCacheDir = preparePackageParserCache(mIsUpgrade);
// 定义扫描参数
int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
if (mIsUpgrade || mFirstBoot) {
scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
}
// 先扫描 /vendor/overlay 目录
scanDirTracedLI(new File(VENDOR_OVERLAY_DIR), mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
// 调用 scanDirTracedLI 函数扫描 /system/frameworks 目录
scanDirTracedLI(frameworkDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
scanFlags | SCAN_NO_DEX, 0);
// Collected privileged system packages.
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
// 扫描 /system/priv-app 下的 package
scanDirTracedLI(privilegedAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
// Collect ordinary system packages.
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
// 扫描 /system/app 下的 package
scanDirTracedLI(systemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// Collect all vendor packages.
File vendorAppDir = new File("/vendor/app");
try {
vendorAppDir = vendorAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
// 扫描 /vendor/app 下的 package
scanDirTracedLI(vendorAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// Collect all OEM packages.
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
// 扫描 OEM 的 Package
scanDirTracedLI(oemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
由以上代码可知,PMS 将扫描以下几个目录(仅列出重点):
✨ /system/frameworks :该目录中的文件都是系统库,例如:framework.jar、services.jar、framework-res.apk。不过 scanDirTracedLI 只扫描 APK 文件,所以 framework-res.apk 是该目录中唯一“受宠”的文件。
✨ /system/app :该目录下全是默认的系统应用。例如:Browser.apk、SettingsProvider.apk 等。
✨ /vendor/app :该目录中的文件由厂商提供,即全是厂商特定的 APK 文件,目前市面上的厂商都把自己的应用放在 /system/app 目录下。
scanDirTracedLI
PMS 调用 scanDirTracedLI 函数进行扫描,下面分析此函数:
public void scanDirTracedLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
try {
scanDirLI(dir, parseFlags, scanFlags, currentTime); // 调用 scanDirLI 函数
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
我们可以看出,实际是调用了 scanDirLI 函数进行扫描工作!
scanDirLI
下面的重点就是来关注 scanDirLI 函数了:
private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
// 列举该目录下的文件
final File[] files = dir.listFiles();
if (ArrayUtils.isEmpty(files)) {
Log.d(TAG, "No files in app dir " + dir);
return;
}
ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
mParallelPackageParserCallback);
int fileCount = 0;
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
if (!isPackage) {
// Ignore entries which are not packages
continue;
}
parallelPackageParser.submit(file, parseFlags);
fileCount++;
}
// Process results one by one
for (; fileCount > 0; fileCount--) {
ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
Throwable throwable = parseResult.throwable;
int errorCode = PackageManager.INSTALL_SUCCEEDED;
if (throwable == null) {
// Static shared libraries have synthetic package names
if (parseResult.pkg.applicationInfo.isStaticSharedLibrary()) {
renameStaticSharedLibraryPackage(parseResult.pkg);
}
try {
if (errorCode == PackageManager.INSTALL_SUCCEEDED) {
// 调用 scanPackageLI 函数扫描一个特定的文件,返回值是 PackageParser 的内部类 Package,该类的实例代表一个 APK 文件,所以它就是和 APK 文件对应的数据结构
scanPackageLI(parseResult.pkg, parseResult.scanFile, parseFlags, scanFlags,
currentTime, null);
}
... ...
}
// Delete invalid userdata apps
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
errorCode == PackageManager.INSTALL_FAILED_INVALID_APK) {
// 非系统 Package 扫描失败,删除文件
removeCodePathLI(parseResult.scanFile);
}
}
parallelPackageParser.close();
}
scanPackageLI – 01
PMS 中有三处 scanPackageLI,我们后面会一一分析到,先来看第一个也是最先碰到的 sanPackageLI 函数。
private PackageParser.Package scanPackageLI(PackageParser.Package pkg, File scanFile,
final int policyFlags, int scanFlags, long currentTime, @Nullable UserHandle user)
throws PackageManagerException {
if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
if (pkg.childPackages != null && pkg.childPackages.size() > 0) {
scanFlags |= SCAN_CHECK_ONLY;
}
} else {
scanFlags &= ~SCAN_CHECK_ONLY;
}
// Scan the parent
PackageParser.Package scannedPkg = scanPackageInternalLI(pkg, scanFile, policyFlags,
scanFlags, currentTime, user);
// Scan the children
final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
PackageParser.Package childPackage = pkg.childPackages.get(i);
scanPackageInternalLI(childPackage, scanFile, policyFlags, scanFlags,
currentTime, user);
}
if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
return scanPackageLI(pkg, scanFile, policyFlags, scanFlags, currentTime, user);
}
return scannedPkg;
}
scanPackageInternalLI
调用 scanPackageInternalLI():
private PackageParser.Package scanPackageInternalLI(PackageParser.Package pkg, File scanFile,
int policyFlags, int scanFlags, long currentTime, @Nullable UserHandle user)
throws PackageManagerException {
PackageSetting ps = null;
PackageSetting updatedPkg;
// 判断系统 APP 是否需要更新
synchronized (mPackages) {
// 查看是否已经有该安装包,通过 mSetting 查找
String oldName = mSettings.getRenamedPackageLPr(pkg.packageName);
if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
// 如果存在同一个包名的老的安装包,且已经改回原始名称了
ps = mSettings.getPackageLPr(oldName);
}
// 如果没有原始包,则使用真实包名
if (ps == null) {
ps = mSettings.getPackageLPr(pkg.packageName);
}
// 查这个包是否是一个隐藏或者可以更新的系统包
updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
// If this is a package we don't know about on the system partition, we
// may need to remove disabled child packages on the system partition
// or may need to not add child packages if the parent apk is updated
// on the data partition and no longer defines this child package.
if ((policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
// If this is a parent package for an updated system app and this system
// app got an OTA update which no longer defines some of the child packages
// we have to prune them from the disabled system packages.
PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(pkg.packageName);
if (disabledPs != null) {
final int scannedChildCount = (pkg.childPackages != null)
? pkg.childPackages.size() : 0;
final int disabledChildCount = disabledPs.childPackageNames != null
? disabledPs.childPackageNames.size() : 0;
for (int i = 0; i < disabledChildCount; i++) {
String disabledChildPackageName = disabledPs.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);
}
}
}
}
}
... ...
// Note that we invoke the following method only if we are about to unpack an application
// 调用第二个 scanPackageLI 函数
PackageParser.Package scannedPkg = scanPackageLI(pkg, policyFlags, scanFlags
| SCAN_UPDATE_SIGNATURE, currentTime, user);
... ...
}
scanPackageLI – 02
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
long currentTime, UserHandle user) throws PackageManagerException {
// 创建一个 PackageParser 对象,用于解析包
PackageParser pp = new PackageParser();
// 设置 PackageParse 的三个属性
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
pp.setCallback(mPackageParserCallback);
// 判断扫描模式
if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
}
// 解析APK获取对应PackageParser.Package对象 pkg
final PackageParser.Package pkg;
// 调用 PackageParser 的 parsePackage 函数解析 APK 文件
try {
// 💥 💥 💥 💥 💥 💥 真正的解析
pkg = pp.parsePackage(scanFile, parseFlags);
} catch (PackageParserException e) {
throw PackageManagerException.from(e);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
// Static shared libraries have synthetic package names
if (pkg.applicationInfo.isStaticSharedLibrary()) {
renameStaticSharedLibraryPackage(pkg);
}
return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);
}
扫描非系统 Package
if (!mOnlyCore) { // mOnlyCore 用于控制是否扫描非系统 Package
// do this first before mucking with mPackages for the "expecting better" case
final Iterator<PackageParser.Package> pkgIterator = mPackages.values().iterator();
while (pkgIterator.hasNext()) {
final PackageParser.Package pkg = pkgIterator.next();
if (pkg.isStub) {
stubSystemApps.add(pkg.packageName);
}
}
final Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
PackageSetting ps = psit.next();
/*
* If this is not a system app, it can't be a
* disable system app.
*/
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
/// M: Operator apps are belong to system domain, therefore, need prune.
/// We should also consider OTA from old version without mtkFlag
if (sPmsExt.isNotOperatorApp(ps))
continue;
}
/*
* If the package is scanned, it's not erased.
*/
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
/*
* If the system app is both scanned and in the
* disabled packages list, then it must have been
* added via OTA. Remove it from the currently
* scanned package so the previously user-installed
* application can be scanned.
*/
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
logCriticalInfo(Log.WARN, "Expecting better updated system app for "
+ ps.name + "; removing system app. Last known codePath="
+ ps.codePathString + ", installStatus=" + ps.installStatus
+ ", versionCode=" + ps.versionCode + "; scanned versionCode="
+ scannedPkg.mVersionCode);
removePackageLI(scannedPkg, true);
mExpectingBetter.put(ps.name, ps.codePath);
}
continue;
}
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
psit.remove();
logCriticalInfo(Log.WARN, "System package " + ps.name
+ " no longer exists; it's data will be wiped");
// Actual deletion of code and data will be handled by later
// reconciliation step
} else {
// we still have a disabled system package, but, it still might have
// been removed. check the code path still exists and check there's
// still a package. the latter can happen if an OTA keeps the same
// code path, but, changes the package name.
final PackageSetting disabledPs =
mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()
|| disabledPs.pkg == null) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
}
}
}
if (!mOnlyCore) {
scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
| PackageParser.PARSE_FORWARD_LOCK,
scanFlags | SCAN_REQUIRE_KNOWN, 0);
// Remove disable package settings for updated system apps that were
// removed via an OTA. If the update is no longer present, remove the
// app completely. Otherwise, revoke their system privileges.
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
mSettings.removeDisabledSystemPackageLPw(deletedAppName);
final String msg;
if (deletedPkg == null) {
// should have found an update, but, we didn't; remove everything
msg = "Updated system package " + deletedAppName
+ " no longer exists; removing its data";
// Actual deletion of code and data will be handled by later
// reconciliation step
} else {
// found an update; revoke system privileges
msg = "Updated system package + " + deletedAppName
+ " no longer exists; revoking system privileges";
// Don't do anything if a stub is removed from the system image. If
// we were to remove the uncompressed version from the /data partition,
// this is where it'd be done.
final PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
/// M: [Operator] Revoke operator permissions for the original operator
sPmsExt.clearExtFlags(deletedPkg, deletedPs);
}
logCriticalInfo(Log.WARN, msg);
}
/*
* Make sure all system apps that we expected to appear on
* the userdata partition actually showed up. If they never
* appeared, crawl back and revive the system version.
*/
for (int i = 0; i < mExpectingBetter.size(); i++) {
final String packageName = mExpectingBetter.keyAt(i);
if (!mPackages.containsKey(packageName)) {
final File scanFile = mExpectingBetter.valueAt(i);
logCriticalInfo(Log.WARN, "Expected better " + packageName
+ " but never showed up; reverting to system");
int reparseFlags = mDefParseFlags;
if (FileUtils.contains(privilegedAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED;
} else if (FileUtils.contains(systemAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else if (FileUtils.contains(vendorAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else if (FileUtils.contains(oemAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else {
Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
continue;
}
mSettings.enableSystemPackageLPw(packageName);
try {
scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse original system package: "
+ e.getMessage());
}
}
}
// Uncompress and install any stubbed system applications.
// This must be done last to ensure all stubs are replaced or disabled.
decompressSystemApplications(stubSystemApps, scanFlags);
final int cachedNonSystemApps = PackageParser.sCachedPackageReadCount.get()
- cachedSystemApps;
final long dataScanTime = SystemClock.uptimeMillis() - systemScanTime - startTime;
final int dataPackagesCount = mPackages.size() - systemPackagesCount;
Slog.i(TAG, "Finished scanning non-system apps. Time: " + dataScanTime
+ " ms, packageCount: " + dataPackagesCount
+ " , timePerPackage: "
+ (dataPackagesCount == 0 ? 0 : dataScanTime / dataPackagesCount)
+ " , cached: " + cachedNonSystemApps);
if (mIsUpgrade && dataPackagesCount > 0) {
MetricsLogger.histogram(null, "ota_package_manager_data_app_avg_scan_time",
((int) dataScanTime) / dataPackagesCount);
}
}
构造函数分析 – 扫尾工作
这部分任务比较简单,就是将第二阶段手机的信息再集中整理一次,可自行研究。
总结
第二阶段分析就此结束!