一、简介
PackageManagerService(简称 PMS),是 Android 系统核心服务之一,处理包管理相关的工作,常见的比如安装、卸载应用等。本章针对SyetemServer、PMS构造方法重点模块解析
二、SystemServer.java
PMS是在SystemServer中启动,所有我们从SystemServer为入口进行解析:
frameworks/base/services/java/com/android/server/SystemServer.java
2.1 main
|
2.2 run
private void run() {
...
//SYSTEM_SERVER_START
EventLog.writeEvent(EventLogTags.SYSTEM_SERVER_START,
mStartCount, mRuntimeStartUptime, mRuntimeStartElapsedTime);
// Start services.
try {
t.traceBegin("StartServices");
//启动引导服务【见1.3】
startBootstrapServices(t);
//启动核心服务
startCoreServices(t);
//启动其他服务
startOtherServices(t);
startApexServices(t);
// Only update the timeout after starting all the services so that we use
// the default timeout to start system server.
updateWatchdogTimeout(t);
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
t.traceEnd(); // StartServices
}
...
}
2.3 startBootstrapServices
private void startBootstrapServices() {
…
//启动installer服务,负责package安装、删除、迁移、更新的系统服务
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);
} finally {
Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
}
//mFirstBoot是后续WMS创建时所需要的参数,系统服务之间是有依赖关系的,它们的启动顺序不能随意被更改。
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
t.traceEnd();
...
}
private void startOtherServices() {
...
t.traceBegin("MakePackageManagerServiceReady");
mPackageManagerService.systemReady();
t.traceEnd();
…
}
三、PackageManagerService.Java
3.1 main
main方法主要做了两件事,一个是创建PMS对象,另一个是将PMS注册到ServiceManager中。
public static PackageManagerService main(Context context,
Installer installer, @NonNull DomainVerificationService domainVerificationService,
boolean factoryTest) {
// Self-check for initial settings.
//自检初始设置
PackageManagerServiceCompilerMapping.checkProperties();
final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
Trace.TRACE_TAG_PACKAGE_MANAGER);
t.traceBegin("create package manager");
final PackageManagerTracedLock lock = new PackageManagerTracedLock();
final Object installLock = new Object();
HandlerThread backgroundThread = new ServiceThread("PackageManagerBg",
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
backgroundThread.start();
Handler backgroundHandler = new Handler(backgroundThread.getLooper(),
BACKGROUND_HANDLER_CALLBACK);
//injector里面会初始化Settings、PackageDexOptimizer、DexManager等,后面需要用到
PackageManagerServiceInjector injector = new PackageManagerServiceInjector(
context, lock, installer, installLock, new PackageAbiHelperImpl(),
backgroundHandler,
SYSTEM_PARTITIONS,
(i, pm) -> new ComponentResolver(i.getUserManagerService(), pm.mUserNeedsBadging),
(i, pm) -> PermissionManagerService.create(context,
i.getSystemConfig().getAvailableFeatures()),
(i, pm) -> new UserManagerService(context, pm,
new UserDataPreparer(installer, installLock, context), lock),
//Settings用于保存所有包的动态设置
(i, pm) -> new Settings(Environment.getDataDirectory(),
RuntimePermissionsPersistence.createInstance(),
i.getPermissionManagerServiceInternal(),
domainVerificationService, backgroundHandler,
lock),
(i, pm) -> AppsFilterImpl.create(i,
i.getLocalService(PackageManagerInternal.class)),
(i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"),
//得到全局系统配置信息。
(i, pm) -> SystemConfig.getInstance(),
//创建Dex优化工具类
(i, pm) -> new PackageDexOptimizer(i.getInstaller(), i.getInstallLock(),
i.getContext(), "*dexopt*"),
(i, pm) -> new DexManager(i.getContext(), i.getPackageDexOptimizer(),
i.getInstaller(), i.getInstallLock(), i.getDynamicCodeLogger()),
(i, pm) -> new DynamicCodeLogger(i.getInstaller()),
(i, pm) -> new ArtManagerService(i.getContext(), 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, i.getDisplayMetrics(),
pm.mCacheDir,
pm.mPackageParserCallback) /* scanningCachingPackageParserProducer */,
(i, pm) -> new PackageParser2(pm.mSeparateProcesses, i.getDisplayMetrics(), null,
pm.mPackageParserCallback) /* scanningPackageParserProducer */,
(i, pm) -> new PackageParser2(pm.mSeparateProcesses, i.getDisplayMetrics(), null,
pm.mPackageParserCallback) /* preparingPackageParserProducer */,
// Prepare a supplier of package parser for the staging manager to parse apex file
....
if (Build.VERSION.SDK_INT <= 0) {
Slog.w(TAG, "**** ro.build.version.sdk not set!");
}
//初始化PMS[见3.1]
PackageManagerService m = new PackageManagerService(injector, factoryTest,
PackagePartitions.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG,
Build.VERSION.SDK_INT, Build.VERSION.INCREMENTAL);
t.traceEnd(); // "create package manager"
.....
injector.getCompatibility().registerListener(SELinuxMMAC.SELINUX_LATEST_CHANGES,
selinuxChangeListener);
injector.getCompatibility().registerListener(SELinuxMMAC.SELINUX_R_CHANGES,
selinuxChangeListener);
m.installAllowlistedSystemPackages();
IPackageManagerImpl iPackageManager = m.new IPackageManagerImpl();
//向ServiceManager注册服务
ServiceManager.addService("package", iPackageManager);
final PackageManagerNative pmn = new PackageManagerNative(m);
ServiceManager.addService("package_native", pmn);
return m;
}
3.2 PackageManagerService()
PMS的构造方法,这部分代码非常多,主要分5个阶段:
PMS_START阶段
- 构造Settings类:这个是Android的全局管理者,用于协助PMS保存所有的安装包信息;
- 保存Installer对象;
- 初始化SystemConfig,获取系统配置信息,包括全局属性、groupid以及系统权限。初始化一些功能类,包括:PackageDexOptimizer (dex优化工具类) 、 DexManager(dex管理类)、PackageHandler(建立package相关操作的消息循环)等;
- 创建data下的各种目录,比如data/app, data/app-private等。
PMS_SYSTEM_SCAN_START阶段
- 通过scanDirTracedLI扫描系统目录文件,包括:/system/framework 、/system/priv-app 、/system/app 这俩都是放系统app、/vendor/overlay、/vendor/app、oem/app。
PMS_DATA_SCAN_START阶段
- 通过scanDirTracedLI扫描/data/app和/data/app-private目录下的文件。
PMS_SCAN_END阶段
- 将上述信息写回/data/system/packages.xml。
PMS_READY阶段
- 创建服务PackageInstallerService。
3.2.1 BOOT_PROGRESS_PMS_START
public PackageManagerService(PackageManagerServiceInjector injector, boolean factoryTest,
final String partitionsFingerprint, final boolean isEngBuild,
final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {
// 存储构建和版本信息
mIsEngBuild = isEngBuild; // 是否为工程版构建
mIsUserDebugBuild = isUserDebugBuild; // 是否为用户调试版本
mSdkVersion = sdkVersion; // 系统的 SDK 版本
mIncrementalVersion = incrementalVersion; // 增量构建版本
// 通过 injector 注入依赖
mInjector = injector;
mInjector.getSystemWrapper().disablePackageCaches();
final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
Trace.TRACE_TAG_PACKAGE_MANAGER);
mPendingBroadcasts = new PendingPackageBroadcasts();
// 启动 injector 的引导程序
mInjector.bootstrap(this);
mLock = injector.getLock();
mPackageStateWriteLock = mLock;
mInstallLock = injector.getInstallLock();
LockGuard.installLock(mLock, LockGuard.INDEX_PACKAGES);
//第一阶段 BOOT_PROGRESS_PMS_START
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis());
// 初始化上下文和其他服务
mContext = injector.getContext();
mFactoryTest = factoryTest;
//用于存储屏幕的相关信息
mMetrics = injector.getDisplayMetrics();
//Installer对象
mInstaller = injector.getInstaller();
mEnableFreeCacheV2 = SystemProperties.getBoolean("fw.free_cache_v2", true);
// Create sub-components that provide services / data. Order here is important.
t.traceBegin("createSubComponents");
// Expose private service for system components to use.
LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());
LocalManagerRegistry.addManager(PackageManagerLocal.class,
new PackageManagerLocalImpl(this));
LocalServices.addService(TestUtilityService.class, this);
mTestUtilityService = LocalServices.getService(TestUtilityService.class);
// 初始化用户管理和组件解析器
mUserManager = injector.getUserManagerService();
mUserNeedsBadging = new UserNeedsBadgingCache(mUserManager);
mComponentResolver = injector.getComponentResolver();
mPermissionManager = injector.getPermissionManagerServiceInternal();
//Android的全局管理者,用于协助PMS保存所有的安装包信息;[见3.3]
mSettings = injector.getSettings();
mIncrementalManager = mInjector.getIncrementalManager();
mDefaultAppProvider = mInjector.getDefaultAppProvider();
mLegacyPermissionManager = mInjector.getLegacyPermissionManagerInternal();
PlatformCompat platformCompat = mInjector.getCompatibility();
mPackageParserCallback = new PackageParser2.Callback() {
@Override
public boolean isChangeEnabled(long changeId, @NonNull ApplicationInfo appInfo) {
return platformCompat.isChangeEnabled(changeId, appInfo);
}
@Override
public boolean hasFeature(String feature) {
return PackageManagerService.this.hasSystemFeature(feature, 0);
}
};
// CHECKSTYLE:ON IndentationCheck
t.traceEnd();
// 添加共享用户,如两个App的之间的数据是不共享的,如果它们有了共同的sharedUserId,就可以运行在同一个进程中共享数据。
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();
// 获取分离进程的系统属性
String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
if ("*".equals(separateProcesses)) {
mDefParseFlags = ParsingPackageUtils.PARSE_IGNORE_PROCESSES;
mSeparateProcesses = null;
Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
} else {
mDefParseFlags = 0;
mSeparateProcesses = separateProcesses.split(",");
Slog.w(TAG, "Running with debug.separate_processes: "
+ separateProcesses);
}
} else {
mDefParseFlags = 0;
mSeparateProcesses = null;
}
// 初始化 Dex 优化器和管理器
mPackageDexOptimizer = injector.getPackageDexOptimizer();
//Dex优化工具类
mDexManager = injector.getDexManager();
mDynamicCodeLogger = injector.getDynamicCodeLogger();
//后台DexOpt服务
mBackgroundDexOptService = injector.getBackgroundDexOptService();
mArtManagerService = injector.getArtManagerService();
mMoveCallbacks = new MovePackageHelper.MoveCallbacks(FgThread.get().getLooper());
mViewCompiler = injector.getViewCompiler();
mSharedLibraries = mInjector.getSharedLibrariesImpl();
mBackgroundHandler = injector.getBackgroundHandler();
mContext.getSystemService(DisplayManager.class)
.getDisplay(Display.DEFAULT_DISPLAY).getMetrics(mMetrics);
t.traceBegin("get system config");
SystemConfig systemConfig = injector.getSystemConfig();
mAvailableFeatures = systemConfig.getAvailableFeatures();
t.traceEnd();
mProtectedPackages = new ProtectedPackages(mContext);
// 初始化 APEX 和应用过滤器
mApexManager = injector.getApexManager();
mAppsFilter = mInjector.getAppsFilter();
mInstantAppRegistry = new InstantAppRegistry(mContext, mPermissionManager,
mInjector.getUserManagerInternal(), new DeletePackageHelper(this));
mChangedPackagesTracker = new ChangedPackagesTracker();
// 应用安装目录
mAppInstallDir = new File(Environment.getDataDirectory(), "app");
mDomainVerificationConnection = new DomainVerificationConnection(this);
mDomainVerificationManager = injector.getDomainVerificationManagerInternal();
mDomainVerificationManager.setConnection(mDomainVerificationConnection);
// 初始化各类Helper
mBroadcastHelper = new BroadcastHelper(mInjector);
mAppDataHelper = new AppDataHelper(this);
mInstallPackageHelper = new InstallPackageHelper(this, mAppDataHelper);
mRemovePackageHelper = new RemovePackageHelper(this, mAppDataHelper);
mDeletePackageHelper = new DeletePackageHelper(this, mRemovePackageHelper,
mAppDataHelper);
mSharedLibraries.setDeletePackageHelper(mDeletePackageHelper);
mPreferredActivityHelper = new PreferredActivityHelper(this);
mResolveIntentHelper = new ResolveIntentHelper(mContext, mPreferredActivityHelper,
injector.getCompatibility(), mUserManager, mDomainVerificationManager,
mUserNeedsBadging, () -> mResolveInfo, () -> mInstantAppInstallerActivity,
injector.getBackgroundHandler());
mDexOptHelper = new DexOptHelper(this);
mSuspendPackageHelper = new SuspendPackageHelper(this, mInjector, mUserManager,
mBroadcastHelper, mProtectedPackages);
mDistractingPackageHelper = new DistractingPackageHelper(this, mInjector, mBroadcastHelper,
mSuspendPackageHelper);
mStorageEventHelper = new StorageEventHelper(this, mDeletePackageHelper,
mRemovePackageHelper);
synchronized (mLock) {
// Create the computer as soon as the state objects have been installed. The
// cached computer is the same as the live computer until the end of the
// constructor, at which time the invalidation method updates it.
mSnapshotStatistics = new SnapshotStatistics();// 初始化快照统计数据
sSnapshotPendingVersion.incrementAndGet();
mLiveComputer = createLiveComputer();
registerObservers(true);// 注册观察者,监听系统状态的变化
}
Computer computer = mLiveComputer;
// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
// writer
// 这里是包管理器服务的核心锁机制,用于在包安装过程中确保线程安全。
synchronized (mLock) {
mHandler = injector.getHandler();
mProcessLoggingHandler = new ProcessLoggingHandler();
//将PackageHandler添加到Watchdog的检测集中
Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
// 加载共享库的配置
ArrayMap<String, SystemConfig.SharedLibraryEntry> libConfig
= systemConfig.getSharedLibraries();
final int builtInLibCount = libConfig.size();
for (int i = 0; i < builtInLibCount; i++) {
mSharedLibraries.addBuiltInSharedLibraryLPw(libConfig.valueAt(i));
}
// Now that we have added all the libraries, iterate again to add dependency
// information IFF their dependencies are added.
// 添加共享库的依赖项
long undefinedVersion = SharedLibraryInfo.VERSION_UNDEFINED;
for (int i = 0; i < builtInLibCount; i++) {
String name = libConfig.keyAt(i);
SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);
final int dependencyCount = entry.dependencies.length;
for (int j = 0; j < dependencyCount; j++) {
final SharedLibraryInfo dependency =
computer.getSharedLibraryInfo(entry.dependencies[j], undefinedVersion);
if (dependency != null) {
computer.getSharedLibraryInfo(name, undefinedVersion)
.addDependency(dependency);
}
}
}
// 读取 SELinux 安装策略
SELinuxMMAC.readInstallPolicy();
t.traceBegin("loadFallbacks");
FallbackCategoryProvider.loadFallbacks();
t.traceEnd();
// 读取用户设置,检查系统是否是首次启动
t.traceBegin("read user settings");
mFirstBoot = !mSettings.readLPw(computer,
mInjector.getUserManagerInternal().getUsers(
/* excludePartial= */ true,
/* excludeDying= */ false,
/* excludePreCreated= */ false));
t.traceEnd();
// 如果是第一次启动,设置安装程序的第一次启动标志
if (mFirstBoot) {
t.traceBegin("setFirstBoot: ");
try {
mInstaller.setFirstBoot();
} catch (InstallerException e) {
Slog.w(TAG, "Could not set First Boot: ", e);
}
t.traceEnd();
}
mPermissionManager.readLegacyPermissionsTEMP(mSettings.mPermissions);
mPermissionManager.readLegacyPermissionStateTEMP();
if (mFirstBoot) {
DexOptHelper.requestCopyPreoptedFiles();
}
String customResolverActivityName = Resources.getSystem().getString(
R.string.config_customResolverActivity);
if (!TextUtils.isEmpty(customResolverActivityName)) {
mCustomResolverComponentName = ComponentName.unflattenFromString(
customResolverActivityName);
}
long startTime = SystemClock.uptimeMillis();
3.2.2 BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
/system可以称作为System分区,里面主要存储谷歌和其他厂商提供的Android系统相关文件和框架。Android系统架构分为应用层、应用框架层、系统运行库层(Native 层)、硬件抽象层(HAL层)和Linux内核层,除了Linux内核层在Boot分区,其他层的代码都在System分区。
该阶段主要在扫描各目录下的apps耗时,开机耗时需重点关注。
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
startTime);
final String bootClassPath = System.getenv("BOOTCLASSPATH");
final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
if (bootClassPath == null) {
Slog.w(TAG, "No BOOTCLASSPATH found!");
}
if (systemServerClassPath == null) {
Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!");
}
final VersionInfo ver = mSettings.getInternalVersion();
mIsUpgrade =
!partitionsFingerprint.equals(ver.fingerprint);
if (mIsUpgrade) {
PackageManagerServiceUtils.logCriticalInfo(Log.INFO,
"Upgrading from " + ver.fingerprint + " (" + ver.buildFingerprint + ") to "
+ PackagePartitions.FINGERPRINT + " (" + Build.FINGERPRINT + ")");
}
mInitAppsHelper = new InitAppsHelper(this, mApexManager, mInstallPackageHelper,
mInjector.getSystemPartitions());
// when upgrading from pre-M, promote system app permissions from install to runtime
mPromoteSystemApps =
mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;
mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;
final WatchedArrayMap<String, PackageSetting> packageSettings =
mSettings.getPackagesLocked();
if (isDeviceUpgrading()) {
// Save the names of pre-existing packages prior to scanning, so we can determine
// which system packages are completely new due to an upgrade.
mExistingPackages = new ArraySet<>(packageSettings.size());
for (PackageSetting ps : packageSettings.values()) {
mExistingPackages.add(ps.getPackageName());
}
// Triggering {@link com.android.server.pm.crossprofile.
// CrossProfileIntentFilterHelper.updateDefaultCrossProfileIntentFilter} to update
// {@link CrossProfileIntentFilter}s between eligible users and their parent
t.traceBegin("cross profile intent filter update");
mInjector.getCrossProfileIntentFilterHelper()
.updateDefaultCrossProfileIntentFilter();
t.traceEnd();
}
mCacheDir = PackageManagerServiceUtils.preparePackageParserCache(
mIsEngBuild, mIsUserDebugBuild, mIncrementalVersion);
mInitialNonStoppedSystemPackages = mInjector.getSystemConfig()
.getInitialNonStoppedSystemPackages();
mShouldStopSystemPackagesByDefault = mContext.getResources()
.getBoolean(R.bool.config_stopSystemPackagesByDefault);
final int[] userIds = mUserManager.getUserIds();
//扫描system目录下的apps,[见3.2.2.1]
PackageParser2 packageParser = mInjector.getScanningCachingPackageParser();
mOverlayConfig = mInitAppsHelper.initSystemApps(packageParser, packageSettings, userIds,
startTime);
3.2.2.1 InitAppsHelper.initSystemApps
public OverlayConfig initSystemApps(PackageParser2 packageParser,
WatchedArrayMap<String, PackageSetting> packageSettings,
int[] userIds, long startTime) {
// Prepare apex package info before scanning APKs, this information is needed when
// scanning apk in apex.
final List<ApexManager.ScanResult> apexScanResults = scanApexPackagesTraced(packageParser);
mApexManager.notifyScanResult(apexScanResults);
扫描system各个目录下的apps[见3.2.2.2]
scanSystemDirs(packageParser, mExecutorService);
// Parse overlay configuration files to set default enable state, mutability, and
// priority of system overlays.
final ArrayMap<String, File> apkInApexPreInstalledPaths = new ArrayMap<>();
for (ApexManager.ActiveApexInfo apexInfo : mApexManager.getActiveApexInfos()) {
for (String packageName : mApexManager.getApksInApex(apexInfo.apexModuleName)) {
apkInApexPreInstalledPaths.put(packageName, apexInfo.preInstalledApexPath);
}
}
final OverlayConfig overlayConfig = OverlayConfig.initializeSystemInstance(
consumer -> mPm.forEachPackageState(mPm.snapshotComputer(),
packageState -> {
var pkg = packageState.getPkg();
if (pkg != null) {
consumer.accept(pkg, packageState.isSystem(),
apkInApexPreInstalledPaths.get(pkg.getPackageName()));
}
}));
// do this first before mucking with mPackages for the "expecting better" case
updateStubSystemAppsList(mStubSystemApps);
mInstallPackageHelper.prepareSystemPackageCleanUp(packageSettings,
mPossiblyDeletedUpdatedSystemApps, mExpectingBetter, userIds);
[见3.2.2.3]统计扫描多少个应用和耗时
logSystemAppsScanningTime(startTime);
return overlayConfig;
}
3.2.2.2 InitAppsHelper.scanSystemDirs
@GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
private void scanSystemDirs(PackageParser2 packageParser, ExecutorService executorService) {
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
// Collect vendor/product/system_ext overlay packages. (Do this before scanning
// any apps.)
// For security and version matching reason, only consider overlay packages if they
// reside in the right directory.
for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
final ScanPartition partition = mDirsToScanAsSystem.get(i);
if (partition.getOverlayFolder() == null) {
continue;
}
//扫描/vendor/overlay目录下的文件
scanDirTracedLI(partition.getOverlayFolder(),
mSystemParseFlags, mSystemScanFlags | partition.scanFlag,
packageParser, executorService, partition.apexInfo);
}
//扫描/system/framework 目录下的文件
scanDirTracedLI(frameworkDir,
mSystemParseFlags, mSystemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED,
packageParser, executorService, null);
if (!mPm.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) {
//扫描 /system/priv-app 目录下的文件
scanDirTracedLI(partition.getPrivAppFolder(),
mSystemParseFlags,
mSystemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag,
packageParser, executorService, partition.apexInfo);
}
scanDirTracedLI(partition.getAppFolder(),
mSystemParseFlags, mSystemScanFlags | partition.scanFlag,
packageParser, executorService, partition.apexInfo);
}
}
3.2.2.3 logSystemAppsScanningTime
@GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
private void logSystemAppsScanningTime(long startTime) {
mCachedSystemApps = PackageCacher.sCachedPackageReadCount.get();
// Remove any shared userIDs that have no associated packages
mPm.mSettings.pruneSharedUsersLPw();
mSystemScanTime = SystemClock.uptimeMillis() - startTime;
mSystemPackagesCount = mPm.mPackages.size();
//统计扫描多少个system目录,平均耗时多少,可以在even log中查找
Slog.i(TAG, "Finished scanning system apps. Time: " + mSystemScanTime
+ " ms, packageCount: " + mSystemPackagesCount
+ " , timePerPackage: "
+ (mSystemPackagesCount == 0 ? 0 : mSystemScanTime / mSystemPackagesCount)
+ " , cached: " + mCachedSystemApps);
if (mIsDeviceUpgrading && mSystemPackagesCount > 0) {
//CHECKSTYLE:OFF IndentationCheck
FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,
BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_SYSTEM_APP_AVG_SCAN_TIME,
mSystemScanTime / mSystemPackagesCount);
//CHECKSTYLE:ON IndentationCheck
}
}
3.2.3 BOOT_PROGRESS_PMS_DATA_SCAN_START
data可以称为Data分区,它用来存储所有用户的个人数据和配置文件。下面列出Data分区部分子目录:
| 目录| 含义|
| :——–: | :——–:| :–: |
| app| 存储用户自己安装的App|
| data| 存储所有已安装的App数据的目录,每个App都有自己单独的子目录 |
| app-private| App的私有存储空间 |
| app-lib|存储所有App的Jni库 |
| system| 存放系统配置文件 |
| anr| 用于存储ANR发生时系统生成的traces.txt文件 |
//该方法为扫描data目录下的apps,[见3.2.3.1]
mInitAppsHelper.initNonSystemApps(packageParser, userIds, startTime);
packageParser.close();
mRequiredVerifierPackages = getRequiredButNotReallyRequiredVerifiersLPr(computer);
mRequiredInstallerPackage = getRequiredInstallerLPr(computer);
mRequiredUninstallerPackage = getRequiredUninstallerLPr(computer);
// PermissionController hosts default permission granting and role management, so it's a
// critical part of the core system.
mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr(computer);
// Resolve the storage manager.
mStorageManagerPackage = getStorageManagerPackageName(computer);
// Resolve protected action filters. Only the setup wizard is allowed to
// have a high priority filter for these actions.
mSetupWizardPackage = getSetupWizardPackageNameImpl(computer);
mComponentResolver.fixProtectedFilterPriorities(mSetupWizardPackage);
mDefaultTextClassifierPackage = ensureSystemPackageName(computer,
mContext.getString(R.string.config_servicesExtensionPackage));
mSystemTextClassifierPackageName = ensureSystemPackageName(computer,
mContext.getString(R.string.config_defaultTextClassifierPackage));
mConfiguratorPackage = ensureSystemPackageName(computer,
mContext.getString(R.string.config_deviceConfiguratorPackageName));
mAppPredictionServicePackage = ensureSystemPackageName(computer,
getPackageFromComponentString(R.string.config_defaultAppPredictionService));
mIncidentReportApproverPackage = ensureSystemPackageName(computer,
mContext.getString(R.string.config_incidentReportApproverPackage));
mRetailDemoPackage = getRetailDemoPackageName();
mOverlayConfigSignaturePackage = ensureSystemPackageName(computer,
mInjector.getSystemConfig().getOverlayConfigSignaturePackage());
mRecentsPackage = ensureSystemPackageName(computer,
getPackageFromComponentString(R.string.config_recentsComponentName));
mAmbientContextDetectionPackage = ensureSystemPackageName(computer,
getPackageFromComponentString(
R.string.config_defaultAmbientContextDetectionService));
mWearableSensingPackage = ensureSystemPackageName(computer,
getPackageFromComponentString(
R.string.config_defaultWearableSensingService));
// Now that we know all of the shared libraries, update all clients to have
// the correct library paths.
mSharedLibraries.updateAllSharedLibrariesLPw(
null, null, Collections.unmodifiableMap(mPackages));
for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
// NOTE: We ignore potential failures here during a system scan (like
// the rest of the commands above) because there's precious little we
// can do about it. A settings error is reported, though.
final List<String> changedAbiCodePath =
ScanPackageUtils.applyAdjustedAbiToSharedUser(setting,
null /*scannedPackage*/,
mInjector.getAbiHelper().getAdjustedAbiForSharedUser(
setting.getPackageStates(), null /*scannedPackage*/));
if (!useArtService() && // Skip for ART Service since it has its own dex file GC.
changedAbiCodePath != null && changedAbiCodePath.size() > 0) {
for (int i = changedAbiCodePath.size() - 1; i >= 0; --i) {
final String codePathString = changedAbiCodePath.get(i);
try {
mInstaller.rmdex(codePathString,
getDexCodeInstructionSet(getPreferredInstructionSet()));
} catch (LegacyDexoptDisabledException e) {
throw new RuntimeException(e);
} catch (InstallerException ignored) {
}
}
}
// Adjust seInfo to ensure apps which share a sharedUserId are placed in the same
// SELinux domain.
setting.fixSeInfoLocked();
setting.updateProcesses();
}
// Now that we know all the packages we are keeping,
// read and update their last usage times.
mPackageUsage.read(packageSettings);
mCompilerStats.read();
3.2.3.1InitAppsHelper.initNonSystemApps
public void initNonSystemApps(PackageParser2 packageParser, @NonNull int[] userIds,
long startTime) {
//扫描data app日志节点,BOOT_PROGRESS_PMS_DATA_SCAN_START
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
if ((mScanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) == SCAN_FIRST_BOOT_OR_UPGRADE) {
fixInstalledAppDirMode();
}
//扫描/data/app目录下的文件
scanDirTracedLI(mPm.getAppInstallDir(), 0,
mScanFlags | SCAN_REQUIRE_KNOWN, packageParser, mExecutorService, null);
List<Runnable> unfinishedTasks = mExecutorService.shutdownNow();
if (!unfinishedTasks.isEmpty()) {
throw new IllegalStateException("Not all tasks finished before calling close: "
+ unfinishedTasks);
}
fixSystemPackages(userIds);
[见3.2.3.2]
logNonSystemAppScanningTime(startTime);
mExpectingBetter.clear();
mPm.mSettings.pruneRenamedPackagesLPw();
}
3.2.3.2 InitAppsHelper.logNonSystemAppScanningTime
@GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
private void logNonSystemAppScanningTime(long startTime) {
final int cachedNonSystemApps = PackageCacher.sCachedPackageReadCount.get()
- mCachedSystemApps;
final long dataScanTime = SystemClock.uptimeMillis() - mSystemScanTime - startTime;
final int dataPackagesCount = mPm.mPackages.size() - mSystemPackagesCount;
//统计总共扫描了多少个non-system apps,平均耗时多少,可以在even log里查看
Slog.i(TAG, "Finished scanning non-system apps. Time: " + dataScanTime
+ " ms, packageCount: " + dataPackagesCount
+ " , timePerPackage: "
+ (dataPackagesCount == 0 ? 0 : dataScanTime / dataPackagesCount)
+ " , cached: " + cachedNonSystemApps);
if (mIsDeviceUpgrading && dataPackagesCount > 0) {
//CHECKSTYLE:OFF IndentationCheck
FrameworkStatsLog.write(
FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,
BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_DATA_APP_AVG_SCAN_TIME,
dataScanTime / dataPackagesCount);
//CHECKSTYLE:OFF IndentationCheck
}
}
3.2.4 BOOT_PROGRESS_PMS_SCAN_END
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());
Slog.i(TAG, "Time to scan packages: "
+ ((SystemClock.uptimeMillis() - startTime) / 1000f)
+ " seconds");
// If the partitions fingerprint has changed since the last time we booted,
// we need to re-grant app permission to catch any new ones that
// appear. This is really a hack, and means that apps can in some
// cases get permissions that the user didn't initially explicitly
// allow... it would be nice to have some better way to handle
// this situation.
if (mIsUpgrade) {
Slog.i(TAG, "Partitions fingerprint changed from " + ver.fingerprint + " to "
+ PackagePartitions.FINGERPRINT
+ "; regranting permissions for internal storage");
}
mPermissionManager.onStorageVolumeMounted(
StorageManager.UUID_PRIVATE_INTERNAL, mIsUpgrade);
ver.sdkVersion = mSdkVersion;
// If this is the first boot or an update from pre-M, then we need to initialize the
// default preferred apps across all defined users.
//如果是第一次启动或者是Android M升级后的第一次启动,需要初始化所有用户定义的默认首选App
if (mPromoteSystemApps || mFirstBoot) {
for (UserInfo user : mInjector.getUserManagerInternal().getUsers(true)) {
mSettings.applyDefaultPreferredAppsLPw(user.id);
}
}
// If this is first boot after an OTA, then we need to clear code cache directories.
// Note that we do *not* clear the application profiles. These remain valid
// across OTAs and are used to drive profile verification (post OTA) and
// profile compilation (without waiting to collect a fresh set of profiles).
//OTA后的第一次启动,会清除代码缓存目录。
if (mIsUpgrade) {
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.getVolumeUuid())) {
// No apps are running this early, so no need to freeze
mAppDataHelper.clearAppDataLIF(ps.getPkg(), 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.buildFingerprint = Build.FINGERPRINT;
ver.fingerprint = PackagePartitions.FINGERPRINT;
}
// Defer the app data fixup until we are done with app data clearing above.
mPrepareAppDataFuture = mAppDataHelper.fixAppsDataOnBoot();
// Legacy existing (installed before Q) non-system apps to hide
// their icons in launcher.
if (mIsPreQUpgrade) {
Slog.i(TAG, "Allowlisting 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.getFlags() & 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;
// All the changes are done during package scanning.
ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;
// can downgrade to reader
t.traceBegin("write settings");
// 把Settings的内容保存到packages.xml中
writeSettingsLPrTEMP();
t.traceEnd();
3.2.5 BOOT_PROGRESS_PMS_READY
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
.....
//PackageInstallerService是用于管理安装会话的服务,它会为每次安装过程分配一个SessionId
mInstallerService = mInjector.getPackageInstallerService();
final ComponentName instantAppResolverComponent = getInstantAppResolver(computer);
if (instantAppResolverComponent != null) {
if (DEBUG_INSTANT) {
Slog.d(TAG, "Set ephemeral resolver: " + instantAppResolverComponent);
}
mInstantAppResolverConnection =
mInjector.getInstantAppResolverConnection(instantAppResolverComponent);
mInstantAppResolverSettingsComponent =
getInstantAppResolverSettingsLPr(computer,
instantAppResolverComponent);
} else {
mInstantAppResolverConnection = null;
mInstantAppResolverSettingsComponent = null;
}
updateInstantAppInstallerLocked(null);
// Read and update the usage of dex files.
// Do this at the end of PM init so that all the packages have their
// data directory reconciled.
// At this point we know the code paths of the packages, so we can validate
// the disk file and build the internal cache.
// The usage file is expected to be small so loading and verifying it
// should take a fairly small time compare to the other activities (e.g. package
// scanning).
final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
for (int userId : userIds) {
userPackages.put(userId, computer.getInstalledPackages(/*flags*/ 0, userId)
.getList());
}
mDexManager.load(userPackages);
mDynamicCodeLogger.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);
}
//如果这是首次启动或OTA后的首次启动,则将文件路径设置为预加载包的应用元数据文件
if (mFirstBoot || isDeviceUpgrading()) {
ArrayMap<String, String> paths = systemConfig.getAppMetadataFilePaths();
for (Map.Entry<String, String> entry : paths.entrySet()) {
String pkgName = entry.getKey();
String path = entry.getValue();
File file = new File(path);
if (!file.exists()) {
path = null;
}
PackageSetting disabledPkgSetting = mSettings.getDisabledSystemPkgLPr(pkgName);
if (disabledPkgSetting == null) {
PackageSetting pkgSetting = mSettings.getPackageLPr(pkgName);
if (pkgSetting != null) {
pkgSetting.setAppMetadataFilePath(path);
} else {
Slog.w(TAG, "Cannot set app metadata file for nonexistent package "
+ pkgName);
}
} else {
disabledPkgSetting.setAppMetadataFilePath(path);
}
}
}
....
}