> 文章列表 > Android13 PMS是如何启动的?

Android13 PMS是如何启动的?

Android13 PMS是如何启动的?

作者:Arthas0v0

平常使用安卓实际就是在使用各种app,而下载的app实际是一个apk文件。这个apk文件的安装就交给了PackageManagerService来实现。PackageManagerService的启动也是在SystemServer中。这个过程比较长需要长一点的时间来理。

SystemServer.startBootstrapServices

//frameworks/base/services/java/com/android/server/SystemServer.java       Installer installer = mSystemServiceManager.startService(Installer.class);  IPackageManager iPackageManager;t.traceBegin("StartPackageManagerService");try {Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");Pair<PackageManagerService, IPackageManager> pmsPair = PackageManagerService.main(mSystemContext, installer, domainVerificationService,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);mPackageManagerService = pmsPair.first;iPackageManager = pmsPair.second;} finally {Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");}mFirstBoot = mPackageManagerService.isFirstBoot();

PackageManagerService的main方法初始化了PackageManagerService和IPackageManager,其中传入的installer需要特别关注一下,很关键的变量。

//frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public static Pair<PackageManagerService, IPackageManager> main(Context context,Installer installer, @NonNull DomainVerificationService domainVerificationService,boolean factoryTest, boolean onlyCore) {// 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,并启动HandlerThread backgroundThread = new ServiceThread("PackageManagerBg",Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);backgroundThread.start();Handler backgroundHandler = new Handler(backgroundThread.getLooper());
//真正的操作和相关的对象都放到了PackageManagerServiceInjector中。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, onlyCore),lock),(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(),(i, pm) -> new PackageDexOptimizer(i.getInstaller(), i.getInstallLock(),i.getContext(), "*dexopt*"),(i, pm) -> new DexManager(i.getContext(), i.getPackageDexOptimizer(),i.getInstaller(), i.getInstallLock()),(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, 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()),(i, pm) -> LegacyPermissionManagerService.create(i.getContext()),(i, pm) -> domainVerificationService,(i, pm) -> {HandlerThread thread = new ServiceThread(TAG,Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/);thread.start();return new PackageHandler(thread.getLooper(), pm);},new DefaultSystemWrapper(),LocalServices::getService,context::getSystemService,(i, pm) -> new BackgroundDexOptService(i.getContext(), i.getDexManager(), pm),(i, pm) -> IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE)),(i, pm) -> new SharedLibrariesImpl(pm, i));
​if (Build.VERSION.SDK_INT <= 0) {Slog.w(TAG, "**** ro.build.version.sdk not set!");}//创建一个PackageManagerService实例PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest,PackagePartitions.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG,Build.VERSION.SDK_INT, Build.VERSION.INCREMENTAL);t.traceEnd(); // "create package manager"
.......//根据用户类型安装或卸载系统应用安装包m.installAllowlistedSystemPackages();//创建IPackageManager并添加到ServiceManager中,客户端交互IPackageManagerImpl iPackageManager = m.new IPackageManagerImpl();ServiceManager.addService("package", iPackageManager);//创建native的PackageManager,注册到ServiceManager中final PackageManagerNative pmn = new PackageManagerNative(m);ServiceManager.addService("package_native", pmn);LocalManagerRegistry.addManager(PackageManagerLocal.class, m.new PackageManagerLocalImpl());//返回PackageManagerService和IPackageManagerreturn Pair.create(m, iPackageManager);}

在main方法中重要的就几件事

1.创建PackageManagerServiceInjector
2.创建PackageManagerService
3.创建iPackageManager添加到ServiceManager中
4.创建PackageManagerNative添加到ServiceManager中

PackageManagerServiceInjector就是很简单的做了一层封装,把所有相关的对象都初始化都保存了起来。接下来看PackageManagerService,这个初始化函数非常长,所以分几段来看,可以根据log分为BOOT_PROGRESS_PMS_START,BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,BOOT_PROGRESS_PMS_SCAN_END,BOOT_PROGRESS_PMS_READY,这几个阶段

