PackageManagerServervice 通过 SystemServer 进程启动，该服务会 扫描系统中特定的目录，寻找里面的 APK 格式文件，并对这些文件进行解析（得到 AppInfo 相关讯息），最后完成安装。
PKMS 会在安装应用的过程中解析 APK 中的 AndroidManifest.xml 文件（解析出 Android 四大组件），这些解析完的信息会保存在 Android 系统中，方便系统随时取用。

主要功能

扫描 .apk 文件，安装 系统应用、本地应用

Parser AndroidManifest.xml 清单文件，分析出四大零组件、权限… 等等信息，并储存在 PKMS 方便查询

管理本地应用，其中包括 安装、卸载、查询 APK 信息 … 等等功能

分配应用程序的 UID、GID

透过 GID（Group 群组 ID）来管理权限管理，在某个群组中才能使用某些功能

使用

我们可以通过Context#getPackageManager（）方法 来取得 PKMS 服务，PackageManager 是抽象类，实际上是 ApplicationPackageManager。

Copy

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

PackageManager packageManager = this.getBaseContext().getPackageManager();
}

ServiceManager 取得 PKMS

ActivityThread 通过 ServiceManager 取得 PKMS 的 IBinder，这里的
IPackageManager 是透过 AIDL 自动产生的类，IPackageManager 通过 asInterface 来取得 Java 代理类，透过该代理类来与 PKMS 通信

Copy
// ActivityThread.java

@UnsupportedAppUsage
public static IPackageManager getPackageManager() {
if (sPackageManager != null) {
return sPackageManager;
}

// 1.取得ServiceManager的代理
// 2.透过代理传入“package”来取得PKMS的句柄（handle）
// 3.返回PKMS的代理
final IBinder b = ServiceManager.getService("package");

// 创建 AIDL 的代理类
sPackageManager = IPackageManager.Stub.asInterface(b);

return sPackageManager;
}

SystemServer 初始化 PKMS

SystemServer 启动引导服务（startBootstrapServices）:PKMS 就是在这里启动

Copy
// SystemServer.java

public static void main(String[] args) {
new SystemServer().run();
}

private void run() {
... 省略部分

try {
startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
} /* 省略 catch */

... 省略部分

// Loop forever.
Looper.loop();

throw new RuntimeException("Main thread loop unexpectedly exited");
}

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t)
...

// 安装服务
Installer installer = mSystemServiceManager.startService(Installer.class);

mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

...

try {
... watch dog

// 呼叫 PackageManagerService 的静态 main 方法
// @ 分析 main
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
domainVerificationService, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF,
mOnlyCore);
} ... watch dog

...
}

startBootstrapServices

启动 Installer 服务，之后会用这个服务来安装所有应用

Copy
// SystemServer.java

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
... 省略部分

Installer installer = mSystemServiceManager.startService(Installer.class);

... 省略部分
}

VoldProperties#decrypt 判断手机装置是否加密（读取 init.rc 档的设定），mOnlyCore = true 代表只运行核心程序。

Copy
// SystemServer.java

private static final String ENCRYPTING_STATE = "trigger_restart_min_framework";

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
...

// Only run "core" apps if we're encrypting the device.
String cryptState = VoldProperties.decrypt().orElse("");

if (ENCRYPTING_STATE.equals(cryptState)) {
// 只运行核心程序
... log msg

mOnlyCore = true;
} else if (ENCRYPTED_STATE.equals(cryptState)) {
... log msg

mOnlyCore = true;
}

...
}

调用PKMS#main方法，创建 PKMS 对象

Copy
// SystemServer.java

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
... 省略部分

try {
...

PackageManagerService.main(mSystemContext, installer,
domainVerificationService,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF,
mOnlyCore); // 假设传入 false
} /* 省略 finally */

... 省略部分
}

如果设备没有加密，就执行 A/B OTA dexopting，OtaDexoptService#main方法

Copy
// SystemServer.java

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
...

if (!mOnlyCore) {
boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
false);

if (!disableOtaDexopt) {
... trace log
try {
... watch dog

OtaDexoptService.main(mSystemContext, mPackageManagerService);
} /* catch、finally */
}
}

...
}

PKMS 在 SystemServer#startBootstrapServices函数 完成初始化操作后，会在 startOtherServices 做后续的操作（完成 Dex 优化、systemReady）
透过PKMS#performFstrimIfNeeded完成 dex 优化

Copy
// SystemServer.java

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {

... 省略部分

try {
mPackageManagerService.performFstrimIfNeeded();
} ...

... 省略部分
}

PKMS 准备就绪调用 systemReady，加载预设权限

PKMS 分析

PKMS main

透过PackageManagerService#main方法就可以创建 PackageManagerService 物件，并且将 PKMS 透过 package、package_native 添加到 ServiceManager 中

Copy
// PackageManagerService.java

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

// 检查 package 编译相关系统属性
PackageManagerServiceCompilerMapping.checkProperties();

...

