PackageManagerServices(程序包管理服务)是安卓系统核心服务之一,简称PMS,在安卓系统中负责管理应用,常见的比如安装、卸载应用等,本章将结合安卓11源码梳理PMS相关流程。
1、启动PMS服务
PMS作为系统核心服务之一,其启动流程位于frameworks/base/services/java/com/android/server/SystemServer.java
,相关代码如下:
// 在startBootstrapServices下启动PMS
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
// 启动installer,该服务会创建具有适当权限的关键目录,如/data/user
// installer服务必须在其他服务启动之前启动
t.traceBegin("StartInstaller");
Installer installer = mSystemServiceManager.startService(Installer.class);
t.traceEnd();
...
// 启动PMS
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");
}
}
// 在startOtherServices下确保PMS启动完成
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
t.traceBegin("MakePackageManagerServiceReady");
mPackageManagerService.systemReady();
t.traceEnd();
}
2、PMS启动流程
PMS在SystemServer.java
中被启动后,会前往 frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
中继续其启动流程,PMS的Main函数如下:
public static PackageManagerService main(Context context, Installer installer,@NonNull DomainVerificationService domainVerificationService, boolean factoryTest,boolean onlyCore) {
// 检查初始化配置
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),
// 初始化Settings对象
(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()),
...
}
PMS的构造方法代码较多,可以分为5个阶段:
2.1、 PMS_START阶段
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());
...
// 创建Settings对象
mSettings = injector.getSettings();
...
// 调用addSharedUserLPw函数添加共享ID
t.traceBegin("addSharedUsers");
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);
t.traceEnd();
}
总体来说,PMS_START阶段可以分为以下几个部分
- 获取Settings类,这个类在Android中是在PMS的Main函数下初始化的,Settings的具体构造函数如下:
Settings(File dataDir, RuntimePermissionsPersistence runtimePermissionsPersistence,
LegacyPermissionDataProvider permissionDataProvider,
@NonNull DomainVerificationManagerInternal domainVerificationManager,
@NonNull PackageManagerTracedLock lock) {
...
// 创建/data/system文件夹
mSystemDir = new File(dataDir, "system");
mSystemDir.mkdirs();
// 设置文件夹权限
FileUtils.setPermissions(mSystemDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1, -1);
mSettingsFilename = new File(mSystemDir, "packages.xml");
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
mPackageListFilename = new File(mSystemDir, "packages.list");
FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);
final File kernelDir = new File("/config/sdcardfs");
mKernelMappingFilename = kernelDir.exists() ? kernelDir : null;
// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
mDomainVerificationManager = domainVerificationManager;
registerObservers();
mSnapshot = makeCache();
}
在/data/system
目录下存在以下5个文件:
文件 | 功能 |
---|---|
packages.xml | 记录所有安装app的信息 |
packages-backup.xml | 备份文件 |
packages-stopped.xml | 记录系统被强制停止的文件 |
packages-stopped-backup.xml | 备份文件 |
packages.list | 记录应用的数据信息 |
- 向Settings中添加信息
- 获取系统配置信息,包括全局属性、groupid以及系统权限。将一些类进行绑定,包括:PackageDexOptimizer (dex优化工具类) 、 DexManager(dex管理类)、PackageHandler(建立package相关操作的消息循环)等
- 创建data下的各种目录
2.2、 PMS_SYSTEM_SCAN_START阶段
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_SYSTEM_SCAN_START, startTime);
// 读取环境变量BOOTCLASSPATH,用于之后的类加载和优化
final String bootClassPath = System.getenv("BOOTCLASSPATH");
final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
...
// 在system/下创建framework目录
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
...
// 在扫描APK之前准备APEX包信息
mApexManager.scanApexPackagesTraced(packageParser, executorService);
// 在vendor/product/system_ext分区的收集包名
for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
final ScanPartition partition = mDirsToScanAsSystem.get(i);
if (partition.getOverlayFolder() == null) {
continue;
}
scanDirTracedLI(partition.getOverlayFolder(), systemParseFlags,systemScanFlags | partition.scanFlag, 0,packageParser, executorService);
}
可以看出,这里的主要工作是对系统区进行扫描,扫描顺序是OverlayFolder -> frameworkDir -> PrivAppFolder -> AppFolder(), 这里主要操作如下:
- 扫描各个系统分区的的App
- 解析系统App信息
- 把解析结果存储起来,存储在PMS的相关属性和mSettings里
2.3、 PMS_DATA_SCAN_START阶段
这里就是对/data/app进行了扫描,主要工作与扫描系统App目录是一样的,只是细节处理上有些不同。除此之外还做了一些收尾工作。
/*
* Make sure all system apps that we expected to appear on
* the userdata partition actually showed up. If they never
* appeared, crawl back and revive the system version.
*/
for (int i = 0; i < mExpectingBetter.size(); i++) {
final String packageName = mExpectingBetter.keyAt(i);
if (!mPackages.containsKey(packageName)) {
final File scanFile = mExpectingBetter.valueAt(i);
logCriticalInfo(Log.WARN, "Expected better " + packageName
+ " but never showed up; reverting to system");
@ParseFlags int reparseFlags = 0;
@ScanFlags int rescanFlags = 0;
for (int i1 = mDirsToScanAsSystem.size() - 1; i1 >= 0; i1--) {
final ScanPartition partition = mDirsToScanAsSystem.get(i1);
if (partition.containsPrivApp(scanFile)) {
reparseFlags = systemParseFlags;
rescanFlags = systemScanFlags | SCAN_AS_PRIVILEGED
| partition.scanFlag;
break;
}
if (partition.containsApp(scanFile)) {
reparseFlags = systemParseFlags;
rescanFlags = systemScanFlags | partition.scanFlag;
break;
}
}
if (rescanFlags == 0) {
Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
continue;
}
```
// 将packageName对应的包设置数据(PackageSetting)添加到mSettings的mPackages中
mSettings.enableSystemPackageLPw(packageName);
try {
```
// 扫描系统App的升级包
scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse original system package: "
+ e.getMessage());
}
}
}
2.4、 PMS_SCAN_END阶段
这里主要做了如下几件事情:
1.如果SDK版本发生了变化(升级系统),重新对App进行授权
2.为系统核心服务准备存储空间
3.如果是升级后第一次正常启动,需要清除代码缓存,但不是会清除应用的配置文件
4.把更新后的信息写回对应的xml文件中
// 打印相关日志
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,SystemClock.uptimeMillis());
Slog.i(TAG, "Time to scan packages: "+ ((SystemClock.uptimeMillis()-startTime)/1000f)+ " seconds");
// 如果SDK版本发生了变化(升级系统),重新对App进行授权
final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion);
if (sdkUpdated) {
Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
+ mSdkVersion + "; regranting permissions for internal storage");
}
mPermissionManager.updateAllPermissions(
StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated);
ver.sdkVersion = mSdkVersion;
// 如果是首次启动或者从6.0以前的系统升级,初始化用户首选App
if (!mOnlyCore && (mPromoteSystemApps || mFirstBoot)) {
for (UserInfo user : mInjector.getUserManagerInternal().getUsers(true)) {
mSettings.applyDefaultPreferredAppsLPw(user.id);
primeDomainVerificationsLPw(user.id);
}
}
2.5、 PMS_READY阶段
这里又对一些属性进行了赋值。
// Initialize InstantAppRegistry's Instant App list for all users.
final int[] userIds = UserManagerService.getInstance().getUserIds();
for (AndroidPackage pkg : mPackages.values()) {
if (pkg.isSystem()) {
continue;
}
for (int userId : userIds) {
final PackageSetting ps = getPackageSetting(pkg.getPackageName());
if (ps == null || !ps.getInstantApp(userId) || !ps.getInstalled(userId)) {
continue;
}
mInstantAppRegistry.addInstantAppLPw(userId, ps.appId);
}
}
// Prepare a supplier of package parser for the staging manager to parse apex file
// during the staging installation.
final Supplier<PackageParser2> apexParserSupplier = () -> new PackageParser2(
mSeparateProcesses, mOnlyCore, mMetrics, null /* cacheDir */,
mPackageParserCallback);
mInstallerService = new PackageInstallerService(mContext, this, apexParserSupplier);
final Pair<ComponentName, String> instantAppResolverComponent =
getInstantAppResolverLPr();
if (instantAppResolverComponent != null) {
if (DEBUG_INSTANT) {
Slog.d(TAG, "Set ephemeral resolver: " + instantAppResolverComponent);
}
mInstantAppResolverConnection = new InstantAppResolverConnection(
mContext, instantAppResolverComponent.first,
instantAppResolverComponent.second);
mInstantAppResolverSettingsComponent =
getInstantAppResolverSettingsLPr(instantAppResolverComponent.first);
} else {
mInstantAppResolverConnection = null;
mInstantAppResolverSettingsComponent = null;
}
updateInstantAppInstallerLocked(null);
// 读取并更新dex文件的使用情况
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);
}
} // synchronized (mLock)
} // synchronized (mInstallLock)
// CHECKSTYLE:ON IndentationCheck
mModuleInfoProvider = new ModuleInfoProvider(mContext, this);
// Uncork cache invalidations and allow clients to cache package information.
PackageManager.uncorkPackageInfoCache();
t.traceBegin("GC");
Runtime.getRuntime().gc();
t.traceEnd();
mInstaller.setWarnIfHeld(mLock);
PackageParser.readConfigUseRoundIcon(mContext.getResources());
mServiceStartWithDelay = SystemClock.uptimeMillis() + (60 * 1000L);
以上就是对PMS的启动总体流程做了大致的梳理,其中一些值得关注的细节将在之后的文章中逐一介绍和分析。