安卓PMS模块之启动及解析APK流程(3)

Posted by Vane's Blog on April 13, 2020

基于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的图标的流程概述如下:

  1. 手机开机之后,系统开始运行,启动了init进程
  2. init进程启动了Android系统的母进程-Zygote进程
  3. Zygote进程fork systemserver进程
  4. systemserver中启动PMS服务
  5. PMS中扫面特定目录下的应用程序apk,然后解析apk,将信息保存起来,并启动一些系统应用,如 桌面Launcher应用
  6. 启动桌面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服务的启动流程如下:

Installer-start

  1. 构造函数 Installer初始化 context 和 isolated(是否真正连接installd)成员变量
  2. 重写 onStart() 方法,基于 isolated 判断是否调用 connect() 进行连接
  3. connect() 通过 ServiceManager 获取 installd 服务并拿到服务的本地代理放到成员变量 mInstalld 中
  4. 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的构造方法,这部分的代码很长,简单概括如下:

  1. 创建了 Java 层 Installer 和 C 层 installd 之间的 socket 连接
  2. 扫描各目录下 apk文件完成安装(建立各安装包的配置结构信息,并添加到全局列表中进行管理)
  3. 创建了 PackageHandler 对象并建立消息循环,接收外部的安装请求
  4. 解析权限,建立底层 Linux Kernel 的用户机制和虚拟机层权限机制之间的映射

主要分为5个阶段:

  1. PMS_START
  2. PMS_SYSTEM_SCAN_START
  3. PMS_DATA_SCAN_START
  4. PMS_SCAN_END
  5. 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阶段概括为以下步骤:

  1. 创建Settings对象

  2. 用系统属性来设置DisplayMetrics对象, 保存分辨率等相关信息

  3. 获取系统配置信息,如全局的groupId、系统权限和可用的feature

  4. 创建名为“PackageManager”的handler线程,负责apk的安装、卸载

  5. 创建各种目录,如/data/app、/data/app-lib、/data/app-asec、/data/app-private、/data/app-regional

  6. 创建用户管理服务,管理多用户

  7. 从/etc/permissions目录下面读取获取系统中定义的permissions

  8. 通过SystemConfig得到系统中的共享库列表

  9. 读取安装相关SELinux策略

  10. 读取文件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文件,比如将标签 所指的动态库保存到 PMS的成员变量mSharedLibraries。可见,SystemConfig创建过程是对以下8个目录中的所有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的流程图。

scanDirTracedLI

可以看到依次调用 scanDirLIscanPackageLIscanPackageInternalLI。 其中,scanDirLI调用了 ParallelPackageParser 类进行解析,真正的工作还是交给 PackageParser 来完成。PackageParserparsePackage 方法内部完成了应用的解析,实际上是解析了 AndroidManifest.xml 文件里面各个标签,包括包名、版本、权限、各组件这些信息,最后的解析结果放在 PackageParser.Package 类中返回给 PMS,这样 PMS 就拥有应用的信息便与做各种管理。 后面继续调用了 scanPackageLIscanPackageInternalLI是进一步检测应用是否需要更新,如果需要更新则接着调用 createInstallArgsForExisting构造安装参数开始安装,安装涉及到的签名校验也是在这里,调用了 collectCertificatesLIcompareSignatures等。

parsePackage 解析package的详细流程可参考之前写的文章:安卓PMS模块之安装APK(1)

该阶段主要工作是扫描相关目录下的apk文件,然后做一些删除工作,概括如下:

  1. 从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH
  2. 扫描/vendor/overlay目录下的package
  3. 扫描/system/framework目录下的package
  4. 扫描/system/priv-app目录下的系统package
  5. 扫描/system/app目录下的普通package
  6. 扫描/vendor/app目录下的vendor供应商package
  7. 扫描/oem/app目录下的oem制造商的package
  8. 删除不再存在的系统package
  9. 查找那些安装不完整的package,并将其删除
  10. 删除临时package
  11. 删除那些没有对应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);

主要工作:

  1. sdk版本变更,更新权限;
  2. OTA升级后首次启动,清除不必要的缓存数据;
  3. 权限等默认项更新完后,清理相关数据;
  4. 更新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);

主要工作有:

  1. 创建PackageInstallerService对象
  2. GC回收内存

3.6 小节总结

目前为止已分析完PMS构造方法,一共有5个阶段,总结如下:

  1. PMS_START

    1. 创建Settings对象

    2. 用系统属性来设置DisplayMetrics对象, 保存分辨率等相关信息

    3. 获取系统配置信息,如全局的groupId、系统权限和可用的feature

    4. 创建名为“PackageManager”的handler线程,负责apk的安装、卸载

    5. 创建各种目录,如/data/app、/data/app-lib、/data/app-asec、/data/app-private、/data/app-regional

    6. 创建用户管理服务,管理多用户

    7. 从/etc/permissions目录下面读取获取系统中定义的permissions

    8. 通过SystemConfig得到系统中的共享库列表

    9. 读取安装相关SELinux策略

    10. 读取文件package.xml等文件内容,解析后插到mSettings的mPackages等变量中

  2. PMS_SYSTEM_SCAN_START

    1. 从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH
    2. 扫描/vendor/overlay目录下的package
    3. 扫描/system/framework目录下的package
    4. 扫描/system/priv-app目录下的系统package
    5. 扫描/system/app目录下的普通package
    6. 扫描/vendor/app目录下的vendor供应商package
    7. 扫描/oem/app目录下的oem制造商的package
    8. 删除不再存在的系统package
    9. 查找那些安装不完整的package,并将其删除
    10. 删除临时package
    11. 删除那些没有对应package的shared uid
  3. PMS_DATA_SCAN_START

    对于不仅仅解析核心应用的情况下,还处理data目录的应用信息,及时更新,去除不必要的数据

  4. PMS_SCAN_END

    1. sdk版本变更,更新权限;
    2. OTA升级后首次启动,清除不必要的缓存数据;
    3. 权限等默认项更新完后,清理相关数据;
    4. 更新package.xml、package.lsit及pacakge-stopped.xml文件
  5. PMS_READY

    1. 创建PackageInstallerService对象
    2. GC回收内存

4. PMS启动流程的其他操作

分析完PMS的构造方法后,根据小节2可知,在startOtherServices方法中会调用以下几个方法继续PMS的操作

  1. updatePackagesIfNeeded
  2. performFstrimIfNeeded
  3. systemReady
  4. 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方法的调用栈如下:

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的启动流程,工作简单总结如下:

  1. 启动Installer服务

  2. 构建PMS对象,其中在PMS构造方法中主要做了以下内容:

    1. 创建了 Java 层 Installer 和 C 层 installd 之间的 socket 连接
    2. 扫描各目录下 apk文件完成安装(建立各安装包的配置结构信息,并添加到全局列表中进行管理)
    3. 创建了 PackageHandler 对象并建立消息循环,接收外部的安装请求
    4. 解析权限,建立底层 Linux Kernel 的用户机制和虚拟机层权限机制之间的映射
  3. 根据下面的情况需要Dex优化

    • FOTA升级
    • 第一次开机
    • 恢复出厂设置
    • 从Android pre-N升级到O
    • 清除过Dalvik虚拟机的Cache
  4. 执行磁盘清理工作,释放磁盘空间

  5. 当PMS准备就绪时,更新一些Package的信息、默认权限的获取以及通知在等待PMS就绪的主件

  6. 等待所有packages准备就绪