Injector injector = new Injector(
context, lock, installer, installLock,
new PackageAbiHelperImpl(),
backgroundHandler,
SYSTEM_PARTITIONS,
(i, pm) -> new ComponentResolver(i.getUserManagerService(), pm.mPmInternal, lock),
(i, pm) -> PermissionManagerService.create(context,
i.getSystemConfig().getAvailableFeatures()),
(i, pm) -> new UserManagerService(context, pm,
new UserDataPreparer(installer, installLock, context, onlyCore),
lock),
(i, pm) -> new Settings(Environment.getDataDirectory(),
RuntimePermissionsPersistence.createInstance(),
i.getPermissionManagerServiceInternal(),
domainVerificationService, lock),
(i, pm) -> AppsFilter.create(pm.mPmInternal, i),
(i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"),
(i, pm) -> SystemConfig.getInstance(),
(i, pm) -> new PackageDexOptimizer(i.getInstaller(), i.getInstallLock(),
i.getContext(), "*dexopt*"),
(i, pm) -> new DexManager(i.getContext(), pm, i.getPackageDexOptimizer(),
i.getInstaller(), i.getInstallLock()),
(i, pm) -> new ArtManagerService(i.getContext(), pm, i.getInstaller(),
i.getInstallLock()),
(i, pm) -> ApexManager.getInstance(),
(i, pm) -> new ViewCompiler(i.getInstallLock(), i.getInstaller()),
(i, pm) -> (IncrementalManager)
i.getContext().getSystemService(Context.INCREMENTAL_SERVICE),
(i, pm) -> new DefaultAppProvider(() -> context.getSystemService(RoleManager.class),
() -> LocalServices.getService(UserManagerInternal.class)),
(i, pm) -> new DisplayMetrics(),
(i, pm) -> new PackageParser2(pm.mSeparateProcesses, pm.mOnlyCore,
i.getDisplayMetrics(), pm.mCacheDir,
pm.mPackageParserCallback) /* scanningCachingPackageParserProducer */,
(i, pm) -> new PackageParser2(pm.mSeparateProcesses, pm.mOnlyCore,
i.getDisplayMetrics(), null,
pm.mPackageParserCallback) /* scanningPackageParserProducer */,
(i, pm) -> new PackageParser2(pm.mSeparateProcesses, false, i.getDisplayMetrics(),
null, pm.mPackageParserCallback) /* preparingPackageParserProducer */,
// Prepare a supplier of package parser for the staging manager to parse apex file
// during the staging installation.
(i, pm) -> new PackageInstallerService(
i.getContext(), pm, i::getScanningPackageParser),
(i, pm, cn) -> new InstantAppResolverConnection(
i.getContext(), cn, Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE),
(i, pm) -> new ModuleInfoProvider(i.getContext(), pm),
(i, pm) -> LegacyPermissionManagerService.create(i.getContext()),
(i, pm) -> domainVerificationService,
(i, pm) -> {
// 负责 apk 安装、卸载
HandlerThread thread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
thread.start();
return pm.new PackageHandler(thread.getLooper());
},
new DefaultSystemWrapper(),
LocalServices::getService,
context::getSystemService);

// 调用 PackageMangerService 的构造函数
PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest,
Build.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG, Build.VERSION.SDK_INT,
Build.VERSION.INCREMENTAL);

...

// 通过 package、package_native 添加到 ServiceManager中
ServiceManager.addService("package", m);
final PackageManagerNative pmn = m.new PackageManagerNative();
ServiceManager.addService("package_native", pmn);
return m;
}

Copy
// PackageManagerService.java

public static class Injector {

@VisibleForTesting(visibility = Visibility.PRIVATE)
interface Producer<T> {
/** Produce an instance of type {@link T} */
T produce(Injector injector, PackageManagerService packageManager);
}

...

@VisibleForTesting(visibility = Visibility.PRIVATE)
static class Singleton<T> {
private final Producer<T> mProducer;
private volatile T mInstance = null;

Singleton(Producer<T> producer) {
this.mProducer = producer;
}

T get(Injector injector, PackageManagerService packageManagerService) {
if (mInstance == null) {
mInstance = mProducer.produce(injector, packageManagerService);
}
return mInstance;
}
}

private final Singleton<PermissionManagerServiceInternal> mPermissionManagerServiceProducer;
private final Singleton<UserManagerService> mUserManagerProducer;
private final Singleton<Settings> mSettingsProducer;
private final Singleton<AppsFilter> mAppsFilterProducer;
...
private final Singleton<DisplayMetrics> mDisplayMetricsProducer;

Injector(Context context, PackageManagerTracedLock lock, Installer installer,
Object installLock, PackageAbiHelper abiHelper,
Handler backgroundHandler,
List<ScanPartition> systemPartitions,
...
Producer<PermissionManagerServiceInternal> permissionManagerServiceProducer,
Producer<UserManagerService> userManagerProducer,
Producer<Settings> settingsProducer,
Producer<DisplayMetrics> displayMetricsProducer,
) {

...

mPermissionManagerServiceProducer = new Singleton<>(permissionManagerServiceProducer);
mUserManagerProducer = new Singleton<>(userManagerProducer);
mSettingsProducer = new Singleton<>(settingsProducer);

...

mDisplayMetricsProducer = new Singleton<>(displayMetricsProducer);
}

public PermissionManagerServiceInternal getPermissionManagerServiceInternal() {
return mPermissionManagerServiceProducer.get(this, mPackageManager);
}

public Context getContext() {
return mContext;
}

public Settings getSettings() {
return mSettingsProducer.get(this, mPackageManager);
}

public DisplayMetrics getDisplayMetrics() {
return mDisplayMetricsProducer.get(this, mPackageManager);
}

...

}

PKMS 构造方法

PackageManagerService 的构造函数中可以发现 PKMS 构造有 5 个阶段 （写在 EventLog 中）

