PMS源码解析——PMS的启动流程(Android12)

1,695 阅读8分钟

Android的知识体系搭建

一 概述

PackageManagerService(后续简称 PMS) 是 Android 最重要的服务之一,它负责了系统种应用的安装,卸载,解析,查询等等功能。

二 PMS 简介

在 Android 中,系统的核心服务有两种启动方式。

  1. 通过 rc 文件配置并加载,单独运行在一个进程中(类似 SurfaceFling 服务)
  2. 在 SystemServer 服务进程中启动。

这里的 PMS 就是使用的第二种方式。关于 PMS 的继承关系如下。

PMS结构.png

三 SystemServer

PMS 是在 SystemServer 启动时,批量启动系统服务时启动的,函数是 startBootstrapServices。

3.1 startBootstrapServices

在 SystemServer 的 startBootstrapServices 中。

[frameworks/base/services/java/com/android/server/SystemServer.java]

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {

	// 创建 PMS 对象
	mPackageManagerService = PackageManagerService.main(mSystemContext,
		installer,domainVerificationService, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF,mOnlyCore);

	SystemServerDexLoadReporter.configureSystemServerDexReporter(
	mPackageManagerService);

    mFirstBoot = mPackageManagerService.isFirstBoot();
    mPackageManager = mSystemContext.getPackageManager();
}

通过 PackageManagerService 的 main 方法获取一个 PackageManagerService 对象。PMS 服务的主要初始化过程,就是通过这个 main 函数开始的。

四 PMS

4.1 main

[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]

public static PackageManagerService main(Context context, Installer installer,
            @NonNull DomainVerificationService domainVerificationService, boolean factoryTest,
            boolean onlyCore) {

	// 创建了一个 PMS 的后台线程
	HandlerThread backgroundThread = new HandlerThread("PackageManagerBg");
	backgroundThread.start();
	Handler backgroundHandler = new Handler(backgroundThread.getLooper());

	// 创建了一个 Injector,这里面保存了好多信息,这里我只列举了一个 Settings
	// Settings 是系统的设置,里面保存了很多系统相关信息
	Injector injector = new Injector(
		(i, pm) -> new Settings(Environment.getDataDirectory(),
                        RuntimePermissionsPersistence.createInstance(),
                        i.getPermissionManagerServiceInternal(),
                        domainVerificationService, lock),
		(i, pm) -> new PackageDexOptimizer(i.getInstaller(),i.getInstallLock(),
		i.getContext(), "*dexopt*")
	);

	// 创建了一个 PackageManagerService 对象
	PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest,
			Build.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG, Build.VERSION.SDK_INT,
			Build.VERSION.INCREMENTAL);

	// 将 PackageManagerService 注册到了 ServiceManager
	ServiceManager.addService("package", m);
	// 创建了一个 PackageManagerNative
	final PackageManagerNative pmn = m.new PackageManagerNative();
	// 将 PackageManagerNative 注册到了
	ServiceManager.addService("package_native", pmn);
	return m;
}
interface Producer<T> {
	/** Produce an instance of type {@link T} */
	T produce(Injector injector, PackageManagerService packageManager);
}

在 main 函数中,主要做了三件事。

  1. 创建了一个 Injector 对象,这个 Injector 的构造函数的参数很多,其实都是 Producer 的子类,Producer 是一个 Single Abstract Method Interfaces (SAM Interfaces)。 所以这里传入的参数都是 lambda 表达式,其实就是对象的构造方式。
  2. 创建了一个 PMS 并添加到系统服务 package 中
  3. 创建了一个 PackageManagerNative 并添加到系统服务 package_native 中

Injector 的中文意思是注射器,其实这里的作用是给 PMS 的一些关键变量赋值。

注意 main 函数中创建了两个对象,Injector 和 PackageDexOptimizer

  • Settings 保存了系统的一些信息
  • PackageDexOptimizer 用于 apk 时的 dex 优化

PMS 的 main 函数很短,是因为主要逻辑都在 PMS 的构造函数中。

