基于Android 8.1源码, 分析PackageManagerService的启动过程
frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/services/core/java/com/android/server/SystemConfig.java
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
frameworks/base/services/core/java/com/android/server/pm/Settings.java
frameworks/base/services/core/java/com/android/server/pm/Installer.java
frameworks/base/core/java/android/content/pm/PackageManager.java
frameworks/base/core/java/android/content/pm/PackageParser.java
1. 概述
PackageManagerService(简称PMS),是Android系统中核心服务之一,管理apk相关的工作,如安装、升级和卸载应用等。PKMS服务的启动是由SystemServer启动的。从开机到手机界面上显示app的图标的流程概述如下:
- 手机开机之后,系统开始运行,启动了init进程
- init进程启动了Android系统的母进程-Zygote进程
- Zygote进程fork systemserver进程
- systemserver中启动PMS服务
- PMS中扫面特定目录下的应用程序apk,然后解析apk,将信息保存起来,并启动一些系统应用,如 桌面Launcher应用
- 启动桌面Launcher应用后,Launcher应用会将已安装的app图标显示在手机界面上
本篇文章主要是分析上述的第4和5流程:PMS启动流程和 PMS解析apk过程。
2. PMS初始化
由Android O系统启动流程–SystemServer篇二可知,android系统的核心服务最后由SystemServer的startBootstrapServices
方法启动的。启动PMS服务的代码如下:
[->SystemServer.java]
private void startBootstrapServices() {
...
// 启动installer服务【见小节2.1】
Installer installer = mSystemServiceManager.startService(Installer.class);
...
// Only run "core" apps if we're encrypting the device.
// 获取设别是否加密(手机设置密码),如果设备加密了,则只解析"core"应用
String cryptState = SystemProperties.get("vold.decrypt");
if (ENCRYPTING_STATE.equals(cryptState)) {
Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
mOnlyCore = true;
} else if (ENCRYPTED_STATE.equals(cryptState)) {
Slog.w(TAG, "Device encrypted - only parsing core apps");
mOnlyCore = true;
}
...
// 创建PMS对象【见小节3】
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
...
}
private void startOtherServices() {
...
// dex优化【见小节4.1】
mPackageManagerService.updatePackagesIfNeeded();
...
// 磁盘维护【见小节4.2】
mPackageManagerService.performFstrimIfNeeded();
...
// 准备就绪【见小节4.3】
mPackageManagerService.systemReady();
...
// 等待所有pacakges准备就绪【见小节4.4】
mPackageManagerService.waitForAppDataPrepared();
}
整个system_server进程启动过程,涉及PMS服务的主要几个动作如下,接下来分别讲解每个过程
- PackageManagerService.main
- PackageManagerService.performBootDexOpt
- PackageManagerService.systemReady
2.1 启动Installer服务
Installer 是 PackageManagerService 的一个内部类,继承自SystemService,协助完成安装过程,主要是进行 apk 格式转换和数据目录建立,封装对文件和路径操作,真正的安装工作交由 IInstalld 内部类对象完成。
Installer服务的启动流程如下:
- 构造函数 Installer初始化 context 和 isolated(是否真正连接installd)成员变量
- 重写 onStart() 方法,基于 isolated 判断是否调用 connect() 进行连接
- connect() 通过 ServiceManager 获取 installd 服务并拿到服务的本地代理放到成员变量 mInstalld 中
- Installer 调用 dexopt() 最终调用了 mInstalld 的dexopt() 方法,其他方法类似,几乎就是一个 IInstalld 类的封装
注意: Installer 的实现变化很大:6.0 上通过以命令的方式通过 execute 方法执行;8.1 通过 AIDL 接口实现 PackageManageService(system权限) 与 installd(root权限) 守护进程共同完成应用管理。
3. PackageManagerService.main
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
// Self-check for initial settings.
PackageManagerServiceCompilerMapping.checkProperties();
// 创建PMS实例
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
// 将PMS注册到ServiceManager,这是binder服务的常规注册流程
ServiceManager.addService("package", m);
final PackageManagerNative pmn = m.new PackageManagerNative();
ServiceManager.addService("package_native", pmn);
return m;
}
接下来分析PMS的构造方法,这部分的代码很长,简单概括如下:
- 创建了 Java 层 Installer 和 C 层 installd 之间的 socket 连接
- 扫描各目录下 apk文件完成安装(建立各安装包的配置结构信息,并添加到全局列表中进行管理)
- 创建了 PackageHandler 对象并建立消息循环,接收外部的安装请求
- 解析权限,建立底层 Linux Kernel 的用户机制和虚拟机层权限机制之间的映射
主要分为5个阶段:
- PMS_START
- PMS_SYSTEM_SCAN_START
- PMS_DATA_SCAN_START
- PMS_SCAN_END
- PMS_READY
3.1 PMS_START阶段
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis());
if (mSdkVersion <= 0) {
Slog.w(TAG, "**** ro.build.version.sdk not set!");
}
mContext = context;
mPermissionReviewRequired = context.getResources().getBoolean(
R.bool.config_permissionReviewRequired);
mFactoryTest = factoryTest;
mOnlyCore = onlyCore;// 标记是否只加载核心服务
mMetrics = new DisplayMetrics();// 创建DisplayMetrics对象,保存分辨率等相关信息
mSettings = new Settings(mPackages);// 步骤1:创建Settings对象【见小节3.1.1】
// 添加system, phone, log, nfc, bluetooth, shell这六种shareUserId到mSettings
mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
...
mInstaller = installer; // 创建Installer对象,与installd交互
// 构造PackageDexOptimizer及DexManager类,处理dex优化
mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
"*dexopt*");
mDexManager = new DexManager(this, mPackageDexOptimizer, installer, mInstallLock);
// 运行在”android.fg"线程的handler对象
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
// 权限变化监听器
mOnPermissionChangeListeners = new OnPermissionChangeListeners(
FgThread.get().getLooper());
// 步骤2:获取默认分辨率
getDefaultDisplayMetrics(context, mMetrics);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "get system config");
// 步骤3:获取系统配置信息【见小节3.1.2】
SystemConfig systemConfig = SystemConfig.getInstance();
// 取出全局的groupId保存在PMS中
mGlobalGids = systemConfig.getGlobalGids();
// 取出系统权限保存到PMS的全局变量中
mSystemPermissions = systemConfig.getSystemPermissions();
// 取出可用的feature保存在PMS的全局变量中
mAvailableFeatures = systemConfig.getAvailableFeatures();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
mProtectedPackages = new ProtectedPackages(mContext);
// 创建提供服务/数据的子组件。这里的顺序很重要,使用到了两个重要的同步锁:mInstallLock、mPackages
synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
//步骤4: 创建名为“PackageManager”的handler线程,负责apk的安装、卸载
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
mHandler = new PackageHandler(mHandlerThread.getLooper());
mProcessLoggingHandler = new ProcessLoggingHandler();
// 将mHandler加入到Watchdog检测中,安装应用可能会有大量的I/O操作会比较耗时
// 因此这里的WATCHDOG_TIMEOUT设置为10min
Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
mDefaultPermissionPolicy = new DefaultPermissionGrantPolicy(this);
mInstantAppRegistry = new InstantAppRegistry(this);
// 步骤5: 创建各种目录
// 为/data 目录下子目录生成文件对象
File dataDir = Environment.getDataDirectory();
// 对应/data/app 目录:用于存放安装的应用
mAppInstallDir = new File(dataDir, "app");
// 对应/data/app-lib 目录:用于存放 应用的native库
mAppLib32InstallDir = new File(dataDir, "app-lib");
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
// 对应/data/app-private 目录:存放drm保护的应用
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
mRegionalizationAppInstallDir = new File(dataDir, "app-regional");
// 步骤6:创建用户管理服务,管理多用户
sUserManager = new UserManagerService(context, this,
new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
// Propagate permission configuration in to package manager.
// 步骤7:从/etc/permissions目录下面读取获取系统中定义的permissions
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中
mSettings.mPermissions.put(perm.name, bp);
}
if (perm.gids != null) {
bp.setGids(perm.gids, perm.perUser);
}
}
// 步骤8:通过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);
}
// 步骤9:读取安装相关SELinux策略
mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
// 步骤10:读取文件package.xml内容,解析后插到mSettings的mPackages等变量中
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
...
PMS_START阶段概括为以下步骤:
-
创建Settings对象
-
用系统属性来设置DisplayMetrics对象, 保存分辨率等相关信息
-
获取系统配置信息,如全局的groupId、系统权限和可用的feature
-
创建名为“PackageManager”的handler线程,负责apk的安装、卸载
-
创建各种目录,如/data/app、/data/app-lib、/data/app-asec、/data/app-private、/data/app-regional
-
创建用户管理服务,管理多用户
-
从/etc/permissions目录下面读取获取系统中定义的permissions
-
通过SystemConfig得到系统中的共享库列表
-
读取安装相关SELinux策略
-
读取文件package.xml等文件内容,解析后插到mSettings的mPackages等变量中
从/data/system/packages.xml、packages-backup.xml、packages.list 、packages-stopped.xml和packages-stopped-backup.xml文件中获取packages、permissions相关信息,添加到相关数据结构中,packages.xml文件记录了系统的permissions以及每个apk的name、codePath、flags、version等相关信息。这些信息是安装apk时解析apk的AndroidManifest.xml文件获取的。当有apk升级、安装或卸载都会更新packages.xml文件。
3.1.1 创建Settings对象
[->Settings.java]
Settings(Object lock) {
this(Environment.getDataDirectory(), lock);
}
Settings(File dataDir, Object lock) {
mLock = lock;
mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);
mSystemDir = new File(dataDir, "system");
mSystemDir.mkdirs();// 创建/data/system
FileUtils.setPermissions(mSystemDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1, -1);
mSettingsFilename = new File(mSystemDir, "packages.xml");
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
mPackageListFilename = new File(mSystemDir, "packages.list");
FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);
final File kernelDir = new File("/config/sdcardfs");
mKernelMappingFilename = kernelDir.exists() ? kernelDir : null;
// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}
Settings类是PackageManager中重要的管理类,它主要保存应用的动态设置。
文件 | 功能 |
---|---|
packages.xml | 记录所有安装app的信息:维护的是应用包的基本信息,权限信息、用户权组信息等 |
packages-backup.xml | 备份文件 |
packages-stopped.xml | 记录系统被强制停止的文件 |
packages-stopped-backup.xml | 备份文件 |
packages.list | 记录应用的数据信息:维护的是应用包列表,只是包含具体的包名以及存储的路径等 |
3.1.2 获取系统配置信息
[->SystemConfig.java]
SystemConfig() {
// Read configuration from system
// 从/etc/sysconfig读取配置
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
// Read configuration from the old permissions dir
// 从旧权限目录/etc/permissions读取配置
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
// Allow Vendor to customize system configs around libs, features, permissions and apps
// 允许供应商自定义有关libs、功能、权限和应用程序的系统配置
int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
ALLOW_APP_CONFIGS;
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
// Allow ODM to customize system configs around libs, features and apps
int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
// Only allow OEM to customize features
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES);
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES);
//Remove vulkan specific features
if (SystemProperties.getBoolean("persist.graphics.vulkan.disable", false)) {
removeFeature(PackageManager.FEATURE_VULKAN_HARDWARE_LEVEL);
removeFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION);
removeFeature(PackageManager.FEATURE_VULKAN_HARDWARE_COMPUTE);
}
// Remove android extension pack for opengles version 3.0
int value = SystemProperties.getInt("ro.opengles.version", 0);
if (value > 0 && (value == 196608)) {
if (mAvailableFeatures.remove("android.hardware.opengles.aep") != null) {
Slog.d(TAG, "Removed android.hardware.opengles.aep feature for opengles 3.0");
}
}
}
readPermissions()解析指定目录下的所有xml文件,比如将标签
- /system/etc/sysconfig
- /system/etc/permissions
- /vendor/etc/sysconfig
- /vendor/etc/permissions
- /odm/etc/sysconfig
- /odm/etc/permissions
- /oem/etc/sysconfig
- /oem/etc/permissions
该方法是解析指定目录下所有的具有可读权限的,且以xml后缀文件。
SystemConfig类与系统的配置相关,通过读取相关的文件,记录相关的配置,如权限、相关白名单等。关于apk权限相关问题,另开一篇文章详细讲解。
3.2 BOOT_PROGRESS_PMS_SYSTEM_SCAN_START阶段
// 记录开始扫描的时间
long startTime = SystemClock.uptimeMillis();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
startTime);
// 步骤1:获取Java 启动类库、framework所有核心库,在init.rc文件配置
final String bootClassPath = System.getenv("BOOTCLASSPATH");
final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
// frameworkDir的路径为/system/framework
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
...
// 准备packages parser的cache空间
mCacheDir = preparePackageParserCache(mIsUpgrade);
// Set flag to monitor and not change apk file paths when
// scanning install directories.
// 配置扫描的参数
int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
if (mIsUpgrade || mFirstBoot) {
scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
}
// 步骤2:扫描/vendor/overlay目录下的package
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);
// 扫描静态overlay的packages
mParallelPackageParserCallback.findStaticOverlayPackages();
// Find base frameworks (resource packages without code).
// 步骤3:扫描/system/framework目录下的package
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");
// 步骤4:扫描/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.
// 步骤5:扫描/system/app目录下的普通package
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// Collect all vendor packages.
// 步骤6:扫描/vendor/app目录下的vendor供应商package
File vendorAppDir = new File("/vendor/app");
try {
vendorAppDir = vendorAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(vendorAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// Collect all OEM packages.
// 步骤7:扫描/oem/app目录下的oem制造商的package
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirTracedLI(oemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// Collect all Regionalization packages form Carrier's res packages.
// 如果支持运营商/区域化,则扫描加载运营商的package
if (RegionalizationEnvironment.isSupported()) {
Log.d(TAG, "Load Regionalization vendor apks");
final List<File> RegionalizationDirs =
RegionalizationEnvironment.getAllPackageDirectories();
for (File f : RegionalizationDirs) {
File RegionalizationSystemDir = new File(f, "system");
// Collect packages in <Package>/system/priv-app
scanDirLI(new File(RegionalizationSystemDir, "priv-app"),
PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
// Collect packages in <Package>/system/app
scanDirLI(new File(RegionalizationSystemDir, "app"),
PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags, 0);
// Collect overlay in <Package>/system/vendor
scanDirLI(new File(RegionalizationSystemDir, "vendor/overlay"),
PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_TRUSTED_OVERLAY,
scanFlags | SCAN_TRUSTED_OVERLAY, 0);
}
}
// Prune any system packages that no longer exist.
// 步骤8:删除不再存在的系统package
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
// Stub packages must either be replaced with full versions in the /data
// partition or be disabled.
final List<String> stubSystemApps = new ArrayList<>();
if (!mOnlyCore) {
// 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();
// 如果不是系统package,则可设置为disabled的,这里先跳过
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
continue;
}
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
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 {
final PackageSetting disabledPs =
mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()
|| disabledPs.pkg == null) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
}
}
}
//look for any incomplete package installations
// 步骤9:查找那些安装不完整的package,并将其删除
ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
for (int i = 0; i < deletePkgsList.size(); i++) {
final String packageName = deletePkgsList.get(i).name;
logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + packageName);
synchronized (mPackages) {
mSettings.removePackageLPw(packageName);
}
}
//delete tmp files
//步骤10:删除临时package
deleteTempPackageFiles();
final int cachedSystemApps = PackageParser.sCachedPackageReadCount.get();
// Remove any shared userIDs that have no associated packages
// 步骤11:删除那些没有对应package的shared uid
mSettings.pruneSharedUsersLPw();
final long systemScanTime = SystemClock.uptimeMillis() - startTime;
final int systemPackagesCount = mPackages.size();
if (mIsUpgrade && systemPackagesCount > 0) {
MetricsLogger.histogram(null, "ota_package_manager_system_app_avg_scan_time",
((int) systemScanTime) / systemPackagesCount);
}
scanDirTracedLI
方法扫描的目录包括:
- 系统应用,目录有
/vender/overlay
、/system/framework
、/system/priv-app
、/system/app
、/vendor/app
、/oem/app
- 非系统应用,目录有
/data/app
、/data/app-private
下图是scanDirTracedLI
的流程图。
可以看到依次调用 scanDirLI
、scanPackageLI
、scanPackageInternalLI
。
其中,scanDirLI
调用了 ParallelPackageParser
类进行解析,真正的工作还是交给 PackageParser
来完成。PackageParser
的 parsePackage
方法内部完成了应用的解析,实际上是解析了 AndroidManifest.xml
文件里面各个标签,包括包名、版本、权限、各组件这些信息,最后的解析结果放在 PackageParser.Package
类中返回给 PMS,这样 PMS 就拥有应用的信息便与做各种管理。
后面继续调用了 scanPackageLI
和 scanPackageInternalLI
是进一步检测应用是否需要更新,如果需要更新则接着调用 createInstallArgsForExisting
构造安装参数开始安装,安装涉及到的签名校验也是在这里,调用了 collectCertificatesLI
、compareSignatures
等。
parsePackage
解析package的详细流程可参考之前写的文章:安卓PMS模块之安装APK(1)
该阶段主要工作是扫描相关目录下的apk文件,然后做一些删除工作,概括如下:
- 从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH
- 扫描/vendor/overlay目录下的package
- 扫描/system/framework目录下的package
- 扫描/system/priv-app目录下的系统package
- 扫描/system/app目录下的普通package
- 扫描/vendor/app目录下的vendor供应商package
- 扫描/oem/app目录下的oem制造商的package
- 删除不再存在的系统package
- 查找那些安装不完整的package,并将其删除
- 删除临时package
- 删除那些没有对应package的shared uid
3.3 BOOT_PROGRESS_PMS_DATA_SCAN_START阶段
if (!mOnlyCore) {// 处理非系统应用
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
// 扫描:/data/app目录,保存到mPackages中
scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
// 步骤2:扫描/data/app-private目录,收集目录中文件信息
scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
| PackageParser.PARSE_FORWARD_LOCK,
scanFlags | SCAN_REQUIRE_KNOWN, 0);
...
// 移除通过OTA删除的更新系统应用程序的禁用package设置
// 如果更新不再存在,则完全删除该应用。否则,撤消其系统权限
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
// 从mSettings.mDisabledSysPackages变量中移除去此应用
mSettings.removeDisabledSystemPackageLPw(deletedAppName);
final String msg;
if (deletedPkg == null) {
// 用户目录中也没有升级包,则肯定是残留的应用信息,则把它的数据目录删除掉
msg = "Updated system package " + deletedAppName
+ " no longer exists; removing its data";
} else {
msg = "Updated system package + " + deletedAppName
+ " no longer exists; revoking system privileges";
// 如果在用户空间找到了文件,则说明系统目录下的文件可能被删除了
// 因此把应用的系统属性去掉,以普通应用的方式运行
final PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
}
// 报告系统发生了不一致的情况
logCriticalInfo(Log.WARN, msg);
}
// 现在来处理mExpectingBetter列表,这个列表的应用是带有升级包的系统的应用,
// 前面把他们从mPackages列表中清除了并放到mExpectingBetter列表
// 最后也对他们进行扫描处理,但不会放到mPackages中
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;
// 确保应用位于下面4个系统应用目录,如果不在,不需要处理
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;
}
// 现在把这个apk标示为系统应用,从mSettings.mDisabledSysPackages中删除,
// 因为在scanDirLI->scanPackageLI中会执行mSettings.disableSystemPackageLPw
// 所以此时包名的标签是只有<update-package>,执行到这步之后变成<package>标签,
// 在下面的scanPackageLI中又会添加一个<update-package>标签的
mSettings.enableSystemPackageLPw(packageName);
try {
// 重新扫描一下这个文件,会添加一个<update-package>标签
scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse original system package: "
+ e.getMessage());
}
}
}
// 最后处理子安装包,确保子安装包被整包替换或被禁用
decompressSystemApplications(stubSystemApps, scanFlags);
final int cachedNonSystemApps = PackageParser.sCachedPackageReadCount.get()
- cachedSystemApps;
final long dataScanTime = SystemClock.uptimeMillis() - systemScanTime - startTime;
final int dataPackagesCount = mPackages.size() - systemPackagesCount;
if (mIsUpgrade && dataPackagesCount > 0) {
MetricsLogger.histogram(null, "ota_package_manager_data_app_avg_scan_time",
((int) dataScanTime) / dataPackagesCount);
}
}
// 清空目录
mExpectingBetter.clear();
// 获取storage manager包名
mStorageManagerPackage = getStorageManagerPackageName();
// 解析受保护action过滤,仅setupwizard拥有最高优先级处理这个过滤
mSetupWizardPackage = getSetupWizardPackageName();
if (mProtectedFilters.size() > 0) {
if (DEBUG_FILTERS && mSetupWizardPackage == null) {
Slog.i(TAG, "No setup wizard;"
+ " All protected intents capped to priority 0");
}
for (ActivityIntentInfo filter : mProtectedFilters) {
if (filter.activity.info.packageName.equals(mSetupWizardPackage)) {
// skip setup wizard; allow it to keep the high priority filter
continue;
}
filter.setPriority(0);
}
}
mDeferProtectedFilters = false;
mProtectedFilters.clear();
// 更新所有应用的动态库路径
updateAllSharedLibrariesLPw(null);
for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
// NOTE: We ignore potential failures here during a system scan (like
// the rest of the commands above) because there's precious little we
// can do about it. A settings error is reported, though.
adjustCpuAbisForSharedUserLPw(setting.packages, null /*scannedPackage*/);
}
// 更新上一次使用时间
mPackageUsage.read(mPackages);
mCompilerStats.read();
主要工作有:对于不仅仅解析核心应用的情况下,还处理data目录的应用信息,及时更新,去除不必要的数据。
3.4 BOOT_PROGRESS_PMS_SCAN_END阶段
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());
Slog.i(TAG, "Time to scan packages: "
+ ((SystemClock.uptimeMillis()-startTime)/1000f)
+ " seconds");
// 如果平台的SDK版本和上次启动时候发生了变化,可能permission的定义也发生了变化,因此需要重新赋予应用权限
int updateFlags = UPDATE_PERMISSIONS_ALL;
if (ver.sdkVersion != mSdkVersion) {
Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
+ mSdkVersion + "; regranting permissions for internal storage");
updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
}
updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
ver.sdkVersion = mSdkVersion;
// 如果这是第一次启动或来自Android M之前的版本的升级,并且它是正常启动,
// 那需要在所有已定义的用户中初始化默认的首选应用程序
if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
for (UserInfo user : sUserManager.getUsers(true)) {
mSettings.applyDefaultPreferredAppsLPw(this, user.id);
applyFactoryDefaultBrowserLPw(user.id);
primeDomainVerificationsLPw(user.id);
}
}
// 在启动期间确实为系统用户准备存储,因为像SettingsProvider和SystemUI这样的核心系统应用程序无法等待用户启动
final int storageFlags;
if (StorageManager.isFileEncryptedNativeOrEmulated()) {
storageFlags = StorageManager.FLAG_STORAGE_DE;
} else {
storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
}
List<String> deferPackages = reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL,
UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
true /* onlyCoreApps */);
mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> {
TimingsTraceLog traceLog = new TimingsTraceLog("SystemServerTimingAsync",
Trace.TRACE_TAG_PACKAGE_MANAGER);
traceLog.traceBegin("AppDataFixup");
try {
mInstaller.fixupAppData(StorageManager.UUID_PRIVATE_INTERNAL,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
} catch (InstallerException e) {
Slog.w(TAG, "Trouble fixing GIDs", e);
}
traceLog.traceEnd();
traceLog.traceBegin("AppDataPrepare");
if (deferPackages == null || deferPackages.isEmpty()) {
return;
}
int count = 0;
for (String pkgName : deferPackages) {
PackageParser.Package pkg = null;
synchronized (mPackages) {
PackageSetting ps = mSettings.getPackageLPr(pkgName);
if (ps != null && ps.getInstalled(UserHandle.USER_SYSTEM)) {
pkg = ps.pkg;
}
}
if (pkg != null) {
synchronized (mInstallLock) {
prepareAppDataAndMigrateLIF(pkg, UserHandle.USER_SYSTEM, storageFlags,
true /* maybeMigrateAppData */);
}
count++;
}
}
traceLog.traceEnd();
Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages");
}, "prepareAppData");
if(mIsUpgrade){
SystemProperties.set("persist.sys.update", "1");
}else{
System.out.println("PM not setupdate flag");
}
// 如果是在OTA之后首次启动,并且正常启动,那需要清除代码缓存目录,但不清除应用程序配置文件
if (mIsUpgrade && !onlyCore) {
Slog.i(TAG, "Build fingerprint changed; clearing code caches");
for (int i = 0; i < mSettings.mPackages.size(); i++) {
final PackageSetting ps = mSettings.mPackages.valueAt(i);
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
// No apps are running this early, so no need to freeze
clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
| Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
}
ver.fingerprint = Build.FINGERPRINT;
}
// 检查默认浏览器,没有则设置
checkDefaultBrowser();
// clear only after permissions and other defaults have been updated
mExistingSystemPackages.clear();
mPromoteSystemApps = false;
// All the changes are done during package scanning.
ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;
// can downgrade to reader
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings");
// 保存配置,将信息写到package.xml、package.lsit及pacakge-stopped.xml文件中
mSettings.writeLPr();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
主要工作:
- sdk版本变更,更新权限;
- OTA升级后首次启动,清除不必要的缓存数据;
- 权限等默认项更新完后,清理相关数据;
- 更新package.xml、package.lsit及pacakge-stopped.xml文件
3.5 BOOT_PROGRESS_PMS_READY阶段
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
...
// 创建PackageInstallerService
mInstallerService = new PackageInstallerService(context, this);
...
// 读取并更新dex文件的用法
// 在PM init结束时执行此操作,以便所有程序包都已协调其数据目录
// 此时知道了包的代码路径,因此可以验证磁盘文件并构建内部缓存
// 使用文件预计很小,因此与其他活动(例如包扫描)相比,加载和验证它应该花费相当小的时间
final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
for (int userId : currentUserIds) {
userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList());
}
// 执行dexopt操作生成.odex后缀文件
mDexManager.load(userPackages);
if (mIsUpgrade) {
MetricsLogger.histogram(null, "ota_package_manager_init_time",
(int) (SystemClock.uptimeMillis() - startTime));
}
} // synchronized (mPackages)
} // synchronized (mInstallLock)
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "GC");
// 启动内存垃圾回收
Runtime.getRuntime().gc();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "loadFallbacks");
FallbackCategoryProvider.loadFallbacks();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
mInstaller.setWarnIfHeld(mPackages);
// 创建并添加PackageManagerInternalImpl服务到ServiceManager
LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
主要工作有:
- 创建PackageInstallerService对象
- GC回收内存
3.6 小节总结
目前为止已分析完PMS构造方法,一共有5个阶段,总结如下:
-
PMS_START
-
创建Settings对象
-
用系统属性来设置DisplayMetrics对象, 保存分辨率等相关信息
-
获取系统配置信息,如全局的groupId、系统权限和可用的feature
-
创建名为“PackageManager”的handler线程,负责apk的安装、卸载
-
创建各种目录,如/data/app、/data/app-lib、/data/app-asec、/data/app-private、/data/app-regional
-
创建用户管理服务,管理多用户
-
从/etc/permissions目录下面读取获取系统中定义的permissions
-
通过SystemConfig得到系统中的共享库列表
-
读取安装相关SELinux策略
-
读取文件package.xml等文件内容,解析后插到mSettings的mPackages等变量中
-
-
PMS_SYSTEM_SCAN_START
- 从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH
- 扫描/vendor/overlay目录下的package
- 扫描/system/framework目录下的package
- 扫描/system/priv-app目录下的系统package
- 扫描/system/app目录下的普通package
- 扫描/vendor/app目录下的vendor供应商package
- 扫描/oem/app目录下的oem制造商的package
- 删除不再存在的系统package
- 查找那些安装不完整的package,并将其删除
- 删除临时package
- 删除那些没有对应package的shared uid
-
PMS_DATA_SCAN_START
对于不仅仅解析核心应用的情况下,还处理data目录的应用信息,及时更新,去除不必要的数据
-
PMS_SCAN_END
- sdk版本变更,更新权限;
- OTA升级后首次启动,清除不必要的缓存数据;
- 权限等默认项更新完后,清理相关数据;
- 更新package.xml、package.lsit及pacakge-stopped.xml文件
-
PMS_READY
- 创建PackageInstallerService对象
- GC回收内存
4. PMS启动流程的其他操作
分析完PMS的构造方法后,根据小节2可知,在startOtherServices
方法中会调用以下几个方法继续PMS的操作
- updatePackagesIfNeeded
- performFstrimIfNeeded
- systemReady
- waitForAppDataPrepared
接下来分析上述的四个方法。
4.1 updatePackagesIfNeeded
@Override
public void updatePackagesIfNeeded() {
enforceSystemOrRoot("Only the system can request package update");
// 判断是否是FOTA升级
boolean causeUpgrade = isUpgrade();
// 判断是否是第一次开机或者恢复出厂设置或者从Android pre-N升级到O
// 从pre-N升级时,我们需要像第一次启动一样处理包提取,因为没有可用的分析数据
boolean causeFirstBoot = isFirstBoot() || mIsPreNUpgrade;
// 判断是否有清除过Dalvik虚拟机的Cache
boolean causePrunedCache = VMRuntime.didPruneDalvikCache();
// 如果不存在上面三种情况,则直接返回,不需要执行更新Package
if (!causeUpgrade && !causeFirstBoot && !causePrunedCache) {
return;
}
List<PackageParser.Package> pkgs;
synchronized (mPackages) {
// 这里会按照Package的重要程度来给他们分配优先级
// core app优先级最高,系统app次之,接着是其他app使用的app,最后则是最近未被使用和剩余的app
pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);
}
final long startTime = System.nanoTime();
// 这里最后会调用到mInstaller.dexopt()方法,mInstaller会和Installd进行通信完成Dex优化升级
final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */,
getCompilerFilterForReason(causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT),
false /* bootComplete */);
final int elapsedTimeSeconds =
(int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime);
MetricsLogger.histogram(mContext, "opt_dialog_num_dexopted", stats[0]);
MetricsLogger.histogram(mContext, "opt_dialog_num_skipped", stats[1]);
MetricsLogger.histogram(mContext, "opt_dialog_num_failed", stats[2]);
MetricsLogger.histogram(mContext, "opt_dialog_num_total", getOptimizablePackages().size());
MetricsLogger.histogram(mContext, "opt_dialog_time_s", elapsedTimeSeconds);
}
上面的代码首先判断是否需要对Package进行更新,如果需要更新的话会首先按照Package的重要程度给其赋予一个优先级, 更新packages的优先级:core app >system app > other app ,然后调用performDexOptUpgrade完成dex优化升级。
updatePackagesIfNeeded
方法的调用栈如下:
4.2 performFstrimIfNeeded
@Override
public void performFstrimIfNeeded() {
// 只有system或是root用户才有权限请求fstrim
enforceSystemOrRoot("Only the system can request fstrim");
// Before everything else, see whether we need to fstrim.
try {
// 获取StorageManager对象
IStorageManager sm = PackageHelper.getStorageManager();
if (sm != null) {
boolean doTrim = false;
// 获取执行FTRIM间隔,默认是3天,可以通过setting provider更改这个时间
final long interval = android.provider.Settings.Global.getLong(
mContext.getContentResolver(),
android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,
DEFAULT_MANDATORY_FSTRIM_INTERVAL);
if (interval > 0) {
final long timeSinceLast = System.currentTimeMillis() - sm.lastMaintenance();
// 上一次执行strim到现在超过三天,这需要执行FTRIM
if (timeSinceLast > interval) {
doTrim = true;
Slog.w(TAG, "No disk maintenance in " + timeSinceLast
+ "; running immediately");
}
}
if (doTrim) {
final boolean dexOptDialogShown;
synchronized (mPackages) {
dexOptDialogShown = mDexOptDialogShown;
}
// 如果不是第一次启动,显示一个提示框
if (!isFirstBoot() && dexOptDialogShown) {
try {
ActivityManager.getService().showBootMessage(
mContext.getResources().getString(
R.string.android_upgrading_fstrim), true);
} catch (RemoteException e) {
}
}
// 发送消息H_FSTRIM给handler,然后再向vold发送fstrim命令
sm.runMaintenance();
}
} else {
Slog.e(TAG, "storageManager service unavailable!");
}
} catch (RemoteException e) {
// Can't happen; StorageManagerService is local
}
}
上面主要是执行磁盘清理工作,释放磁盘空间。 磁盘维护最终调用的是vold
进程的 fstrim
进行清理操作。
4.3 systemReady
@Override
public void systemReady() {
enforceSystemOrRoot("Only the system can claim the system is ready");
mSystemReady = true;
final ContentResolver resolver = mContext.getContentResolver();
// 注册一个监听
ContentObserver co = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
mEphemeralAppsDisabled =
(Global.getInt(resolver, Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0) ||
(Secure.getInt(resolver, Secure.INSTANT_APPS_ENABLED, 1) == 0);
}
};
mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
.getUriFor(Global.ENABLE_EPHEMERAL_FEATURE),
false, co, UserHandle.USER_SYSTEM);
mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
.getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, UserHandle.USER_SYSTEM);
co.onChange(true);
// 禁用运营商的app
CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), this,
mContext.getContentResolver(), UserHandle.USER_SYSTEM);
// 系统处于ready时,读取系统的兼容性设置
boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt(
mContext.getContentResolver(),
android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1;
// 设置PackageParser是否启用兼容性设置
PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
if (DEBUG_SETTINGS) {
Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
}
int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;
synchronized (mPackages) {
// 检查Preferred Activity是否有更新
ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
removed.clear();
for (PreferredActivity pa : pir.filterSet()) {
if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
removed.add(pa);
}
}
if (removed.size() > 0) {
for (int r=0; r<removed.size(); r++) {
PreferredActivity pa = removed.get(r);
Slog.w(TAG, "Removing dangling preferred activity: "
+ pa.mPref.mComponent);
pir.removeFilter(pa);
}
mSettings.writePackageRestrictionsLPr(
mSettings.mPreferredActivities.keyAt(i));
}
}
for (int userId : UserManagerService.getInstance().getUserIds()) {
if (!mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) {
grantPermissionsUserIds = ArrayUtils.appendInt(
grantPermissionsUserIds, userId);
}
}
}
// 多用户服务
sUserManager.systemReady();
// If we upgraded grant all default permissions before kicking off.
// 升级所有以获取到的默认权限
for (int userId : grantPermissionsUserIds) {
mDefaultPermissionPolicy.grantDefaultPermissions(userId);
}
// 此处调取前面获取默认权限失败时抛出的异常
if (grantPermissionsUserIds == EMPTY_INT_ARRAY) {
mDefaultPermissionPolicy.scheduleReadDefaultPermissionExceptions();
}
// Kick off any messages waiting for system ready
// 处理所有等待系统就绪的消息
if (mPostSystemReadyMessages != null) {
for (Message msg : mPostSystemReadyMessages) {
msg.sendToTarget();
}
mPostSystemReadyMessages = null;
}
// Watch for external volumes that come and go over time
// 观察外部存储设备
final StorageManager storage = mContext.getSystemService(StorageManager.class);
storage.registerListener(mStorageListener);
mInstallerService.systemReady();
mPackageDexOptimizer.systemReady();
// Storage相关处理
StorageManagerInternal StorageManagerInternal = LocalServices.getService(
StorageManagerInternal.class);
StorageManagerInternal.addExternalStoragePolicy(
new StorageManagerInternal.ExternalStorageMountPolicy() {
@Override
public int getMountMode(int uid, String packageName) {
if (Process.isIsolated(uid)) {
return Zygote.MOUNT_EXTERNAL_NONE;
}
if (checkUidPermission(WRITE_MEDIA_STORAGE, uid) == PERMISSION_GRANTED) {
return Zygote.MOUNT_EXTERNAL_DEFAULT;
}
if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
return Zygote.MOUNT_EXTERNAL_DEFAULT;
}
if (checkUidPermission(WRITE_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
return Zygote.MOUNT_EXTERNAL_READ;
}
return Zygote.MOUNT_EXTERNAL_WRITE;
}
@Override
public boolean hasExternalStorage(int uid, String packageName) {
return true;
}
});
// Now that we're mostly running, clean up stale users and apps
// 清除过期的userid和app
sUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
if (mPrivappPermissionsViolations != null) {
Slog.wtf(TAG,"Signature|privileged permissions not in "
+ "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
mPrivappPermissionsViolations = null;
}
}
这一部分主要是当PMS准备就绪时,更新一些Package的信息、默认权限的获取以及通知在等待PMS就绪的主件。
4.4 waitForAppDataPrepared
public void waitForAppDataPrepared() {
if (mPrepareAppDataFuture == null) {
return;
}
ConcurrentUtils.waitForFutureNoInterrupt(mPrepareAppDataFuture, "wait for prepareAppData");
mPrepareAppDataFuture = null;
}
该方法主要是等待所有packages准备就绪,waitForFutureNoInterrupt
等待mPrepareAppDataFuture
线程返回。mPrepareAppDataFuture
是在BOOT_PROGRESS_PMS_SCAN_END
阶段开启的线程:
mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> {
TimingsTraceLog traceLog = new TimingsTraceLog("SystemServerTimingAsync",
Trace.TRACE_TAG_PACKAGE_MANAGER);
traceLog.traceBegin("AppDataFixup");
try {
mInstaller.fixupAppData(StorageManager.UUID_PRIVATE_INTERNAL,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
} catch (InstallerException e) {
Slog.w(TAG, "Trouble fixing GIDs", e);
}
traceLog.traceEnd();
traceLog.traceBegin("AppDataPrepare");
if (deferPackages == null || deferPackages.isEmpty()) {
return;
}
int count = 0;
for (String pkgName : deferPackages) {
PackageParser.Package pkg = null;
synchronized (mPackages) {
PackageSetting ps = mSettings.getPackageLPr(pkgName);
if (ps != null && ps.getInstalled(UserHandle.USER_SYSTEM)) {
pkg = ps.pkg;
}
}
if (pkg != null) {
synchronized (mInstallLock) {
prepareAppDataAndMigrateLIF(pkg, UserHandle.USER_SYSTEM, storageFlags,
true /* maybeMigrateAppData */);
}
count++;
}
}
traceLog.traceEnd();
Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages");
}, "prepareAppData");
5. 总结
本篇主要梳理了PMS的启动流程,工作简单总结如下:
-
启动Installer服务
-
构建PMS对象,其中在PMS构造方法中主要做了以下内容:
- 创建了 Java 层 Installer 和 C 层 installd 之间的 socket 连接
- 扫描各目录下 apk文件完成安装(建立各安装包的配置结构信息,并添加到全局列表中进行管理)
- 创建了 PackageHandler 对象并建立消息循环,接收外部的安装请求
- 解析权限,建立底层 Linux Kernel 的用户机制和虚拟机层权限机制之间的映射
-
根据下面的情况需要Dex优化
- FOTA升级
- 第一次开机
- 恢复出厂设置
- 从Android pre-N升级到O
- 清除过Dalvik虚拟机的Cache
-
执行磁盘清理工作,释放磁盘空间
-
当PMS准备就绪时,更新一些Package的信息、默认权限的获取以及通知在等待PMS就绪的主件
-
等待所有packages准备就绪