阶段标志 | 说明 | 其他
BOOT_PROGRESS_PMS_START | 初始阶段，透过 Inject 内部类来取得 单例 的各种服务、对象 | DisplayMetrics、Installer、mPermissionManager、mSettings、mPackageDexOptimizer
BOOT_PROGRESS_PMS_SYSTEM_SCAN_START | 扫描系统 |
BOOT_PROGRESS_PMS_DATA_SCAN_START | 扫描 data 区块 |
BOOT_PROGRESS_PMS_SCAN_END | 扫描结束 |
BOOT_PROGRESS_PMS_READY | 准备阶段 |

PKMS 有使用到多 Thread，而里面有两个重要的 锁 需要注意

锁名称 | 说明 | 补充
mPackages（小锁） | 用于保护所有内存中解析 Package 的细节、状态、更新 | 在持有 mInstallLock 的时候，获取 mPackages 是安全的
mInstallLock（大锁） | 用于保护所有安装 APK 时的锁，通常是有关到应用 APP 的重载（单线程、涉及繁重的 IO 操作） | 在获取 mPackages 时，不该再获取此锁

第一阶段 - BOOT_PROGRESS_PMS_START

第一阶段的重点是 Settings#readLPw 方法，读取 /data/system 目录下的文件

BOOT_PROGRESS_PMS_START：取得 DisplayMetrics（分辨率）、Installer（安装）、PermissionManager （权限管理）、mSettings（保存安装信息、清除不存在的应用）、PackageDexOptimizer（Dex 优化）… 详细请看注释

Copy
// PackageManagerService.java

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,final String buildFingerprint, final boolean isEngBuild,final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

...

EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis());

mOnlyCore = onlyCore;
mMetrics = injector.getDisplayMetrics();
mInstaller = injector.getInstaller();
mUserManager = injector.getUserManagerService(); // 多用戶管理
// 权限管理服务
mPermissionManager = injector.getPermissionManagerServiceInternal();

// 涉及 'data/system/' packages.xml
// packages-backup.xml
// packages.list
// packages-stopped.xml
// packages-stopped-backup.xml 文件
mSettings = injector.getSettings();

...

// 添加 system、phone、log、nfc、bluetooth、shell、se、
// networkstack、uwb 这几个 sharedUserLPw 到 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);

...

// 处理 dex 优化（DexOpt 优化）
mPackageDexOptimizer = injector.getPackageDexOptimizer();
mDexManager = injector.getDexManager();
// Art 虚拟机管理
mArtManagerService = injector.getArtManagerService();

...

// 创建 /data/app 文件夹
mAppInstallDir = new File(Environment.getDataDirectory(), "app");

// 安装 APK 时需要的锁，保护所有对 installed 的访问
// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
// writer
synchronized (mLock) {
// 启动 PackageManager Thread，负责 apk 安装、卸载
mHandler = injector.getHandler();
// 进程纪录 Handler
mProcessLoggingHandler = new ProcessLoggingHandler();

// 监听 PackageManager Thread 是否超时10分钟
Watchdog.getInstance().addThread(mHandler,
// WATCHDOG_TIMEOUT => 10 分鐘
WATCHDOG_TIMEOUT);

...

// 读取安装相关的 SELinux 策略
SELinuxMMAC.readInstallPolicy();

// 读取并解析 /data/system 中的 xml 文件
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));

t.traceEnd();
}

}
}

其中 mSettings.addSharedUserLPw 方法是将 SharedUserId 添加到 Setting 中；一般来讲进程间数据不可共享，但 有共同 SharedUserId 就可以共享数据

mPackageDexOptimizer 是 Dex 的优化工具

mHandler 绑定后台 ServiceThread 的消息队列，PKMS 通过它来驱动 APK 复制＆安装，并且该 Handler 会由 WatchDog 来监看（防止花费过多时间）

PKMD 会访问几个重要的文件夹

访问 | 资料夾
File(Environment.getDataDirectory(), “app”) | /data/app
File(Environment.getDataDirectory(), “app-lib”) | /data/app-lib

Settings 创建

先复习 Settings 对象由来：PKMS 的 Settings 对象会由PKMS#Inject类提供

Copy
// PackageManager

public static class Injector {

private final Singleton<Settings> mSettingsProducer;

Injector(/* 省略参数 */) {
...
mSettingsProducer = new Singleton<>(settingsProducer);
}

public Settings getSettings() {
return mSettingsProducer.get(this, mPackageManager);
}

}

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

Injector injector = new Injector(
context, lock, installer, installLock, new PackageAbiHelperImpl(),
backgroundHandler,
SYSTEM_PARTITIONS,
...

(i, pm) -> new Settings(Environment.getDataDirectory(),
RuntimePermissionsPersistence.createInstance(),
i.getPermissionManagerServiceInternal(),
domainVerificationService,
lock),
);
}

Settings 类 的构造函数会创建所需文件 & 文件夹，并设定它们的权限

Copy
// Settings.java

Settings(File dataDir, //带入的 dataDir 是 /data
RuntimePermissionsPersistence runtimePermissionsPersistence,
LegacyPermissionDataProvider permissionDataProvider,
@NonNull DomainVerificationManagerInternal domainVerificationManager,
@NonNull PackageManagerTracedLock lock) {

...

// 创建 /data/system 目录
mSystemDir = new File(dataDir, "system");//'/data/system'
mSystemDir.mkdirs(); // 创建 /data/system
// 文件夹权限 775
FileUtils.setPermissions(mSystemDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1, -1);

// 创建 /data/system/packages.xml
mSettingsFilename = new File(mSystemDir, "packages.xml");
// 创建 /data/system/packages-backup.xml
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
// 创建 data/system/packages.list
mPackageListFilename = new File(mSystemDir, "packages.list");

// 设定 chmod 0640
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
// 创建 data/system/packages-stopped.list
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
// 创建 data/system/packages-stopped-backup.list
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");

...

}