4.2 PMS 的构造函数

PackageManagerService 的构造函数非常的长,所以这里只简单说明里面执行的大致逻辑。在 PMS 的构造函数中,官方人为的把它划分为了五个阶段

  • BOOT_PROGRESS_PMS_START:这个阶段主要是一些变量的赋值。
  • BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
  • BOOT_PROGRESS_PMS_DATA_SCAN_START
  • BOOT_PROGRESS_PMS_SCAN_END
  • BOOT_PROGRESS_PMS_READY

4.3 阶段一 BOOT_PROGRESS_PMS_START


// ******************** 阶段一 ********************
// 初始化了一堆的变量

// mOnlyCore 是否只加载核心服务(即不加载三方apk)
// mMetrics 设备的显式信息
// mInstaller 应用的安装器
// 创建了一个 PackageManagerInternalImpl 对象 mPmInternal
// mUserManager 用户管理;
// mComponentResolver 包名解析;
// mPermissionManager 权限管理;

// 获取了一个系统设置 mSettings 对象,并添加了以下 shareUserId
// 注意 main 函数中 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);
mSettings.addSharedUserLPw("android.uid.uwb", UWB_UID,
		ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

...

// 从 injector 中获取 PackageDexOptimizer
// PackageDexOptimizer 的作用是应用安装时对 Dex 优化
mPackageDexOptimizer = injector.getPackageDexOptimizer();
mDexManager = injector.getDexManager();
mArtManagerService = injector.getArtManagerService();
// 前台线程
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
mViewCompiler = injector.getViewCompiler();
// 获取系统显示信息
mContext.getSystemService(DisplayManager.class)
		.getDisplay(Display.DEFAULT_DISPLAY).getMetrics(mMetrics);

// 获取系统配置信息
SystemConfig systemConfig = injector.getSystemConfig();
mAvailableFeatures = systemConfig.getAvailableFeatures();


mProtectedPackages = new ProtectedPackages(mContext);

mApexManager = injector.getApexManager();
mAppsFilter = mInjector.getAppsFilter();

final List<ScanPartition> scanPartitions = new ArrayList<>();
final List<ApexManager.ActiveApexInfo> activeApexInfos = mApexManager.getActiveApexInfos();
for (int i = 0; i < activeApexInfos.size(); i++) {
	final ScanPartition scanPartition = resolveApexToScanPartition(activeApexInfos.get(i));
	if (scanPartition != null) {
		scanPartitions.add(scanPartition);
	}
}

mInstantAppRegistry = new InstantAppRegistry(this, mPermissionManager);

mDirsToScanAsSystem = new ArrayList<>();
mDirsToScanAsSystem.addAll(injector.getSystemPartitions());
mDirsToScanAsSystem.addAll(scanPartitions);


// 获取 /data/app 目录
mAppInstallDir = new File(Environment.getDataDirectory(), "app");

...

// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
// writer
synchronized (mLock) {
	mHandler = injector.getHandler();
	mProcessLoggingHandler = new ProcessLoggingHandler();
	Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);

	// 从系统配置信息中获取共享库
	ArrayMap<String, SystemConfig.SharedLibraryEntry> libConfig
			= systemConfig.getSharedLibraries();
	final int builtInLibCount = libConfig.size();
	for (int i = 0; i < builtInLibCount; i++) {
		addBuiltInSharedLibraryLocked(libConfig.valueAt(i));
	}

	//
	long undefinedVersion = SharedLibraryInfo.VERSION_UNDEFINED;
	for (int i = 0; i < builtInLibCount; i++) {
		String name = libConfig.keyAt(i);
		SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);
		final int dependencyCount = entry.dependencies.length;
		for (int j = 0; j < dependencyCount; j++) {
			final SharedLibraryInfo dependency =
				getSharedLibraryInfoLPr(entry.dependencies[j], undefinedVersion);
			if (dependency != null) {
				getSharedLibraryInfoLPr(name, undefinedVersion).addDependency(dependency);
			}
		}
	}

	...

