PackageManagerService的启动过程——Android 12(一)
目录
2.1 SystemServer.startBootstrapServices()
2.2 PackageManagerService.main()
2.3.1 PKMS构造函数BOOT_PROGRESS_PMS_START阶段
2.3.2 PKMS构造函数BOOT_PROGRESS_PMS_SYSTEM_SCAN_START 阶段
2.3.3 PKMS构造函数BOOT_PROGRESS_PMS_DATA_SCAN 阶段
2.3.4 PKMS构造函数BOOT_PROGRESS_PMS_READY阶段
2.4 PKMS.installWhitelistedSystemPackages()
1. PackageManagerService概述
1.1 PackageManagerService职责
PackageManagerService(简称PKMS)的官方解释:随时随地跟踪所有的APKs。主要职责分为:
- 启动过程中扫描App所有安装目录,解析其中的Apk将相关信息加载到PKMS的数据结构中,同时同步到/data/system/packages.xml中;注册APK信息和其四大组件到PKMS中。
- 负责App的安装和卸载。
- 对外提供接口查询App相关信息。
1.2 PKMS内部三把重要的锁
mLock:用来守护内存中解析的package详情和其他相关状态。这是一个细粒度的锁,只应该短暂持有,因为它是系统中竞争最激烈的锁之一。
mInstallLock :用来守护所有对installd的访问,其操作通常涉及到磁盘上应用数据繁重的读写操作。由于installd是单线程,它的操作经常会很慢,因此在持有该锁的情况下不能再获取该锁。相反,在持有该锁时如果短暂获取mLock锁时安全的。(关于installd请参考)
mSnapshotLock : 用来守护对两个snapshot字段的访问:snapshot本身和snapshot 失效标志。当持有mLock锁时不能获取该锁,相反,在持有mSnapshotLock锁时暂时获取mLock锁是安全的。
final PackageManagerTracedLock mLock;
final Object mInstallLock;
private final Object mSnapshotLock = new Object();
1.3 PKMS在SystemServer中全部业务
PKMS在SystemServer.startBootstrapService()中调用PKMS.main()启动PKMS;如果设备没加密,则管理A/B OTA dexopting;
在SystemServer.startOtherServices()中,如果设备没加密,调用PKMS.updatePackagesIfNeeded()完成dex优化;调用PKMS.performFstrimIfNeeded()完成磁盘维护;最后调用PKMS.systemReady()服务启动就绪;最后调用PKMS.waitForAppDataPrepared()等待所有package准备就绪,整个过程如下图所示:
主要涉及的文件有:
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java,代码参考地址:PackageManagerService.java
/frameworks/native/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl,代码参考地址:IPackageManagerNative.aidl
/frameworks/base/core/java/android/content/pm/IPackageManager.aidl,代码参考地址:IPackageManager.aidl
2. PKMS的启动
2.1 SystemServer.startBootstrapServices()
public final class SystemServer implements Dumpable {
private PackageManagerService mPackageManagerService;
private PackageMamager mPackageManager;
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
t.traceBegin("StartPackageManagerService");
try {
Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
domainVerificationService, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF,
mOnlyCore);
} finally {
Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
}
//既然package manager已经启动.注册dex load report来捕获system server加载的dex文件,
//这些dex文件会被BackgroundDexOptService优化.
SystemServerDexLoadReporter.configureSystemServerDexReporter(mPackageManagerService);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
t.traceEnd();
...
}
}
2.2 PackageManagerService.main()
如果设备加密,则运行core应用,即onlyCore=true,主要工作有:
- 创建Injector实例
- 创建PKMS实例,安装白名单
- 把PKMS注册到ServiceManager
- 创建PKMNative实例,并注册到ServiceManager中
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender, TestUtilityService {
public static PackageManagerService main(Context context, Installer installer,
@NonNull DomainVerificationService domainVerificationService, boolean factoryTest,
boolean onlyCore) {
...
//1.创建PKMS实例
PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest,
Build.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG, Build.VERSION.SDK_INT,
Build.VERSION.INCREMENTAL);
...
//2.安装白名单
m.installWhitelistedSystemPackages();
//3.把PKMS注册到ServiceManager中
ServiceManager.addService("package", m);
//创建PKMNative实例
final PackageManagerNative pmn = m.new PackageManagerNative();
3.把PKMNative注册到ServiceManager中
ServiceManager.addService("package_native", pmn);
return m;
}
}
2.3 PackageManagerService构造函数
PKMS的构造函数非常复杂,包含四个过程:
- 第一阶段:BOOT_PROGRESS_PMS_START,初始化PKMS中重要的成员变量,其中包括构建Settings和SystemConfig对象。
- 第二阶段:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,扫描系统App目录
- 第三阶段:该阶段包含两部分:BOOT_PROGRESS_PMS_DATA_START和BOOT_PROGRESS_PMS_DATA_END,START阶段负责扫描Data分区,END阶段扫描结束做相关收尾工作,其中包含清除缓存和更新Settings。
- 第四阶段:BOOT_PROGRESS_PMS_READY,PMS准备就绪阶段,管理安装会话服务和请求GC。
2.3.1 PKMS构造函数BOOT_PROGRESS_PMS_START阶段
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender, TestUtilityService {
private final PackageManagerInternal mPmInternal;
private final ComponentResolver mComponentResolver;
private final PermissionManagerServiceInternal mPermissionManager;
final Settings mSettings;
private final PackageDexOptimizer mPackageDexOptimizer;
private final DexManager mDexManager;
public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
final String buildFingerprint, final boolean isEngBuild,
final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {
//1.从Injector中初始化获取锁对象
mLock = injector.getLock();
mInstallLock = injector.getInstallLock();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, SystemClock.uptimeMillis());
//2.保存Display分辨率相关对象
mMetrics = injector.getDisplayMetrics();
//3.与apk安装和dex优化相关的对象
mInstaller = injector.getInstaller();
//4.暴露PKMS本地服务给系统使用
mPmInternal = new PackageManagerInternalImpl();
//5.用户管理对象
mUserManager = injector.getUserManagerService();
//6.组件解析对象
mComponentResolver = injector.getComponentResolver();
//7.权限管理对象
mPermissionManager = injector.getPermissionManagerServiceInternal();
//8.设置相关对象
mSettings = injector.getSettings();
...
t.traceBegin("addSharedUsers");
//9.添加system/phone/log/nfc/bluetooth/shell/se/networkstack/uwb这9种shareUserId到 mSettings
mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
...
t.traceEnd();
//Dex优化相关
mPackageDexOptimizer = injector.getPackageDexOptimizer();
mDexManager = injector.getDexManager();
//ART虚拟机管理
mArtManagerService = injector.getArtManagerService();
//获取默认分辨率
mContext.getSystemService(DisplayManager.class)
.getDisplay(Display.DEFAULT_DISPLAY).getMetrics(mMetrics);
//创建SystemConfig实例,获取设备可用的features.
SystemConfig systemConfig = injector.getSystemConfig();
mAvailableFeatures = systemConfig.getAvailableFeatures();
//data/app目录
mAppInstallDir = new File(Environment.getDataDirectory(), "app");
//获取SystemConfig的共享库
ArrayMap<String, SystemConfig.SharedLibraryEntry> libConfig = systemConfig.getSharedLibraries();
SELinuxMMAC.readInstallPolicy();
mPermissionManager.readLegacyPermissionsTEMP(mSettings.mPermissions);
mFirstBoot = !mSettings.readLPw(mInjector.getUserManagerInternal().getUsers(true, false, true);
mPermissionManager.readLegacyPermissionsTEMP(mSettings.mPermissions);
...
}
}
2.3.2 PKMS构造函数BOOT_PROGRESS_PMS_SYSTEM_SCAN_START 阶段
这个阶段主要工作:
- 获取环境变量和/system/framework目录
- 扫描system/vendor/product/odm/oem等目录的priv-app、app、overlay包;
- 清除安装时临时文件以及其他不必要的信息
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender, TestUtilityService {
public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
final String buildFingerprint, final boolean isEngBuild,
final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {
...
synchronized (mInstallLock) {
synchronized (mLock) {
...
long startTime = SystemClock.uptimeMillis();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START, startTime);
//获取环境变量
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();
//接下来就是扫描system/vendor/product/odm/oem等目录的priv-app、app、overlay包;
//清除安装时临时文件以及其他不必要的信息
...
}
}
...
}
}
系统App安装目录常见的有:
/system/app | 系统app,不能被普通用户卸载的app |
/system/priv-app | 系统核心app,权限更大 |
/vendor/app | OEM/ODM厂商预置的系统app |
/vendor/priv-app | OEM/ODM厂商预置的系统app |
普通用户自己安装的App在/data/app目录下。
2.3.3 PKMS构造函数BOOT_PROGRESS_PMS_DATA_SCAN 阶段
该阶段包含START和END,在START阶段:扫描Data分区(它用来存储所有用户的个人数据和配置文件),更新和去除不必要的数据。在END阶段根据是否是OTA升级后的首次启动,清除缓存数据,把Settings的内容保存到package.xml中。
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender, TestUtilityService {
public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
final String buildFingerprint, final boolean isEngBuild,
final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {
...
synchronized (mInstallLock) {
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);
}
...
final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null && mPackages.get(packageName) == null) {
removePackageDataLIF(ps, userIds, null, 0, false);
}
//安装存根系统应用程序
installSystemStubPackages(stubSystemApps, scanFlags);
installSystemStubPackages(stubSystemApps, scanFlags);
mStorageManagerPackage = getStorageManagerPackageName();
mSetupWizardPackage = getSetupWizardPackageNameImpl();
//默认文本分类器package
mDefaultTextClassifierPackage = getDefaultTextClassifierPackageName();
//系统文本分类器package
mSystemTextClassifierPackageName = getSystemTextClassifierPackageName();
mDocumenterPackage = getDocumenterPackageName();//文档的package
mConfiguratorPackage = getDeviceConfiguratorPackageName();//设备配置package
//使所有客户端都能访问共享库路径
updateAllSharedLibrariesLocked(null, null, Collections.unmodifiableMap(mPackages));
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END, SystemClock.uptimeMillis());
...
}
}
...
}
}
下面列出Data分区部分子目录:
/data/app | 存储用户自己安装的app |
/data/data/ | 存储已安装app的数据目录 |
/data/app-private | App的私有存储空间 |
/data/app-lib | 存储所有app的Jni库 |
/data/system | 存放系统配置文件 |
/data/anr | 存储ANR时的traces文件 |
mSettings.readLPw()会扫描下面5个文件
1. "/data/system/packages.xml" 所有安装app信息,包括系统permissions、apk的name、codePath、version等通过AndroidManifest.xml解析的内容。
2. "/data/system/packages-backup.xml" 所有安装app信息之备份的信息记录
3. "/data/system/packages.list" 所有安装app信息
4. "/data/system/packages-stopped.xml" 所有强制停止app信息
5. "/data/system/packages-stopped-backup.xml" 所有强制停止app信息之备份的信息记录。其中packages-backup.xml和packages-stopped-backup.xml文件是在写对应文件之前,会先备份,如果写成功会把备份文件删除。
5个文件共分为三组,简单的作用描述如下:
packages.xml:PKMS扫描完目标文件夹后会创建该文件。当系统进行程序安装、卸载和更新等操作时,均会更新该文件。该文件保存了系统中与package 相关的一些信息。
packages.list:描述系统中存在的所有APK的信息。当这些程序有变动时,PKMS就会更新该文件。packages-stopped.xml:从系统自带的设置程序中进入应用程序页面,然后在选择强制停止 (ForceStop)某个应用时,系统会将该应用的相关信息记录到此文件中。也就是该文件保存系统中被用户强制停止的Package的信息。
2.3.4 PKMS构造函数BOOT_PROGRESS_PMS_READY阶段
这个阶段的主要工作包括:管理安装会话服务和请求GC等。
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender, TestUtilityService {
public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
final String buildFingerprint, final boolean isEngBuild,
final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {
...
synchronized (mInstallLock) {
synchronized (mLock) {
...
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis());
//管理安装会话的服务
mInstallerService = mInjector.getPackageInstallerService();
final ComponentName instantAppResolverComponent = getInstantAppResolverLPr();
...
updateInstantAppInstallerLocked(null);
...
VMRuntime.getRuntime().requestConcurrentGC();//请求GC
}
}
...
}
}
2.4 PKMS.installWhitelistedSystemPackages()
安装白名单中的系统App。
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender, TestUtilityService {
/** Install/uninstall system packages for all users based on their user-type, as applicable. */
private void installWhitelistedSystemPackages() {
synchronized (mLock) {
final boolean scheduleWrite = mUserManager.installWhitelistedSystemPackages(
isFirstBoot(), isDeviceUpgrading(), mExistingPackages);
if (scheduleWrite) {
scheduleWritePackageRestrictionsLocked(UserHandle.USER_ALL);
scheduleWriteSettingsLocked();
}
}
}
}
}
2.5 PackageManagerNative类
PackageManagerNative是PKMS的内部类,extends IPackageManagerNative.Stub,主要用来与native层通过AIDL通信。
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender, TestUtilityService {
private class PackageManagerNative extends IPackageManagerNative.Stub {
@Override
public String[] getAllPackages() {
return PackageManagerService.this.getAllPackages().toArray(new String[0]);
}
...
}
}