Settings - readLPw 读取 package 文件

mSettings#readLPw () 函数：读取 /data/system 目录下的文件，并保存到 Setting 对象中，而文件又分为以下几种（提出较为重要的几个）

文件名 | 说明 | 其他
packages.xml | 安装 app 信息 | PKMS 扫描完目录文件后会创建该文件，当系统执行 安装、卸载、更新 等操作时都会更新这个文件
packages-backup.xml | 安装 app 的备份信息 | 避免在安装时关机，产生意外
packages.list | 所有安装的 app 信息（非系统 APP） | 描述所有非系统 APK 信息，当有第三方 APP 变更时就会修改该文件
packages-stopped.xml | 强制停止 app 信息 | 强制停止某个应用时（用户操作），系统会将该应用的相关讯息记录到该文件中
packages-stopped-backup.xml | 强制停止 app 的备份信息 |
mSettings#readLPw() 功能：首先扫描 packages.xml、packages-backup.xml 文件，其中与 Linux 使用 UID 有关的函数如下 | |
“package” 标签：使用 readPackageLPw 函数，读取上一次分配的 Linux UID | |
“shared-user” 标签：使用 readSharedUserLPw 函数，读取上一次应用共享的 shared ID | |

Copy
// Settings.java

boolean readLPw(@NonNull List<UserInfo> users) {
FileInputStream str = null;

// 如果有 packages-backup.xml的话取得backup IO流
if (mBackupSettingsFilename.exists()) {
try {
str = new FileInputStream(mBackupSettingsFilename);
...
} /* 省略 catch */
}

try {
if (str == null) {
...

// 没有 backup 就使用 packages.xml
str = new FileInputStream(mSettingsFilename);
}

// 解析 xml
final TypedXmlPullParser parser = Xml.resolvePullParser(str);
int type;
// 调整 xml 指标位置
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
;
}
// 解析格式，判断 xml 格式是否正确
if (type != XmlPullParser.START_TAG) {
... err log
return false;
}

int outerDepth = parser.getDepth();
// 开始分析 xml
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}

// 解析节点名称
String tagName = parser.getName();
if (tagName.equals("package")) {
// 读取上一次分配的 Linux UID
readPackageLPw(parser, users);

} else if (tagName.equals("permissions")) {
mPermissions.readPermissions(parser);

} else if (tagName.equals("permission-trees")) {
mPermissions.readPermissionTrees(parser);

} else if (tagName.equals("shared-user")) {
// 读取上一次应用共享的 GID
readSharedUserLPw(parser, users);

} ... 省略部分 else if

else {
... log

XmlUtils.skipCurrentTag(parser);
}
}
str.close();
} /* 省略 catch、finally */

...

return true;
}

readPackageLPw 应用分配独立 Linux ID

接下来我们主要关注 “package” 标签中的 3 元素

元素名 | 功能 | 补充
name | 应用包名 | 必须要有 package 包名
userId | Linux 上次为该应用分配的 独立 UID |
sharedUserId | 该应用 没有独立 UID，与其它应用共享 UID | 将该应用添加进 mPendingPackages 列表之后判断

Copy
// Setting.java

public static final String ATTR_NAME = "name";

private final WatchedArrayList<PackageSetting> mPendingPackages = new WatchedArrayList<>();

private void readPackageLPw(TypedXmlPullParser parser, List<UserInfo> users,
ArrayMap<String, Long> originalFirstInstallTimes)
throws XmlPullParserException, IOException {

String name = null;
int userId = 0;
int sharedUserAppId = 0;

try {
// App package name
name = parser.getAttributeValue(null, ATTR_NAME);

...

userId = parser.getAttributeInt(null, "userId", 0);
sharedUserAppId = parser.getAttributeInt(null, "sharedUserId", 0);

if (name == null) {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <package> has no name at "
+ parser.getPositionDescription());
} else if (codePathStr == null) {
...

} else if (userId > 0) { // 已分配到独立 ID
packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
legacyNativeLibraryPathStr, primaryCpuAbiString, secondaryCpuAbiString,
cpuAbiOverrideString, userId, versionCode, pkgFlags, pkgPrivateFlags,
null /* usesSdkLibraries */, null /* usesSdkLibraryVersions */,
null /* usesStaticLibraries */, null /* usesStaticLibraryVersions */,
null /* mimeGroups */, domainSetId);

...

} else if (sharedUserAppId != 0) { // 未分配独立 ID
if (sharedUserAppId > 0) {

// 保存该应用信息
packageSetting = new PackageSetting(name.intern(), realName,
new File(codePathStr), legacyNativeLibraryPathStr,
primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
versionCode, pkgFlags, pkgPrivateFlags, sharedUserAppId,
null /* usesSdkLibraries */,
null /* usesSdkLibrariesVersions */,
null /* usesStaticLibraries */,
null /* usesStaticLibraryVersions */,
null /* mimeGroups */, domainSetId);
...

// 添加到 `mPendingPackages` 列表
mPendingPackages.add(packageSetting);
...
} else {
...
}
} else {
...
}
} /* 省略 catch */
}