第一阶段主要就是对系统中一些关键的变量赋值。注意这里创建了一个目录文件,路径是/data/app,后续 PMS 就会对这个目录下的文件进行扫描并解析。

4.4 阶段二 BOOT_PROGRESS_PMS_SYSTEM_SCAN_START


// 第二阶段
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                    startTime);

// 两个系统环境变量
final String bootClassPath = System.getenv("BOOTCLASSPATH");
final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");

// framework  目录 `/system/framework`
File frameworkDir = new File(Environment.getRootDirectory(), "framework");

final VersionInfo ver = mSettings.getInternalVersion();
mIsUpgrade = !buildFingerprint.equals(ver.fingerprint);

// 几个权限相关的判断
mPromoteSystemApps =
		mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;

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;

final WatchedArrayMap<String, PackageSetting> packageSettings =
	mSettings.getPackagesLocked();

// 设备更新相关
if (isDeviceUpgrading()) {
	mExistingPackages = new ArraySet<>(packageSettings.size());
	for (PackageSetting ps : packageSettings.values()) {
		mExistingPackages.add(ps.name);
	}
}

// 缓存目录 `/data/system/package_cache`
mCacheDir = preparePackageParserCache(mIsEngBuild);

// 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;
}

final int systemParseFlags = mDefParseFlags | ParsingPackageUtils.PARSE_IS_SYSTEM_DIR;
final int systemScanFlags = scanFlags | SCAN_AS_SYSTEM;

// 创建 PackageParser2 对象 packageParser,后续用来解析各种 apk 文件
PackageParser2 packageParser = injector.getScanningCachingPackageParser();
// packageParser 解析用的线程池
ExecutorService executorService = ParallelPackageParser.makeExecutorService();
// 在扫描 APK 之前,准备好 apex 包信息,在以下情况下需要扫描apk时需要这些信息
mApexManager.scanApexPackagesTraced(packageParser, executorService);
// 收集供应商/产品/系统_ext的覆盖包。(在扫描任何应用程序之前做这项工作)
// 出于安全和版本匹配的原因,只考虑覆盖包,如果它们驻留在正确的目录中
for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
	final ScanPartition partition = mDirsToScanAsSystem.get(i);
	if (partition.getOverlayFolder() == null) {
		continue;
	}
	scanDirTracedLI(partition.getOverlayFolder(), systemParseFlags,
			systemScanFlags | partition.scanFlag, 0,
			packageParser, executorService);
}

// 扫描 frameworkDir 目录
scanDirTracedLI(frameworkDir, systemParseFlags,
		systemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0,
		packageParser, executorService);

// 遍历扫描目录开始扫描
for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) {
	final ScanPartition partition = mDirsToScanAsSystem.get(i);
	if (partition.getPrivAppFolder() != null) {
		scanDirTracedLI(partition.getPrivAppFolder(), systemParseFlags,
				systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0,
				packageParser, executorService);
	}
	scanDirTracedLI(partition.getAppFolder(), systemParseFlags,
			systemScanFlags | partition.scanFlag, 0,
			packageParser, executorService);
}

	... // 省略代码
}

第二阶段主要就是扫描系统的一些目录文件,主要目录有

  • /system/framework:Android 系统内置的核心 jar 包和 odex 文件
  • /data/system/package_cache/:PMS 扫描后结果的缓存目录

4.5 阶段三 BOOT_PROGRESS_PMS_DATA_SCAN_START


// 如果不是只加载核心apk,一般情况都是false
if (!mOnlyCore) {
	EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
			SystemClock.uptimeMillis());
	// 扫描 App 安装目录,mAppInstallDir 目录是在阶段一中创建的
	scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0,
			packageParser, executorService);

}

packageParser.close();

List<Runnable> unfinishedTasks = executorService.shutdownNow();


