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。
@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 通信
// 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 就是在这里启动
// 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 服务,之后会用这个服务来安装所有应用
// SystemServer.java
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
... 省略部分
Installer installer = mSystemServiceManager.startService(Installer.class);
... 省略部分
}
VoldProperties#decrypt
判断手机装置是否加密(读取 init.rc
档的设定),mOnlyCore = true
代表只运行核心程序。
// 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 对象
// 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
方法
// 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 优化
// SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
... 省略部分
try {
mPackageManagerService.performFstrimIfNeeded();
} ...
... 省略部分
}
PKMS 准备就绪调用 systemReady,加载预设权限
PKMS 分析#
PKMS main
#
透过PackageManagerService#main
方法就可以创建 PackageManagerService 物件,并且将 PKMS 透过 package、package_native 添加到 ServiceManager 中
// 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;
}
// 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 优化)… 详细请看注释
// 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
类提供
// 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 类 的构造函数会创建所需文件 & 文件夹,并设定它们的权限
// 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 |
// 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 列表之后判断 |
// 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 中
// 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
// 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 是系统型态、使用者型态 |
// 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
列表
// 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
// 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
// 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 进行分析
// 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 列表
// 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
// 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 回收内存
// 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);
...
}