addPackageLPw 函数：在 PKMS 中 每个应用都是以 PackageSetting 对象存在，并将其储存在以 package name 为 Key 的 HashMap 中

Copy
// Setting.java

// 储存全部应用的信息
final WatchedArrayMap<String, PackageSetting> mPackages;

private final AppIdSettingMap mAppIds;

PackageSetting addPackageLPw(String name, String realName, File codePath,
String legacyNativeLibraryPathString, String primaryCpuAbiString,
String secondaryCpuAbiString, String cpuAbiOverrideString, int uid,
... /* 省略部分 */) {

// 以 name 来取得 PackageSetting
PackageSetting p = mPackages.get(name);
if (p != null) {
// 判断 uid
if (p.getAppId() == uid) {
// 相等代表已分配独立 UID
return p;
}
PackageManagerService.reportSettingsProblem(Log.ERROR,
"Adding duplicate package, keeping first: " + name);
return null;
}
p = new PackageSetting(name, realName, codePath, legacyNativeLibraryPathString,
primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
... /* 省略部分 */);

// 设定 UID 给该 PackageSetting
p.setAppId(uid);

// 注册该 ID 至系统
if (mAppIds.registerExistingAppId(uid, p, name)) {
mPackages.put(name, p);
return p;
}
return null;
}

registerExistingAppId函数：已分配的应用会从 mNonSystemSettings 取出 null

Copy
// Process.java

public static final int FIRST_APPLICATION_UID = 10000;

// ------------------------------------------------------------
// AppIdSettingMap.java

private final WatchedArrayList<SettingBase> mNonSystemSettings;

public boolean registerExistingAppId(int appId, SettingBase setting, Object name) {

// 大于 FIRST_APPLICATION_UID 代表是独立应用
if (appId >= Process.FIRST_APPLICATION_UID) {
int size = mNonSystemSettings.size();
final int index = appId - Process.FIRST_APPLICATION_UID;
// fill the array until our index becomes valid
while (index >= size) {
mNonSystemSettings.add(null);
size++;
}
// 已分配会取出 null
if (mNonSystemSettings.get(index) != null) {
// 重复 UID

...err msg
return false;
}
mNonSystemSettings.set(index, setting);
} else {
// 小于 FIRST_APPLICATION_UID 代表是共享应用
...
}
return true;
}

readPackageLPw 应用分配共享 Linux ID

接下来我们主要关注 “shared-user” 标签中的 3 元素

元素名 | 功能 | 补充
name | 用来描述一个共享 Linux 使用者的名称 |
userId | 用来描述一个共享 Linux 使用者的 ID |
system | 描述该 ID 是系统型态、使用者型态 |

Copy
// Setting.java

private void readSharedUserLPw(TypedXmlPullParser parser, List<UserInfo> users)
throws XmlPullParserException, IOException {
String name = null;
int pkgFlags = 0;
int pkgPrivateFlags = 0;
SharedUserSetting su = null;
{
name = parser.getAttributeValue(null, ATTR_NAME);
int userId = parser.getAttributeInt(null, "userId", 0);
if (parser.getAttributeBoolean(null, "system", false)) {
pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
}

if (name == null) {
...
} else if (userId == 0) {
...
} else {
if ((su = addSharedUserLPw(name.intern(), userId, pkgFlags, pkgPrivateFlags))
== null)
...
}
}
}

...
}

Setting#addSharedUserLPw 函数：使用 SharedUserSetting 来描述一个共享应用；比对 ID 确认没问题后，就可以加入 mSharedUsers 列表

Copy
// Setting.java

final WatchedArrayMap<String, SharedUserSetting> mSharedUsers
= new WatchedArrayMap<>();

SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
SharedUserSetting s = mSharedUsers.get(name);
if (s != null) {
if (s.mAppId == uid) {
return s;
}
...err

return null;
}
// 创建对应对象
s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
// 设定 ID
s.mAppId = uid;

// 尝试注册
if (mAppIds.registerExistingAppId(uid, s, name)) {
mSharedUsers.put(name, s);
return s;
}
return null;
}

registerExistingAppId 函数：已分配的应用会从 mNonSystemSettings 取出 null

Copy
// Process.java

public static final int FIRST_APPLICATION_UID = 10000;

// ------------------------------------------------------------
// AppIdSettingMap.java

private final WatchedArrayList<SettingBase> mNonSystemSettings;

public boolean registerExistingAppId(int appId, SettingBase setting, Object name) {

// 大于 FIRST_APPLICATION_UID 代表是独立应用
if (appId >= Process.FIRST_APPLICATION_UID) {
...
} else {
// 小于 FIRST_APPLICATION_UID 代表是共享应用
if (mSystemSettings.get(appId) != null) {
...err

return false;
}
mSystemSettings.put(appId, setting);
}
return true;
}

回到 readLPw 函数：经过上面分析 “shared-user”、“package” 后可以得到共享、独立应用的相关讯息，接着就是要处理共享应用的 ID

Copy
// Settings.java

private final AppIdSettingMap mAppIds;

boolean readLPw(@NonNull List<UserInfo> users) {

...

final int N = mPendingPackages.size();

for (int i = 0; i < N; i++) {
final PackageSetting p = mPendingPackages.get(i);
final int sharedUserAppId = p.getSharedUserAppId();

// 共享 ID 一定大于 0
if (sharedUserAppId <= 0) {
continue;
}
final Object idObj = getSettingLPr(sharedUserAppId);
if (idObj instanceof SharedUserSetting) {
final SharedUserSetting sharedUser = (SharedUserSetting) idObj;
addPackageSettingLPw(p, sharedUser);
} else if (idObj != null) {
...
} else {
...
}
}
mPendingPackages.clear();

return true;
}