if (!mOnlyCore) {
	// 移除已更新的系统应用程序的禁用软件包设置,
	// 这些应用程序是通过OTA删除。如果该更新不再存在,
	// 就将该应用程序完全删除。否则,撤销其系统权限。
	for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) {
		final String packageName = possiblyDeletedUpdatedSystemApps.get(i);
		final AndroidPackage pkg = mPackages.get(packageName);
		final String msg;

		// 从禁用的系统列表中删除
		mSettings.removeDisabledSystemPackageLPw(packageName);

		if (pkg == null) {

		} else {
			removePackageLI(pkg, true);
			try {
				final File codePath = new File(pkg.getPath());
				scanPackageTracedLI(codePath, 0, scanFlags, 0, null);
			} catch (PackageManagerException e) {
			}
		}

		// 最后再检查一次
		final PackageSetting ps = mSettings.getPackageLPr(packageName);
		if (ps != null && mPackages.get(packageName) == null) {
			removePackageDataLIF(ps, userIds, null, 0, false);

		}
	}

	 // 确保所有期望在用户数据分区上的系统应用程序都能出现。
	 // 如果没有出现就回滚系统版本
	for (int i = 0; i < mExpectingBetter.size(); i++) {
		final String packageName = mExpectingBetter.keyAt(i);
		if (!mPackages.containsKey(packageName)) {
			final File scanFile = mExpectingBetter.valueAt(i);

			@ParseFlags int reparseFlags = 0;
			@ScanFlags int rescanFlags = 0;
			for (int i1 = mDirsToScanAsSystem.size() - 1; i1 >= 0; i1--) {
				final ScanPartition partition = mDirsToScanAsSystem.get(i1);
				if (partition.containsPrivApp(scanFile)) {
					reparseFlags = systemParseFlags;
					rescanFlags = systemScanFlags | SCAN_AS_PRIVILEGED
							| partition.scanFlag;
					break;
				}
				if (partition.containsApp(scanFile)) {
					reparseFlags = systemParseFlags;
					rescanFlags = systemScanFlags | partition.scanFlag;
					break;
				}
			}

			mSettings.enableSystemPackageLPw(packageName);

			try {
				final AndroidPackage newPkg = scanPackageTracedLI(
						scanFile, reparseFlags, rescanFlags, 0, null);
				// We rescanned a stub, add it to the list of stubbed system packages
				if (newPkg.isStub()) {
					stubSystemApps.add(packageName);
				}
			} catch (PackageManagerException e) {

			}
		}
	}

	// 解压并安装任何存根的系统应用程序。
	// 必须最后进行,以确保所有存根被替换或禁用。
	installSystemStubPackages(stubSystemApps, scanFlags);

	final int cachedNonSystemApps = PackageCacher.sCachedPackageReadCount.get()
					- cachedSystemApps;

	final long dataScanTime = SystemClock.uptimeMillis() - systemScanTime - startTime;
	final int dataPackagesCount = mPackages.size() - systemPackagesCount;
}
mExpectingBetter.clear();

// 获取 storage manager 的包名
mStorageManagerPackage = getStorageManagerPackageName();

... // 省略代码

// 现在解析完了所有的共享库,更新到所有的客户端,
// 以保证它拥有正确的库路径。
updateAllSharedLibrariesLocked(null, null, Collections.unmodifiableMap(mPackages));

for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
	// 这里忽略了系统扫描过程中可能出现的故障
	final List<String> changedAbiCodePath =
			applyAdjustedAbiToSharedUser(setting, null /*scannedPackage*/,
			mInjector.getAbiHelper().getAdjustedAbiForSharedUser(
					setting.packages, null /*scannedPackage*/));
	if (changedAbiCodePath != null && changedAbiCodePath.size() > 0) {
		for (int i = changedAbiCodePath.size() - 1; i >= 0; --i) {
			final String codePathString = changedAbiCodePath.get(i);
			try {
				mInstaller.rmdex(codePathString,
						getDexCodeInstructionSet(getPreferredInstructionSet()));
			} catch (InstallerException ignored) {
			}
		}
	}
	// 调整seInfo以确保共享UserId的应用程序被放置在同一个
	// SELinux域。
	setting.fixSeInfoLocked();
	setting.updateProcesses();
}