BOOT_PROGRESS_PMS_START

 public PackageManagerService(PackageManagerServiceInjector injector, boolean onlyCore,boolean factoryTest, final String buildFingerprint, final boolean isEngBuild,final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {mIsEngBuild = isEngBuild;mIsUserDebugBuild = isUserDebugBuild;mSdkVersion = sdkVersion;mIncrementalVersion = incrementalVersion;mInjector = injector;mInjector.getSystemWrapper().disablePackageCaches();
​final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",Trace.TRACE_TAG_PACKAGE_MANAGER);mPendingBroadcasts = new PendingPackageBroadcasts();mInjector.bootstrap(this);mLock = injector.getLock();mPackageStateWriteLock = mLock;mInstallLock = injector.getInstallLock();//重要的lockLockGuard.installLock(mLock, LockGuard.INDEX_PACKAGES);EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,SystemClock.uptimeMillis());//BOOT_PROGRESS_PMS_START阶段
​mContext = injector.getContext();mFactoryTest = factoryTest;mOnlyCore = onlyCore;//是否只启动核心业务mMetrics = injector.getDisplayMetrics();mInstaller = injector.getInstaller();//获取installermEnableFreeCacheV2 = SystemProperties.getBoolean("fw.free_cache_v2", true);// 将当前PackageManagerInternal注册到了LocalServices中LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());LocalServices.addService(TestUtilityService.class, this);mTestUtilityService = LocalServices.getService(TestUtilityService.class);//......中间都是获取PackageManagerServiceInjector的一些成员变量// 创建了Settings类了,mSettings管理着app的安装信息,这里添加了6个app的包名到共享用户列表,同时设置权限为系统级别的权限uidmSettings = injector.getSettings();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到odex/oat的转换mPackageDexOptimizer = injector.getPackageDexOptimizer();mDexManager = injector.getDexManager();mBackgroundDexOptService = injector.getBackgroundDexOptService();//ART虚拟机管理服务mArtManagerService = injector.getArtManagerService();mMoveCallbacks = new MovePackageHelper.MoveCallbacks(FgThread.get().getLooper());mViewCompiler = injector.getViewCompiler();//共享库mSharedLibraries = mInjector.getSharedLibrariesImpl();//获取分辨率mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY).getMetrics(mMetrics);
​t.traceBegin("get system config");//获取系统配置SystemConfig systemConfig = injector.getSystemConfig();mAvailableFeatures = systemConfig.getAvailableFeatures();t.traceEnd();//限制几个系统app的访问,如launchermProtectedPackages = new ProtectedPackages(mContext);mApexManager = injector.getApexManager();mAppsFilter = mInjector.getAppsFilter();
​mInstantAppRegistry = new InstantAppRegistry(mContext, mPermissionManager,mInjector.getUserManagerInternal(), new DeletePackageHelper(this));//复制监听包变化的事件,安装卸载等mChangedPackagesTracker = new ChangedPackagesTracker();//非系统app的路径mAppInstallDir = new File(Environment.getDataDirectory(), "app");//.....中间初始化了各种操作类// CHECKSTYLE:OFF IndentationChecksynchronized (mInstallLock) {// writersynchronized (mLock) {//获取安装线程的handler,同样是injector中创建的mHandler = injector.getHandler();mProcessLoggingHandler = new ProcessLoggingHandler();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);}}}
​SELinuxMMAC.readInstallPolicy();
​t.traceBegin("loadFallbacks");FallbackCategoryProvider.loadFallbacks();t.traceEnd();
​t.traceBegin("read user settings");//根据/data/system下的XML判断是不是第一次启动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 (!mOnlyCore && mFirstBoot) {//如果都不是就复制dexDexOptHelper.requestCopyPreoptedFiles();}

这里做的还都是准备工作,获取了需要的一系列对象和路径,比较重要的点就是创建了Settings。

//frameworks/base/services/core/java/com/android/server/pm/Settings.java
Settings(File dataDir, RuntimePermissionsPersistence runtimePermissionsPersistence,LegacyPermissionDataProvider permissionDataProvider,@NonNull DomainVerificationManagerInternal domainVerificationManager,@NonNull Handler handler,@NonNull PackageManagerTracedLock lock)  {
​...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 migrationmStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");...}

Settings中保存了安装包信息,packages-stopped.xml标记为废弃不关注,主要文件就是/data/system/下的packages.xml,packages-backup.xml,packages.list,packages-backup作为备份文件,其他两个文件的作用是

  • packages.xml: PKMS 扫描完目标文件夹后会创建该文件。当系统进行程序安装、卸载和更新等操作时,均会更新该文件。该文件保存了系统中与 package 相关的一些信息。
  • packages.list:描述系统中存在的所有非系统自带的 APK 的信息。当这些程序有变动时,PKMS 就会更新该文件。
//frameworks/base/services/core/java/com/android/server/pm/Settings.javaboolean readLPw(@NonNull Computer computer, @NonNull List<UserInfo> users) {FileInputStream str = null;final ArrayMap<String, Long> originalFirstInstallTimes = new ArrayMap<>();
​try {if (str == null) {if (!mSettingsFilename.exists()) {//如果不存在就返回false,也就是第一次创建mReadMessages.append("No settings file found\\n");PackageManagerService.reportSettingsProblem(Log.INFO,"No settings file; creating initial state");// It's enough to just touch version details to create them// with default valuesfindOrCreateVersion(StorageManager.UUID_PRIVATE_INTERNAL).forceCurrent();findOrCreateVersion(StorageManager.UUID_PRIMARY_PHYSICAL).forceCurrent();return false;}str = new FileInputStream(mSettingsFilename);}final TypedXmlPullParser parser = Xml.resolvePullParser(str);//...如果存在这些xml文件就通过TypedXmlPullParser解析这些xml文件,保存在Settings中​return true;}

BOOT_PROGRESS_PMS_SYSTEM_SCAN_START

EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,startTime);//获取bootClassPath和systemServerClassPath下的环境变量final String bootClassPath = System.getenv("BOOTCLASSPATH");final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
​final VersionInfo ver = mSettings.getInternalVersion();//判断是否升级了mIsUpgrade =!buildFingerprint.equals(ver.fingerprint);if (mIsUpgrade) {PackageManagerServiceUtils.logCriticalInfo(Log.INFO, "Upgrading from "+ ver.fingerprint + " to " + PackagePartitions.FINGERPRINT);}//初始化app的类mInitAppsHelper = new InitAppsHelper(this, mApexManager, mInstallPackageHelper,mInjector.getSystemPartitions());
​//如果是android M升级上来的需要修改为运行时权限mPromoteSystemApps =mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;
​// 对于Android N之前版本升级上来的情况,需像首次启动一样处理packagemIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;
​final WatchedArrayMap<String, PackageSetting> packageSettings =mSettings.getPackagesLocked();
​//扫描之前就存在的系统package的名称,这样就可以确定哪些更新的if (isDeviceUpgrading()) {mExistingPackages = new ArraySet<>(packageSettings.size());for (PackageSetting ps : packageSettings.values()) {mExistingPackages.add(ps.getPackageName());}}//获取缓存目录mCacheDir = PackageManagerServiceUtils.preparePackageParserCache(mIsEngBuild, mIsUserDebugBuild, mIncrementalVersion);
​final int[] userIds = mUserManager.getUserIds();//获取PackageParser2PackageParser2 packageParser = mInjector.getScanningCachingPackageParser();//扫描系统appmOverlayConfig = mInitAppsHelper.initSystemApps(packageParser, packageSettings, userIds,startTime);//系统app以外的appmInitAppsHelper.initNonSystemApps(packageParser, userIds, startTime);packageParser.close();
​// 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.//只允许安装向导这个应用拥有高级别的actionmSetupWizardPackage = 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));
​// 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.//如果升级导致abi发生了变化,那么就卸载原来api的代码final List<String> changedAbiCodePath =ScanPackageUtils.applyAdjustedAbiToSharedUser(setting, null /*scannedPackage*/,mInjector.getAbiHelper().getAdjustedAbiForSharedUser(setting.getPackageStates(), null /*scannedPackage*/));if (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 (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.// 读取并更新保留的package的上次使用时间mPackageUsage.read(packageSettings);mCompilerStats.read();

这里最重要的就是通过mInitAppsHelper获取了系统apk和其他的apk的信息。

//frameworks/base/services/core/java/com/android/server/pm/InitAppsHelper.javapublic OverlayConfig initSystemApps(PackageParser2 packageParser,WatchedArrayMap<String, PackageSetting> packageSettings,int[] userIds, long startTime) {...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);}}....return overlayConfig;}

    private void scanSystemDirs(PackageParser2 packageParser, ExecutorService executorService) {///system/framework路径下File frameworkDir = new File(Environment.getRootDirectory(), "framework");
​scanDirTracedLI(frameworkDir, null,mSystemParseFlags,mSystemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED,packageParser, executorService);//....其他系统app路径也一样就不展示了}

scanSystemDirs中就是通过scanDirTracedLI扫描各种路径下的apk。

      private void scanDirTracedLI(File scanDir, List<File> frameworkSplits,int parseFlags, int scanFlags,PackageParser2 packageParser, ExecutorService executorService) {Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]");try {if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) {// when scanning apk in apexes, we want to check the maxSdkVersionparseFlags |= PARSE_APK_IN_APEX;}mInstallPackageHelper.installPackagesFromDir(scanDir, frameworkSplits, parseFlags,scanFlags, packageParser, executorService);} finally {Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);}}

scanDirTracedLI调用了InstallPackageHelper.installPackagesFromDir来安装

//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java 
public void installPackagesFromDir(File scanDir, List<File> frameworkSplits, int parseFlags,int scanFlags, PackageParser2 packageParser,ExecutorService executorService) {final File[] files = scanDir.listFiles();ParallelPackageParser parallelPackageParser =new ParallelPackageParser(packageParser, executorService, frameworkSplits);
​// Submit files for parsing in parallelint fileCount = 0;for (File file : files) {final boolean isPackage = (isApkFile(file) || file.isDirectory())&& !PackageInstallerService.isStageName(file.getName());if (!isPackage) {// Ignore entries which are not packagescontinue;}if ((scanFlags & SCAN_DROP_CACHE) != 0) {final PackageCacher cacher = new PackageCacher(mPm.getCacheDir());Log.w(TAG, "Dropping cache of " + file.getAbsolutePath());cacher.cleanCachedResult(file);}parallelPackageParser.submit(file, parseFlags);fileCount++;}
​// Process results one by onefor (; fileCount > 0; fileCount--) {ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();Throwable throwable = parseResult.throwable;int errorCode = PackageManager.INSTALL_SUCCEEDED;String errorMsg = null;
​if (throwable == null) {// TODO(b/194319951): move lower in the scan chain// Static shared libraries have synthetic package namesif (parseResult.parsedPackage.isStaticSharedLibrary()) {PackageManagerService.renameStaticSharedLibraryPackage(parseResult.parsedPackage);}try {addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags,null);} catch (PackageManagerException e) {errorCode = e.error;errorMsg = "Failed to scan " + parseResult.scanFile + ": " + e.getMessage();Slog.w(TAG, errorMsg);}} else if (throwable instanceof PackageManagerException) {PackageManagerException e = (PackageManagerException) throwable;errorCode = e.error;errorMsg = "Failed to parse " + parseResult.scanFile + ": " + e.getMessage();Slog.w(TAG, errorMsg);} else {throw new IllegalStateException("Unexpected exception occurred while parsing "+ parseResult.scanFile, throwable);}
​...}}

通过ParallelPackageParser.submit提交安装任务,ParallelPackageParser.submit.take获取任务结果。

//frameworks/base/services/core/java/com/android/server/pm/ParallelPackageParser.java
public void submit(File scanFile, int parseFlags) {mExecutorService.submit(() -> {ParseResult pr = new ParseResult();Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parallel parsePackage [" + scanFile + "]");try {pr.scanFile = scanFile;pr.parsedPackage = parsePackage(scanFile, parseFlags);} catch (Throwable e) {pr.throwable = e;} finally {Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);}try {mQueue.put(pr);} catch (InterruptedException e) {Thread.currentThread().interrupt();mInterruptedInThread = Thread.currentThread().getName();}});}public ParseResult take() {try {if (mInterruptedInThread != null) {throw new InterruptedException("Interrupted in " + mInterruptedInThread);}return mQueue.take();} catch (InterruptedException e) {// We cannot recover from interrupt hereThread.currentThread().interrupt();throw new IllegalStateException(e);}}

submit和take就是通过一个 BlockingQueue实现解析和获取任务。解析是parsePackage来实现的。

    protected ParsedPackage parsePackage(File scanFile, int parseFlags)throws PackageManagerException {return mPackageParser.parsePackage(scanFile, parseFlags, true, mFrameworkSplits);}

这里的mPackageParser就是前面的参数PackageParser2

//frameworks/base/services/core/java/com/android/server/pm/parsing/PackageParser2.java
public ParsedPackage parsePackage(File packageFile, int flags, boolean useCaches,List<File> frameworkSplits) throws PackageManagerException {//判断缓存是否存在,存在就直接使用缓存if (useCaches && mCacher != null) {ParsedPackage parsed = mCacher.getCachedResult(packageFile, flags);if (parsed != null) {return parsed;}}
​long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;ParseInput input = mSharedResult.get().reset();//解析apk文件ParseResult<ParsingPackage> result = parsingUtils.parsePackage(input, packageFile, flags,frameworkSplits);ParsedPackage parsed = (ParsedPackage) result.getResult().hideAsParsed();long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;//添加到缓存if (mCacher != null) {mCacher.cacheResult(packageFile, flags, parsed);}return parsed;}

又到了parsingUtils.parsePackage

//frameworks/base/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.javapublic ParseResult<ParsingPackage> parsePackage(ParseInput input, File packageFile, int flags,List<File> frameworkSplits) {if (((flags & PARSE_FRAMEWORK_RES_SPLITS) != 0)&& frameworkSplits.size() > 0&& packageFile.getAbsolutePath().endsWith("/framework-res.apk")) {return parseClusterPackage(input, packageFile, frameworkSplits, flags);} else if (packageFile.isDirectory()) {//是一个目录就使用parseClusterPackagereturn parseClusterPackage(input, packageFile, /* frameworkSplits= */null, flags);} else {//是单独一个apk就使用parseMonolithicPackagereturn parseMonolithicPackage(input, packageFile, flags);}}

终于到了解析看下简单的parseMonolithicPackage

  private ParseResult<ParsingPackage> parseMonolithicPackage(ParseInput input, File apkFile,int flags) {//先通过parseMonolithicPackageLite初步解析这个apk,这里会解析出minsdkversion,versionCode 这些基本信息final ParseResult<PackageLite> liteResult =ApkLiteParseUtils.parseMonolithicPackageLite(input, apkFile, flags);if (liteResult.isError()) {return input.error(liteResult);}
​final PackageLite lite = liteResult.getResult();if (mOnlyCoreApps && !lite.isCoreApp()) {return input.error(INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED,"Not a coreApp: " + apkFile);}//AssetManager和文件信息的封装,用于后面使用AssetManager加载资源final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);try {//真正解析apkfinal ParseResult<ParsingPackage> result = parseBaseApk(input,apkFile,apkFile.getCanonicalPath(),assetLoader, flags);if (result.isError()) {return input.error(result);}
​return input.success(result.getResult().setUse32BitAbi(lite.isUse32bitAbi()));} catch (IOException e) {return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,"Failed to get path: " + apkFile, e);} finally {IoUtils.closeQuietly(assetLoader);}}

parseMonolithicPackage先通过parseMonolithicPackageLite来初步处理apk,获取PackageLite。然后调用了parseBaseApk详细处理apk。

private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, File apkFile,String codePath, SplitAssetLoader assetLoader, int flags) {//获取apk文件final String apkPath = apkFile.getAbsolutePath();final AssetManager assets;try {assets = assetLoader.getBaseAssetManager();} catch (IllegalArgumentException e) {return input.error(e.getCause() instanceof IOException ? INSTALL_FAILED_INVALID_APK: INSTALL_PARSE_FAILED_NOT_APK, e.getMessage(), e);}final int cookie = assets.findCookieForPath(apkPath);//创建xml解析对象try (XmlResourceParser parser = assets.openXmlResourceParser(cookie,ANDROID_MANIFEST_FILENAME)) {final Resources res = new Resources(assets, mDisplayMetrics, null);
​ParseResult<ParsingPackage> result = parseBaseApk(input, apkPath, codePath, res,parser, flags);
​final ParsingPackage pkg = result.getResult();....
​return input.success(pkg);} catch (Exception e) {return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,"Failed to read manifest from " + apkPath, e);}}
private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, String apkPath,String codePath, Resources res, XmlResourceParser parser, int flags)throws XmlPullParserException, IOException {...final ParseResult<ParsingPackage> result =parseBaseApkTags(input, pkg, manifestArray, res, parser, flags);...}

层层调用到了parseBaseApkTags来解析androidmanifest中的各个标签。

 private ParseResult<ParsingPackage> parseBaseApkTags(ParseInput input, ParsingPackage pkg,TypedArray sa, Resources res, XmlResourceParser parser, int flags)throws XmlPullParserException, IOException {.....boolean foundApp = false;final int depth = parser.getDepth();int type;while ((type = parser.next()) != XmlPullParser.END_DOCUMENT&& (type != XmlPullParser.END_TAG|| parser.getDepth() > depth)) {if (type != XmlPullParser.START_TAG) {continue;}
​String tagName = parser.getName();final ParseResult result;
​// <application> has special logic, so it's handled outside the general methodif (TAG_APPLICATION.equals(tagName)) {if (foundApp) {if (RIGID_PARSER) {result = input.error("<manifest> has more than one <application>");} else {Slog.w(TAG, "<manifest> has more than one <application>");result = input.success(null);}} else {foundApp = true;result = parseBaseApplication(input, pkg, res, parser, flags);}} else {result = parseBaseApkTag(tagName, input, pkg, res, parser, flags);}.....return input.success(pkg);}

如果是application标签,那么就调用parseBaseApplication方法,因为四大组件等都在这个标签下面,其他通parseBaseApkTag解析。

    private ParseResult<ParsingPackage> parseBaseApplication(ParseInput input,ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags)throws XmlPullParserException, IOException {.....while ((type = parser.next()) != XmlPullParser.END_DOCUMENT&& (type != XmlPullParser.END_TAG|| parser.getDepth() > depth)) {if (type != XmlPullParser.START_TAG) {continue;}
​final ParseResult result;String tagName = parser.getName();boolean isActivity = false;switch (tagName) {case "activity":isActivity = true;// fall-throughcase "receiver":ParseResult<ParsedActivity> activityResult =ParsedActivityUtils.parseActivityOrReceiver(mSeparateProcesses, pkg,res, parser, flags, sUseRoundIcon, null /*defaultSplitName*/,input);
​if (activityResult.isSuccess()) {ParsedActivity activity = activityResult.getResult();if (isActivity) {hasActivityOrder |= (activity.getOrder() != 0);pkg.addActivity(activity);} else {hasReceiverOrder |= (activity.getOrder() != 0);pkg.addReceiver(activity);}}
​result = activityResult;break;.....}

这里就通过解析了标签,根据标签调用不同的解析方法。四大组件的信息PMS就都获取到了。
BOOT_PROGRESS_PMS_SCAN_END

 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,SystemClock.uptimeMillis()); 
mPermissionManager.onStorageVolumeMounted(StorageManager.UUID_PRIVATE_INTERNAL, mIsUpgrade);ver.sdkVersion = mSdkVersion;
​// If this is the first boot or an update from pre-M, and it is a normal// boot, then we need to initialize the default preferred apps across// all defined users.//如果是从M升级或者第一次启动,初始化默认应用if (!mOnlyCore && (mPromoteSystemApps || mFirstBoot)) {for (UserInfo user : mInjector.getUserManagerInternal().getUsers(true)) {mSettings.applyDefaultPreferredAppsLPw(user.id);}}
​//如果是第一次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.getVolumeUuid())) {// No apps are running this early, so no need to freezemAppDataHelper.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.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.//安装Q前的非系统应用程序在Launcher中隐藏他们的图标if (!mOnlyCore && 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 updatedmPromoteSystemApps = false;
​// All the changes are done during package scanning.ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;
​// can downgrade to readert.traceBegin("write settings");writeSettingsLPrTEMP();t.traceEnd();

BOOT_PROGRESS_PMS_READY

EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,SystemClock.uptimeMillis());...
​//权限控制器mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr(computer);mSettings.setPermissionControllerVersion(computer.getPackageInfo(mRequiredPermissionControllerPackage, 0,UserHandle.USER_SYSTEM).getLongVersionCode());
​//指定系统中用于运行应用程序的 Sandbox 应用程序的包名,低于系统要求的最低版本就要运行在Sandbox              应用程序中mRequiredSdkSandboxPackage = getRequiredSdkSandboxPackageName(computer);
​...
​final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();for (int userId : userIds) {userPackages.put(userId, computer.getInstalledPackages(/*flags*/ 0, userId).getList());}//通过mDexManager将用户已经安装的app的dex交给 mDexManager 进行处理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);}
​// Rebuild the live computer since some attributes have been rebuilt.mLiveComputer = createLiveComputer();
​} // synchronized (mLock)} // synchronized (mInstallLock)// CHECKSTYLE:ON IndentationCheck
​mModuleInfoProvider = mInjector.getModuleInfoProvider();
​mInjector.getSystemWrapper().enablePackageCaches();t.traceBegin("GC");//触发gc回收应用资源VMRuntime.getRuntime().requestConcurrentGC();t.traceEnd();
​//圆角资源ParsingPackageUtils.readConfigUseRoundIcon(mContext.getResources());
​mServiceStartWithDelay = SystemClock.uptimeMillis() + (60 * 1000L);

SystemServer.startOtherServices

//frameworks/base/services/java/com/android/server/SystemServer.java       
private void startOtherServices() {...if (!mOnlyCore) {...//如果不是只启动核心应用,查看是否更新mPackageManagerService.updatePackagesIfNeeded();}...// 最终执行performFstrim,完成磁盘维护mPackageManagerService.performFstrimIfNeeded();...//PKMS准备就绪mPackageManagerService.systemReady();...
}

到这里PackageManagerService就初始化成功了。


PMS 是学习了解Framework底层原理的核心知识点之一,在Framework底层原理中除了WMS要学习以外,还有Binder、Handler、AMS、PMS……等知识点都要学习,这样才能全面的了解Framework底层原理,为了帮助大家可以更快速的掌握理解这个版块的知识点,这边整理了 《Framework 学习手册》,里面将其Framework中所有的知识点记录在册了,希望能给大家有效的帮助。

《Android Framework学习手册》:https://qr18.cn/AQpN4J

  1. 开机Init 进程
  2. 开机启动 Zygote 进程
  3. 开机启动 SystemServer 进程
  4. Binder 驱动
  5. AMS 的启动过程
  6. PMS 的启动过程
  7. Launcher 的启动过程
  8. Android 四大组件
  9. Android 系统服务 - Input 事件的分发过程
  10. Android 底层渲染 - 屏幕刷新机制源码分析
  11. Android 源码分析实战

Android13 PMS是如何启动的?