public SettingBase getSettingLPr(int appId) {
return mAppIds.getSetting(appId);
}

void addPackageSettingLPw(PackageSetting p, SharedUserSetting sharedUser) {
mPackages.put(p.getPackageName(), p);

// 如果是共享应用还要再判断
if (sharedUser != null) {
SharedUserSetting existingSharedUserSetting = getSharedUserSettingLPr(p);

if (existingSharedUserSetting != null && existingSharedUserSetting != sharedUser) {
...err msg

sharedUser.removePackage(p);
} else if (p.getAppId() != sharedUser.mAppId) {
...err msg

}

sharedUser.addPackage(p);
p.setSharedUserAppId(sharedUser.mAppId);
// 决定最终 ID
p.setAppId(sharedUser.mAppId);
}

Object userIdPs = getSettingLPr(p.getAppId());
if (sharedUser == null) {
if (userIdPs != null && userIdPs != p) {
mAppIds.replaceSetting(p.getAppId(), p);
}
} else {
if (userIdPs != null && userIdPs != sharedUser) {
mAppIds.replaceSetting(p.getAppId(), sharedUser);
}
}
}

第二阶段 - BOOT_PROGRESS_PMS_SYSTEM_SCAN_START

BOOT_PROGRESS_PMS_SYSTEM_SCAN_START：扫描系统阶段，其中目录包括（system、vendor、product、odm、oem … 等等目录中的 priv-app、app、overlay）并且该步骤 仍在两个锁内执行
scanDirTracedLI 方法：该方法扫描 APK 包，会针对传入的路径扫描内部的 APK 档案，之后会再针对 scanDirTracedLI 进行分析

Copy
// PackageManagerService.java

// Key 是应用包名，Value 是应用包
final ArrayMap<String, PackageParser.Package> mPackages =
new ArrayMap<String, PackageParser.Package>();

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
final String buildFingerprint, final boolean isEngBuild,
final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

...

// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
// writer
synchronized (mLock) {

...

// 记录开始时间
long startTime = SystemClock.uptimeMillis();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
startTime);

// 从 init.rc 中获取环境变量 BOOTCLASSPATH、
// SYSTEMSERVERCLASSPATH
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();

// 判断是否需要更新
mIsUpgrade =
!buildFingerprint.equals(ver.fingerprint);

// Android M 升级上来的版本，须将系统应用权限从安装时申请，改为运行时申请
mPromoteSystemApps =
mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;

// Android N升级上来的版本，需要像首次启动一样处理包提取，因为没有可用的分析数据
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 的缓存
mCacheDir = preparePackageParserCache(mIsEngBuild);

// 设定 flag，当扫描安装文件夹时不改变 apk 路径
int scanFlags = SCAN_BOOTING | SCAN_INITIAL;

// 收集 vendor/product/system_ext overlay packages.
for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
final ScanPartition partition = mDirsToScanAsSystem.get(i);
if (partition.getOverlayFolder() == null) {
continue;
}
// 扫描 overlay… 等等文件夹内的 apk
scanDirTracedLI(partition.getOverlayFolder(), systemParseFlags,
systemScanFlags | partition.scanFlag, 0,
packageParser, executorService);
}

// 扫描 framework 文件夹内的 apk
scanDirTracedLI(frameworkDir, systemParseFlags,
systemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0,
packageParser, executorService);

// 判断安装包是否是 android
if (!mPackages.containsKey("android")) {
throw new IllegalStateException(
"Failed to load frameworks package; check log for warnings");
}

for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) {
final ScanPartition partition = mDirsToScanAsSystem.get(i);
if (partition.getPrivAppFolder() != null) {
// 扫描 priv-app 文件夹
scanDirTracedLI(partition.getPrivAppFolder(), systemParseFlags,
systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0,
packageParser, executorService);
}
// 扫描 /system/app 文件夹
scanDirTracedLI(partition.getAppFolder(), systemParseFlags,
systemScanFlags | partition.scanFlag, 0,
packageParser, executorService);
}

...

if (!mOnlyCore) {
// do this first before mucking with mPackages for the "expecting better" case
final int numPackages = mPackages.size();
for (int index = 0; index < numPackages; index++) {
final AndroidPackage pkg = mPackages.valueAt(index);
if (pkg.isStub()) {
stubSystemApps.add(pkg.getPackageName());
}
}

// 倒序扫描所有应用
for (int index = packageSettings.size() - 1; index >= 0; index--) {
final PackageSetting ps = packageSettings.valueAt(index);

// 如果包有 FLAG_SYSTEM 忽略
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
continue;
}
/*
* If the package is scanned, it's not erased.
*/
final AndroidPackage scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
//若在disabled packages list，添加进
// via OTA，再将其移除
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
...
//将系统 App 的 PackageSetting 从 PKMS 中 mPackage 移除
removePackageLI(scannedPkg, true);

// 将升级包的路径添加到 mExpectingBetter 列表中
mExpectingBetter.put(ps.name, ps.getPath());
}
continue;
}