//现在我们知道了我们要保留的所有软件包。
// 读取并更新它们的最后使用时间。
mPackageUsage.read(packageSettings);
mCompilerStats.read();


第二阶段是扫描解析系统的文件,第三阶段就是扫描解析用户目录的文件。不过由于用户的文件可能依赖系统的文件,所以需要更新用户文件的系统依赖路径。

并且移除无效文件,更新上次的最后使用时间等等。

4.6 阶段四 BOOT_PROGRESS_PMS_SCAN_END

// 扫描结束
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
		SystemClock.uptimeMillis());

mPermissionManager.readLegacyPermissionStateTEMP();

// 如果在上次启动之后,构建特征发生了变化。
// 就需要重新授予应用程序权限,以捕捉任何新出现的情况
// 这意味着应用程序在某些情况下可以获得用户最初没有明确允许的权限。
// 如果有一些更好的方法来处理这种情况就更好了。
// (真的假的?)
mPermissionManager.onStorageVolumeMounted(
		StorageManager.UUID_PRIVATE_INTERNAL, mIsUpgrade);
ver.sdkVersion = mSdkVersion;

// 如果这是第一次启动或从M之前的更新,并且是正常的启动
// 那么我们就初始化所有定义的用户默认首选应用程序。
if (!mOnlyCore && (mPromoteSystemApps || mFirstBoot)) {
	for (UserInfo user : mInjector.getUserManagerInternal().getUsers(true)) {
		mSettings.applyDefaultPreferredAppsLPw(user.id);
	}
}

// 在启动过程中为系统用户真正提前准备好存储。
// 因为核心系统应用程序(如 SettingsProvide r和 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.submit(() -> {
	try {
		mInstaller.fixupAppData(StorageManager.UUID_PRIVATE_INTERNAL,
				StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
	} catch (InstallerException e) {	}

	if (deferPackages == null || deferPackages.isEmpty()) {
		return;
	}
	int count = 0;
	final Installer.Batch batch = new Installer.Batch();
	for (String pkgName : deferPackages) {
		AndroidPackage pkg = null;
		synchronized (mLock) {
			PackageSetting ps = mSettings.getPackageLPr(pkgName);
			if (ps != null && ps.getInstalled(UserHandle.USER_SYSTEM)) {
				pkg = ps.pkg;
			}
		}
		if (pkg != null) {
			prepareAppDataAndMigrate(batch, pkg, UserHandle.USER_SYSTEM, storageFlags,
					true /* maybeMigrateAppData */);
			count++;
		}
	}
	synchronized (mInstallLock) {
		executeBatchLI(batch);
	}
	traceLog.traceEnd();
	Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages");
}, "prepareAppData");

// 如果这是OTA后的第一次启动,而且是正常启动,
// 那么我们就清除代码缓存目录。
// 注意,我们并不清除应用程序配置文件。这些文件仍然有效
// 在不同的OTA中都是有效的
if (mIsUpgrade && !mOnlyCore) {

	for (int i = 0; i < packageSettings.size(); i++) {
		final PackageSetting ps = packageSettings.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
							| Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
		}
	}
	ver.fingerprint = Build.FINGERPRINT;
}

// 在Q之前安装的非系统应用程序,隐藏它们在 Launch 中的图标。
if (!mOnlyCore && mIsPreQUpgrade) {
	int size = packageSettings.size();
	for (int i = 0; i < size; i++) {
		final PackageSetting ps = packageSettings.valueAt(i);
		if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
			continue;
		}
		ps.disableComponentLPw(PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,
				UserHandle.USER_SYSTEM);
	}
}

// 只有在权限和其他默认值被更新后才能清除
mPromoteSystemApps = false;

// 所有的变化都是在软件包扫描期间完成的
ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;

// 将信息写到 packages.xml 文件
writeSettingsLPrTEMP();

第四阶段是扫描后的一些操作,我们从代码里看到,诸如权限,配置等信息的更新。

4.7 阶段五 BOOT_PROGRESS_PMS_READY

// 最后一个阶段
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
		SystemClock.uptimeMillis());

