Android|Android 10.0 PackageManagerService流程分析

概述 PackageManagerService是android系统核心服务之一,在Android中非常重要,主要负责的功能如下:

  • 解析AndroidManifest.xml 主要包括AndoridManifest中节点的信息。
  • 扫描本地文件,主要针对apk,主要是系统应用,本地安装应用等。
  • 管理本地apk,主要包括安装和删除等。
启动过程 PKMS服务由SystemServer进行启动,在SystemServer中startBootstrapServices()启动PKMS服务,在调用startOtherServices进行dex优化,磁盘管理等功能,并让PKMS进入systemReady状态。
SystemServer.java#startBootstrapServices() startBootstrapServices首先启动Installer服务,也就是安装器,随后判断当前的设备是否处于加密状态,如果是则只解析核心应用,接着调用PKMS的静态方法main来创建pkms对象
private void startBootstrapServices() { ... // Wait for installd to finish starting up so that it has a chance to // create critical directories such as /data/user with the appropriate // permissions.We need this to complete before we initialize other services. //(1)启动Installer //阻塞等待installd完成启动,以便有机会创建具有适当权限的关键目录,如/data/user。 //我们需要在初始化其他服务之前完成此任务。 Installer installer = mSystemServiceManager.startService(Installer.class); mActivityManagerService.setInstaller(installer); ...// Only run "core" apps if we're encrypting the device. //(2)获取设别是否加密(手机设置密码),如果设备加密了,则只解析"core"应用,mOnlyCore = true,后面会频繁使用该变量进行条件判断 String cryptState = VoldProperties.decrypt().orElse(""); 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; }//(3)调用main方法初始化PackageManagerService。 mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); //PKMS是否是第一次启动 mFirstBoot = mPackageManagerService.isFirstBoot(); //(4)如果设备没有加密,操作它。管理A/B OTA dexopting。 if (!mOnlyCore) { boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt", false); OtaDexoptService.main(mSystemContext, mPackageManagerService); } ... }

startOtherServices
  • 执行updatePackagesIfNeeded,完成dex优化
  • 执行performFstrimIfNeeded 完成磁盘维护
  • 调用systemReady 准备就绪
private void startOtherServices() { ... if (!mOnlyCore) { ... //(5)如果设备没有加密,执行performDexOptUpgrade,完成dex优化; mPackageManagerService.updatePackagesIfNeeded(); } ... //(6) 最终执行performFstrim,完成磁盘维护 mPackageManagerService.performFstrimIfNeeded(); ... //(7)PKMS准备就绪 mPackageManagerService.systemReady(); ... }

PackageManagerService.java#main() main函数主要工作:
  • 检查Package编译相关系统属性
  • 调用PackageManagerService构造方法
  • 启动部分应用服务于多用户场景
  • 往ServiceManager中注册packagepackage_native
public static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { // (1)检查Package编译相关系统属性 PackageManagerServiceCompilerMapping.checkProperties(); //(2)调用PackageManagerService构造方法 PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore); //(3)启用部分应用服务于多用户场景 m.enableSystemUserPackages(); //(4)往ServiceManager中注册”package”和”package_native”。 ServiceManager.addService("package", m); final PackageManagerNative pmn = m.new PackageManagerNative(); ServiceManager.addService("package_native", pmn); return m; }

PKMS初始化时的核心部分为PackageManagerService()构造函数的内容,我们接下来就来分析该流程。
PKMS构造函数分析 主要有两个重要的锁(mInstallLock,mPackages)和五个阶段构成。
mPackages:用来解析内存中所有apk的package信息以及相关状态。
五个阶段:
  • 阶段1:BOOT_PROGRESS_PMS_START
  • 阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
  • 阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START
  • 阶段4:BOOT_PROGRESS_PMS_SCAN_END
  • 阶段5:BOOT_PROGRESS_PMS_READY
    PKMS服务也是通过binder进行通信,IPackageManager.aidl由工具转换后自动生成binder的服务端IPackageManager.Stub和客户端IPackageManager.Stub.Proxy。
  • Binder服务端:PackageManagerService继承于IPackageManager.Stub
  • Binder客户端:ApplicationPackageManager的成员变量mPM继承于IPackageManager.Stub.Proxy; 本身APM继承于PackageManager对象。
PackageManagerService.java IPacakgeManager.Stub 是IPackageManager.aidl自动生成的,正好也说明PKMS是service端,通过Binder交互
public class PackageManagerService extends IPackageManager.Stub implements PackageSender

PackageManagerService()构造函数
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { ... //阶段1:BOOT_PROGRESS_PMS_START EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, SystemClock.uptimeMillis()); //阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START, startTime); ...//阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START if (!mOnlyCore) { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START, SystemClock.uptimeMillis()); } ... //阶段4:BOOT_PROGRESS_PMS_SCAN_END EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END, SystemClock.uptimeMillis()); ... //阶段5:BOOT_PROGRESS_PMS_READY EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis()); }

阶段1:BOOT_PROGRESS_PMS_START 主要工作:
  • 构造DisplayMetrics,保存分辨率等相关信息
  • 创建Installer对象 与InstallId交互
  • 创建mPermissionManager对象,进行权限管理
  • 构造Settings类,保存安装包信息,清除路径不存在的孤立应用,主要涉及/data/system目录下的packages.xml,package-backup.xml,packages.list,packages-stopped.xml,packages-stopped-backup.xml等文件。
  • 构造PackageDexOptimizer及DexManager类,处理dex优化;
  • 创建SystemConfig实例,获取系统配置信息,配置共享lib库
  • 创建PackageManager的handler线程,循环处理外部安装相关消息。
public PackageManagerService(...) { LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, SystemClock.uptimeMillis()); mContext = context; mFactoryTest = factoryTest; // 一般为false,即非工厂生产模式 mOnlyCore = onlyCore; //标记是否只加载核心服务 mMetrics = new DisplayMetrics(); // 分辨率配置 mInstaller = installer; //保存installer对象 // Create sub-components that provide services / data. Order here is important. //创建提供服务/数据的子组件。这里的顺序很重要,使用到了两个重要的同步锁:mInstallLock、mPackages synchronized (mInstallLock) { synchronized (mPackages) { // Expose private service for system components to use. // 公开系统组件使用的私有服务 // 本地服务 LocalServices.addService( PackageManagerInternal.class, new PackageManagerInternalImpl()); // 多用户管理服务 sUserManager = new UserManagerService(context, this, new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages); mComponentResolver = new ComponentResolver(sUserManager, LocalServices.getService(PackageManagerInternal.class), mPackages); // 权限管理服务 mPermissionManager = PermissionManagerService.create(context, mPackages /*externalLock*/); mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy(); //创建Settings对象 mSettings = new Settings(Environment.getDataDirectory(), mPermissionManager.getPermissionSettings(), mPackages); } }// 添加system, phone, log, nfc, bluetooth, shell,se,networkstack 这8种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); mSettings.addSharedUserLPw("android.uid.se", SE_UID, ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); mSettings.addSharedUserLPw("android.uid.networkstack", NETWORKSTACK_UID, ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); ... // DexOpt优化 mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context, "*dexopt*"); mDexManager = new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock); // ART虚拟机管理服务 mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock); mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper()); mViewCompiler = new ViewCompiler(mInstallLock, mInstaller); // 权限变化监听器 mOnPermissionChangeListeners = new OnPermissionChangeListeners( FgThread.get().getLooper()); mProtectedPackages = new ProtectedPackages(mContext); mApexManager = new ApexManager(context); // 获取默认分辨率 getDefaultDisplayMetrics(context, mMetrics); //拿到SystemConfig()的对象,其中会调用SystemConfig的readPermissions()完成权限的读取 SystemConfig systemConfig = SystemConfig.getInstance(); synchronized (mInstallLock) { // writer synchronized (mPackages) { // 启动"PackageManager"线程,负责apk的安装、卸载 mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/); mHandlerThread.start(); // 应用handler mHandler = new PackageHandler(mHandlerThread.getLooper()); // 进程记录handler mProcessLoggingHandler = new ProcessLoggingHandler(); // Watchdog监听ServiceThread是否超时:10分钟 Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT); // Instant应用注册 mInstantAppRegistry = new InstantAppRegistry(this); // 共享lib库配置 ArrayMap libConfig = systemConfig.getSharedLibraries(); final int builtInLibCount = libConfig.size(); for (int i = 0; i < builtInLibCount; i++) { String name = libConfig.keyAt(i); SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i); addBuiltInSharedLibraryLocked(entry.filename, name); } ... // 读取安装相关SELinux策略 SELinuxMMAC.readInstallPolicy(); // 返回栈加载 FallbackCategoryProvider.loadFallbacks(); //读取并解析/data/system下的XML文件 mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false)); // 清理代码路径不存在的孤立软件包 final int packageSettingCount = mSettings.mPackages.size(); 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); } } // 如果不是首次启动,也不是CORE应用,则拷贝预编译的DEX文件 if (!mOnlyCore && mFirstBoot) { requestCopyPreoptedFiles(); } ... } // synchronized (mPackages) } }

readLPW()会扫描下面5个文件
  1. /data/system/packages.xml
  2. /data/system/packages-backup.xml
  3. /data/system/packages.list
  4. /data/system/packages-stopped.xml
  5. /data/system/packages-stopped-backup.xml
文件共分为三组,简单的作用描述如下:
  • packages.xml:PKMS 扫描完目标文件夹后会创建该文件。当系统进行程序安装、卸载和更新等操作时,均会更新该文件。该文件保存了系统中与 package 相关的一些信息。
  • packages.list:描述系统中存在的所有非系统自带的 APK 的信息。当这些程序有变动时,PKMS 就会更新该文件。
  • packages-stopped.xml:从系统自带的设置程序中进入应用程序页面,然后在选择强制停止(ForceStop)某个应用时,系统会将该应用的相关信息记录到此文件中。也就是该文件保存系统中被用户强制停止的 Package 的信息。
这些目录的指向,都在Settings中的构造函数完成, 如下所示,得到目录后调用readLPw()进行扫描
Settings(File dataDir, PermissionSettings permission, Object lock) { mLock = lock; mPermissions = permission; mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock); mSystemDir = new File(dataDir, "system"); //mSystemDir指向目录"/data/system" mSystemDir.mkdirs(); //创建 "/data/system" //设置权限 FileUtils.setPermissions(mSystemDir.toString(), FileUtils.S_IRWXU|FileUtils.S_IRWXG |FileUtils.S_IROTH|FileUtils.S_IXOTH, -1, -1); //(1)指向目录"/data/system/packages.xml" mSettingsFilename = new File(mSystemDir, "packages.xml"); //(2)指向目录"/data/system/packages-backup.xml" mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml"); //(3)指向目录"/data/system/packages.list" mPackageListFilename = new File(mSystemDir, "packages.list"); FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID); //(4)指向目录"/data/system/packages-stopped.xml" mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml"); //(5)指向目录"/data/system/packages-stopped-backup.xml" mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml"); }

解析上面这几个xml的文件内容,建立对应的数据结构
[Settings.java] boolean readLPw(@NonNull List users) { FileInputStream str = null; ... if (str == null) { str = new FileInputStream(mSettingsFilename); } //解析"/data/system/packages.xml" XmlPullParser parser = Xml.newPullParser(); parser.setInput(str, StandardCharsets.UTF_8.name()); int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { ; } int outerDepth = parser.getDepth(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } //根据XML的各个节点进行各种操作,例如读取权限、shared-user等 String tagName = parser.getName(); if (tagName.equals("package")) { readPackageLPw(parser); } else if (tagName.equals("permissions")) { mPermissions.readPermissions(parser); } else if (tagName.equals("permission-trees")) { mPermissions.readPermissionTrees(parser); } else if (tagName.equals("shared-user")) { readSharedUserLPw(parser); }... } str.close(); ... return true; }

创建SharedUserSetting对象并添加到Settings的成员变量mSharedUsers中,在Android系统中,多个package通过设置shareUserid属性可以运行在同一进程,共享同一个UID。
mSettings.addSharedUserLPw("android.uid.system", //字符串 Process.SYSTEM_UID, //系统进程使用的用户id,值为1000 ApplicationInfo.FLAG_SYSTEM, //标志系统 Package ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); //特权系统应用 SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) { //mSharedUsers 是一个 HashMap,key 为字符串,值为 SharedUserSetting 对象 SharedUserSetting s = mSharedUsers.get(name); if (s != null) { if (s.userId == uid) { return s; } PackageManagerService.reportSettingsProblem(Log.ERROR, "Adding duplicate shared user, keeping first: " + name); return null; } //创建一个新的 SharedUserSetting 对象,并设置的 userId 为 uid s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags); s.userId = uid; if (registerExistingAppIdLPw(uid, s, name)) { mSharedUsers.put(name, s); //将name与s键值对添加到mSharedUsers中保存 return s; } return null; }

阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START 主要工作:
  • 从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH;
  • 对于旧版本升级的情况,将安装时获取权限变更为运行时申请权限
  • 扫描system/vendor/product/odem/oem 等目录的priv-app ,app ,overlay包
  • 清除安装时临时文件以及其他不必要的信息。
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { synchronized (mInstallLock) { synchronized (mPackages) { // 记录扫描开始时间 long startTime = SystemClock.uptimeMillis(); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START, startTime); //获取环境变量,init.rc final String bootClassPath = System.getenv("BOOTCLASSPATH"); final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH"); ... // 获取system/framework目录 File frameworkDir = new File(Environment.getRootDirectory(), "framework"); // 获取内部版本 final VersionInfo ver = mSettings.getInternalVersion(); // 判断fingerprint是否有更新 mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint); ... // 对于Android M之前版本升级上来的情况,需将系统应用程序权限从安装升级到运行时 mPromoteSystemApps = mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1; // 对于Android N之前版本升级上来的情况,需像首次启动一样处理package mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N; mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1; mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q; // 在扫描之前保存预先存在的系统package的名称,不希望自动为新系统应用授予运行时权限 if (mPromoteSystemApps) { Iterator pkgSettingIter = mSettings.mPackages.values().iterator(); while (pkgSettingIter.hasNext()) { PackageSetting ps = pkgSettingIter.next(); if (isSystemApp(ps)) { mExistingSystemPackages.add(ps.name); } } } // 准备解析package的缓存 mCacheDir = preparePackageParserCache(); // 设置flag,而不在扫描安装时更改文件路径 int scanFlags = SCAN_BOOTING | SCAN_INITIAL; ... //扫描以下路径: /vendor/overlay、/product/overlay、/product_services/overlay、/odm/overlay、/oem/overlay、/system/framework /system/priv-app、/system/app、/vendor/priv-app、/vendor/app、/odm/priv-app、/odm/app、/oem/app、/oem/priv-app、 /product/priv-app、/product/app、/product_services/priv-app、/product_services/app、/product_services/priv-appscanDirTracedLI(new File(VENDOR_OVERLAY_DIR),...); scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),...); scanDirTracedLI(new File(PRODUCT_SERVICES_OVERLAY_DIR),...); scanDirTracedLI(new File(ODM_OVERLAY_DIR),...); scanDirTracedLI(new File(OEM_OVERLAY_DIR),...); ... final List possiblyDeletedUpdatedSystemApps = new ArrayList<>(); final List stubSystemApps = new ArrayList<>(); // 删掉不存在的package if (!mOnlyCore) { final Iterator pkgIterator = mPackages.values().iterator(); while (pkgIterator.hasNext()) { final PackageParser.Package pkg = pkgIterator.next(); if (pkg.isStub) { stubSystemApps.add(pkg.packageName); } } final Iterator psit = mSettings.mPackages.values().iterator(); while (psit.hasNext()) { PackageSetting ps = psit.next(); // 如果不是系统应用,则不被允许disable if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) { continue; }// 如果应用被扫描,则不允许被擦除 final PackageParser.Package scannedPkg = mPackages.get(ps.name); if (scannedPkg != null) { // 如果系统应用被扫描且存在disable应用列表中,则只能通过OTA升级添加 if (mSettings.isDisabledSystemPackageLPr(ps.name)) { ... removePackageLI(scannedPkg, true); mExpectingBetter.put(ps.name, ps.codePath); } continue; } ... } } // 删除临时文件 deleteTempPackageFiles(); // 删除没有关联应用的共享UID标识 mSettings.pruneSharedUsersLPw(); ... } ... } ... }

说明下:[system/app/与system/priv-app/的区别] 在system/priv-app目录主要是存放手机厂商定制的系统的系统级应用,比如phone app,settings app,systemui app等,这些应用需要系统及权限,而又不能被用户卸载掉。这个目录是在Android KitKat新增加的分区。在KitKat之前版本在系统分区的所有apks都可以使用系统权限,这个更改使手机厂商能够更好的控制捆绑软件对敏感权限的访问。手机厂商在定制一些系统软件的时候软件也会需要专门给priv-app添加selinux policy。当然应用需要获取系统权限还有其他的办法,在AndroidManifest.xml文件中添加 android:sharedUserId="android.uid.sysytem",同时给该apk添加系统签名,比如小米手机就需要给apk添加小米的系统权限。
阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START 主要工作:解析核心应用,处理data目录下的应用信息,更新,删除不必要的数据。
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { synchronized (mInstallLock) { synchronized (mPackages) { ... if (!mOnlyCore) { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START, SystemClock.uptimeMillis()); //扫描/data/app 目录 scanDirTracedLI(sAppInstallDir, 0, 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. // 移除通过OTA删除的更新系统应用程序的禁用package设置 // 如果更新不再存在,则完全删除该应用。否则,撤消其系统权限 for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) { final String packageName = possiblyDeletedUpdatedSystemApps.get(i); final PackageParser.Package pkg = mPackages.get(packageName); final String msg; // remove from the disabled system list; do this first so any future // scans of this package are performed without this state mSettings.removeDisabledSystemPackageLPw(packageName); ... }/*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. */ // 确保期望在userdata分区上显示的所有系统应用程序实际显示 // 如果从未出现过,需要回滚以恢复系统版本 for (int i = 0; i < mExpectingBetter.size(); i++) { final String packageName = mExpectingBetter.keyAt(i); if (!mPackages.containsKey(packageName)) { final File scanFile = mExpectingBetter.valueAt(i); ... mSettings.enableSystemPackageLPw(packageName); try { //扫描APK scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 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. // 解压缩并安装任何存根系统应用程序。必须最后执行此操作以确保替换或禁用所有存根 installSystemStubPackages(stubSystemApps, scanFlags); ... // 获取storage manager包名 mStorageManagerPackage = getStorageManagerPackageName(); // Resolve protected action filters. Only the setup wizard is allowed to // have a high priority filter for these actions. // 解决受保护的action过滤器。只允许setup wizard(开机向导)为这些action设置高优先级过滤器 mSetupWizardPackage = getSetupWizardPackageName(); ...// Now that we know all of the shared libraries, update all clients to have // the correct library paths. // 更新客户端以确保持有正确的共享库路径 updateAllSharedLibrariesLocked(null, Collections.unmodifiableMap(mPackages)); ... // 读取并更新要保留的package的上次使用时间 mPackageUsage.read(mPackages); mCompilerStats.read(); } } } }

阶段四:BOOT_PROGRESS_PMS_SCAN_END 主要工作:
  • sdk版本变更,更新权限
  • OTA升级后首次启动,清除不必要的缓存数据
  • 权限等默认更新后,清理相关数据
  • 更新package.xml
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { synchronized (mInstallLock) { synchronized (mPackages) { ... EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END, SystemClock.uptimeMillis()); // If the platform SDK has changed since the last time we booted, // we need to re-grant app permission to catch any new ones that // appear.This is really a hack, and means that apps can in some // cases get permissions that the user didn't initially explicitly // allow...it would be nice to have some better way to handle // this situation. // 如果自上次启动以来,平台SDK已改变,则需要重新授予应用程序权限以捕获出现的任何新权限 final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion); mPermissionManager.updateAllPermissions( StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, mPackages.values(), mPermissionCallback); ...// If this is the first boot or an update from pre-M, and it is a normal // boot, then we need to initialize the default preferred apps across // all defined users. // 如果这是第一次启动或来自Android M之前的版本的升级,并且它是正常启动,那需要在所有已定义的用户中初始化默认的首选应用程序 if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) { for (UserInfo user : sUserManager.getUsers(true)) { mSettings.applyDefaultPreferredAppsLPw(user.id); primeDomainVerificationsLPw(user.id); } }// Prepare storage for system user really early during boot, // since core system apps like SettingsProvider and SystemUI // can't wait for user to start // 在启动期间为系统用户准备存储,因为像SettingsProvider和SystemUI这样的核心系统应用程序无法等待用户启动 final int storageFlags; if (StorageManager.isFileEncryptedNativeOrEmulated()) { storageFlags = StorageManager.FLAG_STORAGE_DE; } else { storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; } ...// If this is first boot after an OTA, and a normal boot, then // we need to clear code cache directories. // Note that we do *not* clear the application profiles. These remain valid // across OTAs and are used to drive profile verification (post OTA) and // profile compilation (without waiting to collect a fresh set of profiles). // 如果是在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, FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); } } ver.fingerprint = Build.FINGERPRINT; }// Grandfather existing (installed before Q) non-system apps to hide // their icons in launcher. //安装Android-Q前的非系统应用程序在Launcher中隐藏他们的图标 if (!onlyCore && mIsPreQUpgrade) { Slog.i(TAG, "Whitelisting all existing apps to hide their icons"); int size = mSettings.mPackages.size(); for (int i = 0; i < size; i++) { final PackageSetting ps = mSettings.mPackages.valueAt(i); if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) { continue; } ps.disableComponentLPw(PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME, UserHandle.USER_SYSTEM); } } // 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 //降级去读取 mSettings.writeLPr(); } } }

阶段五:BOOT_PROGRESS_PMS_READY 主要工作有:
  • 创建PackageInstallerService对
  • GC回收内存
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { synchronized (mInstallLock) { synchronized (mPackages) { ... EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis()); ...// PermissionController hosts default permission granting and role management, so it's a critical part of the core system.//PermissionController 持有默认的权限授予和角色管理,所以这是核心系统的一个关键部分。 mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr(); ... updateInstantAppInstallerLocked(null); // Read and update the usage of dex files. // Do this at the end of PM init so that all the packages have their data directory reconciled. // At this point we know the code paths of the packages, so we can validate // the disk file and build the internal cache. // The usage file is expected to be small so loading and verifying it should take a fairly small time compare to the other activities (e.g. package scanning). // 阅读并更新dex文件的用法 // 在PM init结束时执行此操作,以便所有程序包都已协调其数据目录 // 此时知道了包的代码路径,因此可以验证磁盘文件并构建内部缓存 // 使用文件预计很小,因此与其他活动(例如包扫描)相比,加载和验证它应该花费相当小的时间 final Map userPackages = new HashMap<>(); for (int userId : userIds) { userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList()); } mDexManager.load(userPackages); if (mIsUpgrade) { MetricsLogger.histogram(null, "ota_package_manager_init_time", (int) (SystemClock.uptimeMillis() - startTime)); } } } ...// Now after opening every single application zip, make sure they are all flushed.Not really needed, but keeps things nice andtidy. // 打开应用之后,及时回收处理 Runtime.getRuntime().gc(); // The initial scanning above does many calls into installd while // holding the mPackages lock, but we're mostly interested in yelling // once we have a booted system. // 上面的初始扫描在持有mPackage锁的同时对installd进行了多次调用 mInstaller.setWarnIfHeld(mPackages); ... }

DEX优化 检查是否需要去更新Packages并进行dex优化,如果没有OTA升级,没有大版本升级,没有清除dalvik虚拟机缓存,可以去更新packages。最终调用的是Installer的dexopt进行优化
PKMS.java#updatePackagesIfNeeded() 更新packages的优先级:core app> system app > other app,调用performDexOptUpgrade()进行系统更新
public void updatePackagesIfNeeded() { //只有system或是root用户才有权限请求 package update enforceSystemOrRoot("Only the system can request package update"); //(1)判断有没有进行OTA升级,我们需要在OTA后重新提取。 boolean causeUpgrade = isDeviceUpgrading(); //(2)是否是第一次启动或是系统大版本升级 boolean causeFirstBoot = isFirstBoot() || mIsPreNUpgrade; // We need to re-extract after a pruned cache, as AoT-ed files will be out of date. //(3)判断是否有清除过dalvik虚拟机的缓存 boolean causePrunedCache = VMRuntime.didPruneDalvikCache(); //(4)如果上面的三个都没有,那么就不进行任何操作 if (!causeUpgrade && !causeFirstBoot && !causePrunedCache) { return; } List pkgs; synchronized (mPackages) { //(5)按照package的优先级进行排序,core app >system app > other app pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this); } final long startTime = System.nanoTime(); //记录开始时间//进行dex优化, final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */, causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT, false /* bootComplete */); ... }

PackageManagerService.java#performDexOptUpgrade() 判断是否需要对package进行更新,如果需要那么更新会按照优先级完成dex优化,最终调用Install的dexopt进行dex优化。
private int[] performDexOptUpgrade(List pkgs, boolean showDialog, final int compilationReason, boolean bootComplete) { ... //循环取出packages,进行优化 for (PackageParser.Package pkg : pkgs) { numberOfPackagesVisited++; boolean useProfileForDexopt = false; //第一次启动或是ota升级之后并且是系统应用才会进行odex if ((isFirstBoot() || isDeviceUpgrading()) && isSystemApp(pkg)) { ... } ... //最终是调用 mInstaller.dexopt 完成优化的,installd守护进程,installer安装器和Installd通信 int primaryDexOptStaus = performDexOptTraced(new DexoptOptions( pkg.packageName, pkgCompilationReason, dexoptFlags)); switch (primaryDexOptStaus) { case PackageDexOptimizer.DEX_OPT_PERFORMED: numberOfPackagesOptimized++; //odex优化完成的应用 break; case PackageDexOptimizer.DEX_OPT_SKIPPED: numberOfPackagesSkipped++; //跳过的应用 break; case PackageDexOptimizer.DEX_OPT_FAILED: numberOfPackagesFailed++; //失败的应用 break; default: Log.e(TAG, "Unexpected dexopt return code " + primaryDexOptStaus); break; } } return new int[] { numberOfPackagesOptimized, numberOfPackagesSkipped, numberOfPackagesFailed }; }

磁盘维护 磁盘维护最终调用的是vold进行的fstrim进行清理操作
PackageManagerService.java#performFstrimIfNeeded() 主要执行磁盘清理工作,释放磁盘空间
public void performFstrimIfNeeded() { //只有system或是root用户才有权限请求fstrim enforceSystemOrRoot("Only the system can request fstrim"); // Before everything else, see whether we need to fstrim. //在其他事情之前,看看我们是否需要fstrim try { //获取StorageManager对象 IStorageManager sm = PackageHelper.getStorageManager(); if (sm != null) { boolean doTrim = false; //获取执行FTRIM间隔,默认是3天,可以通过setting provider更改这个时间 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(); 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) { } } // 这里的sm是 StorageManagerService,发送消息H_FSTRIM给handler,然后再向vold发送fstrim命 sm.runMaintenance(); } } else { Slog.e(TAG, "storageManager service unavailable!"); } } catch (RemoteException e) { // Can't happen; StorageManagerService is local } }

PKMS准备就绪 PackageManagerService.java#systemReady() systemReady主要完成默认授权和更新package的信息,通知等待pms的一些组件。
public void systemReady() { //只有system或是root用户才有权限 声称system已经ready enforceSystemOrRoot("Only the system can claim the system is ready"); ContentObserver co = new ContentObserver(mHandler) { ... }; co.onChange(true); //注册一个监听 ... synchronized (mPackages) { ArrayList
removed = new ArrayList<>(); for (int i=0; i 0) { for (int r=0; r { updatePartnerAppInFota(); }).start(); }

【Android|Android 10.0 PackageManagerService流程分析】大概流程就是这样,完。

    推荐阅读