if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
logCriticalInfo(Log.WARN, "System package " + ps.name
+ " no longer exists; it's data will be wiped");
// 系统 APP 将不存在，移除该 APP 的数据
removePackageDataLIF(ps, userIds, null, 0, false);
} else {
// we still have a disabled system package, but, it still might have
// been removed. check the code path still exists and check there's
// still a package. the latter can happen if an OTA keeps the same
// code path, but, changes the package name.
final PackageSetting disabledPs =
mSettings.getDisabledSystemPkgLPr(ps.name);

if (disabledPs.getPath() == null || !disabledPs.getPath().exists()
|| disabledPs.pkg == null) {
// 该系统 APP 在 isDisabledSystemPackage 中，并且没有发现升级包
possiblyDeletedUpdatedSystemApps.add(ps.name);
} else {
// We're expecting that the system app should remain disabled, but add
// it to expecting better to recover in case the data version cannot
// be scanned.
mExpectingBetter.put(disabledPs.name, disabledPs.getPath());
}
}
}
}

...

}

}

}

扫描升级系统 APP - system 文件夹

目前阶段（BOOT_PROGRESS_PMS_SYSTEM_SCAN_START）主要是扫描 /system 文件夹：这个目录下文件夹都如何规划放置
Android 系统架构有分为应用层、应用框架层、系统运行层、硬件抽象层、内核层

system 内文件夹 | 放置内容 | 补充
app | 系统 app | 包括 google 内置、手机厂商 app
framework | 应用框架 jar 包 | 主要放 jar 包、vdex
priv-app | 特权 app |
lib | 放置动态 so 文件 |
fonts | 系统字体 | 多是 ttf 档
media | 系统音效 | 像是铃声、提示音、系统启动动画

第二个目的是扫描系统文件并处理，处理的 重点是 ==OTA 升级 ==，系统会将可升级的系统应用标记为 DisabledSystemPackage，并且有 3 种状况
系统 APP 有更新：透过 removePackageLI 将系统 App 的 PackageSetting 从 PKMS 中 mPackage 移除，并 添加到 mExpectingBetter 列表
系统 APP 被移除：透过 removePackageDataLIF 移除系统 APP 数据
没有升级包：系统应用为 DisabledSystemPackage，但没有发现升级包，代表代表系统升级包 可能 被删除

第三阶段 - BOOT_PROGRESS_PMS_DATA_SCAN_START

BOOT_PROGRESS_PMS_DATA_SCAN_START：主要会 扫描 /data 文件夹
扫描处理、更新 /data 目录的应用信息（也会及时移除不需要的数据）
处理上一步遗留的 possiblyDeletedUpdatedSystemApps 列表

如果无法从 mPackage 中取得 Package 则会删除该 APP

如果可以取得 Package 但不是系统 APP，并且会做以下这些事情

移除 System 权限

移除 Package

重新扫描 Package 路径的 APK
扫描 mExpectingBetter 列表

取得系统 APP 升级包的路径，并且会做以下这些事情

根据系统 APP 所在的目录设定扫描的解析参数

将 PackageName 设定给mSetting#mPackages中（removeDisabledSystemPackageLPw 方法）

清除 mExpectingBetter 列表

Copy
// PackageManagerService.java

private final File mAppInstallDir;

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
final String buildFingerprint, final boolean isEngBuild,
final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

...

// 取得 /data/app 资料夾
mAppInstallDir = new File(Environment.getDataDirectory(), "app");

// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
// writer
synchronized (mLock) {

...

if (!mOnlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());

// 扫描 /data/app文件夹
scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0,
packageParser, executorService);
}

// 关闭 Parser 流（解析 Package xml 的流）
packageParser.close();

// 关闭 Executor 的全部任务
List<Runnable> unfinishedTasks = executorService.shutdownNow();
if (!unfinishedTasks.isEmpty()) {
throw new IllegalStateException("Not all tasks finished before calling close: "
+ unfinishedTasks);
}

if (!mOnlyCore) {
// 2. 扫描上一步所遗留的 APP 包（倒序）

for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) {
final String packageName = possiblyDeletedUpdatedSystemApps.get(i);
final AndroidPackage pkg = mPackages.get(packageName);
final String msg;

// 从禁用系统列表（mDisabledSystemPackage）中移除
mSettings.removeDisabledSystemPackageLPw(packageName);

if (pkg == null) {
// 应该要找到升级包，但没找到（移除该APP）
msg = "Updated system package " + packageName
+ " no longer exists; removing its data";
// (实际上并非马上移除)
} else {

// 如果有取到pkg，代表该APP存在Data区中，
// 不属于System app，移除系统权限
msg = "Updated system package " + packageName
+ " no longer exists; rescanning package on data";
// 以下，删除并重新扫描数据包
removePackageLI(pkg, true); // 删除
try {
final File codePath = new File(pkg.getPath());
// 重新扫描
scanPackageTracedLI(codePath, 0, scanFlags, 0, null);
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse updated, ex-system package: "
+ e.getMessage());
}
}

// 如果我们还有一个包设置[ie.它是以前扫描并为系统所知]
// 但是，我们没有该Pkg [即。从/data扫描它时出错
// partition]，彻底删除包数据。
final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null && mPackages.get(packageName) == null) {
// 移除 data 内出错的数据包
removePackageDataLIF(ps, userIds, null, 0, false);
}
logCriticalInfo(Log.WARN, msg);

}