... // 大段变量的赋值

// PermissionController主持默认的权限授予和角色管理,
// 所以它是一个核心系统的关键部分
mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr();

mSettings.setPermissionControllerVersion(
		getPackageInfo(mRequiredPermissionControllerPackage, 0,
				UserHandle.USER_SYSTEM).getLongVersionCode());

// 为所有用户初始化InstantAppRegistry的即时应用程序列表。
for (AndroidPackage pkg : mPackages.values()) {
	if (pkg.isSystem()) {
		continue;
	}
	for (int userId : userIds) {
		final PackageSetting ps = getPackageSetting(pkg.getPackageName());
		if (ps == null || !ps.getInstantApp(userId) || !ps.getInstalled(userId)) {
			continue;
		}
		mInstantAppRegistry.addInstantAppLPw(userId, ps.appId);
	}
}

mInstallerService = mInjector.getPackageInstallerService();
final ComponentName instantAppResolverComponent = getInstantAppResolverLPr();
if (instantAppResolverComponent != null) {
	mInstantAppResolverConnection =
			mInjector.getInstantAppResolverConnection(instantAppResolverComponent);
	mInstantAppResolverSettingsComponent =
			getInstantAppResolverSettingsLPr(instantAppResolverComponent);
} else {
	mInstantAppResolverConnection = null;
	mInstantAppResolverSettingsComponent = null;
}
updateInstantAppInstallerLocked(null);

// 读取并更新dex文件的用法。在PM init的结束时执行,
// 以便协调所有的包都的数据目录。因为我们现在已经知道软件包的路径
// 所以我们可以验证磁盘文件并建立内部缓存。
// 预计使用文件会很小,所以加载和验证它与其他活动(如软件包扫描)相比
// 应该只会花费相当少的时间。
final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
for (int userId : userIds) {
	userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList());
}
mDexManager.load(userPackages);

// 由于一些属性已经被重建,所以要重新建立实时计算
mLiveComputer = createLiveComputer();

}
}

mModuleInfoProvider = mInjector.getModuleInfoProvider();
mInjector.getSystemWrapper().enablePackageCaches();

// 现在打开每一个应用程序的压缩包后,确保它们都被刷新了(不必要)

VMRuntime.getRuntime().requestConcurrentGC();

ParsingPackageUtils.readConfigUseRoundIcon(mContext.getResources());

阶段五是扫描结束只会,系统做的一些准备工作。例如

  • 权限控制的 mRequiredPermissionControllerPackage
  • 通过 mInjector 获取了一个 PackageInstallerService,这个东西是一开始 main 函数中,通过 Producer 生产者构造出来的
  • 将 dex 从磁盘读到缓存中等

五 总结

好了,关于 PMS 的构造函数与初始化,现在我们再来做一个简单的总结。

  • 首先,在 PMS 的 main 函数中,会创建一个很重要的对象 Injector。传入的参数是一堆的生产者的 lambda 表达式。然后还创建了一个 HandlerThread(backgroundThread)。
  • 创建了一个 PMS 对象,并将它发布到 ServiceManager,服务的名字叫 package
  • 创建了一个 PackageManagerNative 对象,并将它发布到 ServiceManager,服务的名字叫 package_native

然后在 PMS 的构造函数中,做了一大堆初始化的逻辑。具体分为 5 个阶段

  1. 初始化了一堆的变量,并创建了 /data/app 的文件目录。
  2. 扫描系统目录文件 /data/system/package_cache 和 /system/framework
  3. 扫描用户的 app 安装目录 /data/app
  4. 根据系统文件的扫描结果,更新用户 app 的依赖,并删掉没用的数据。如果系统版本有更新,也需要处理
  5. 将 dex 从磁盘读到缓存中等

最后,我们留几个之后要探讨问题留在之后探讨。

  1. apk 是如何安装的(PackageInstallerService 的工作原理)
  2. apk 安装到 /data/app 文件目录后,PMS 是如何扫描解析的(阶段二和阶段三)的深入研究