// 3. 遍历 mExpectingBetter 列表
for (int i = 0; i < mExpectingBetter.size(); i++) {
final String packageName = mExpectingBetter.keyAt(i);
if (!mPackages.containsKey(packageName)) {
// 取得系统 APP 升级包的路径
final File scanFile = mExpectingBetter.valueAt(i);

for (int i1 = mDirsToScanAsSystem.size() - 1; i1 >= 0; i1--) {
final ScanPartition partition = mDirsToScanAsSystem.get(i1);
// 根据系统 APP 所在的目录设定扫描的解析参数
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;
}
}
if (rescanFlags == 0) {
Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
continue;
}

//将PackageName对应的包设置数据（PackagesSetting）
//添加到mSetting的mPackages中
mSettings.enableSystemPackageLPw(packageName);

try {
// 扫描系统 APP 的升级包
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 */
}
}

//解压&安装根系统应用
//该操做要确保最后执行，来确保所有存根被替代or禁用
// Stub（存根）
installSystemStubPackages(stubSystemApps, scanFlags);

...
}

// 清除升级列表
mExpectingBetter.clear();

// 取得 Storage manage 包名
mStorageManagerPackage = getStorageManagerPackageName();

// 解决保护 action 过滤器，只允许 setup wizard 为这些 action 有最高权限的过滤
mSetupWizardPackage = getSetupWizardPackageNameImpl();

...

// 读取并更新要保留的 package 的上次使用时间
mPackageUsage.read(packageSettings);
mCompilerStats.read();

}
}

scanDirTracedLI - 分析 data 目录內容

/data 文件夹可成为 Data 分区，它个主用公用有两个
储存所有用户的 个人数据
储存所有用户的 配置文件
接着来看 /data 目录下的子目录都放那些数据

/data 底下目录 | 含意
app | 储存该收机装置，自己安装的 APP 应用
data | 储存所有已安装的 APP 数据，其中也包括 System APP 数据
app-private | APP 的私有儲存空間
app-lib | 储存所有 APP 的 JNI Lib
system | 存放系统配置文件
anr | 用于存放 ANR 发生时，系统生成的 traces.text 文件

第四階段 - BOOT_PROGRESS_PMS_SCAN_END

BOOT_PROGRESS_PMS_SCAN_END 阶段 升级后首次启动，要清除不必要的缓存数据、权限，更新 package.xml 档案 （packages.xml 用来储存所有 APP 的信息）
SDK 版本更变，重新更新权限
OTA 升级后首次启动，清除不要要缓存
OTA 英文全称是 Over-the-Air Technology ，即空间下载技术，是手机通过行动网络对手机系统，应用程序进行管理的技术
权限更新完成后清理相关数据
透过 mSetting 的内容保存并更新 package.xml 文件，这样以后 PKMS 创建时就会读取到新的 Setting

Copy
// PackageManagerService.java

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
final String buildFingerprint, final boolean isEngBuild,
final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

...

// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
// writer
synchronized (mLock) {

...

// 进入第四阶段
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());

// 权限重制
mPermissionManager.onStorageVolumeMounted(
StorageManager.UUID_PRIVATE_INTERNAL, mIsUpgrade);
ver.sdkVersion = mSdkVersion;

// 如果是第一次启动或从pre-M升级上来，并且是正常启动，那我们需要初始化User定义的首选预设应用
if (!mOnlyCore && (mPromoteSystemApps || mFirstBoot)) {
for (UserInfo user : mInjector.getUserManagerInternal().getUsers(true)) {
mSettings.applyDefaultPreferredAppsLPw(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;
}

...

// 在 OTA 升级成功后的首次启动，不必要的缓存，但不清除应用程序的配置文件
if (mIsUpgrade && !mOnlyCore) {
Slog.i(TAG, "Build fingerprint changed; clearing code caches");
for (int i = 0; i < packageSettings.size(); i++) {
final PackageSetting ps = packageSettings.valueAt(i);
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
// 没有应用会在这时启动，所以不必冻结
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;
}

// 在Launcher中隐藏他们的icon（Android-Q之前的非系统应用）
if (!mOnlyCore && mIsPreQUpgrade) {
Slog.i(TAG, "Whitelisting all existing apps to hide their icons");
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);
}
}
// clear only after permissions and other defaults have been updated
mPromoteSystemApps = false;

// 所有的改变都在扫描中完成
ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;

// 更新 package.xml
t.traceBegin("write settings");
writeSettingsLPrTEMP();
t.traceEnd();

...

}

}
}

第五阶段 - BOOT_PROGRESS_PMS_READY

BOOT_PROGRESS_PMS_READY：PKMS 最后阶段
PackageInstallerService 用于管理安装 Session 服务，每次安装过程都会分配一个 SessionId
要求触发 GC 回收内存

Copy
// PackageManagerService.java
public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
final String buildFingerprint, final boolean isEngBuild,
final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

...

// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
// writer
synchronized (mLock) {

...

EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());

...

// PermissionController 是一个系统核心，预设同意&管理权限
mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr();

... 省略部分

// 取得安装器服务
mInstallerService = mInjector.getPackageInstallerService();

...

// 读取&更新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);
if (mIsUpgrade) {
FrameworkStatsLog.write(
FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,
BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME,
SystemClock.uptimeMillis() - startTime);
}

// 属性被重构后，重构 live computer
mLiveComputer = createLiveComputer();

}

}

...

// 在打开应用 zip 后，确保他们都刷新，并进行 GC 回收
VMRuntime.getRuntime().requestConcurrentGC();

mInstaller.setWarnIfHeld(mLock);

...
}