PackageManagerService 启动流程源码解析
<h2>概述</h2> <p>PackageManagerService,是Android系统中核心服务之一,管理着所有跟package相关的工作,常见的比如安装、卸载应用。 PKMS服务也是通过binder进行通信,IPackageManager.aidl由工具转换后自动生成binder的服务端IPackageManager.Stub和客户端IPackageManager.Stub.Proxy,具体关系如下:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/94b0a76151095e857fc3b17bafb7e0f9.png"></p> <p>Binder服务端:PackageManagerService继承于IPackageManager.Stub;</p> <p>Binder客户端:ApplicationPackageManager(简称APM)的成员变量mPM继承于IPackageManager.Stub.Proxy; 本身APM是继承于PackageManager对象。</p> <p>Android系统启动过程中,一路启动到SystemServer后,便可以启动framework的各大服务,本篇博客将介绍PKMS的启动过程(基于安卓7.0源码)。</p> <h2>PackageManagerService的启动</h2> <p>SystemServer启动过程中涉及到的PKMS代码如下:</p> <pre> <code class="language-java">private void startBootstrapServices() { //启动installer服务 Installer installer = mSystemServiceManager.startService(Installer.class); ... //处于加密状态则仅仅解析核心应用 String cryptState = SystemProperties.get("vold.decrypt"); if (ENCRYPTING_STATE.equals(cryptState)) { mOnlyCore = true; // ENCRYPTING_STATE = "trigger_restart_min_framework" } else if (ENCRYPTED_STATE.equals(cryptState)) { mOnlyCore = true; // ENCRYPTED_STATE = "1" } //创建PKMS对象 mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); //PKMS是否首次启动 mFirstBoot = mPackageManagerService.isFirstBoot(); mPackageManager = mSystemContext.getPackageManager(); ... }</code></pre> <p>PackageManagerService与其他所有的服务一样,也是由SystemServer启动,它也是java层服务之一,PKMS.main()过程主要是创建PKMS服务,并注册到ServiceManager。</p> <p>整个system_server进程启动过程,涉及PKMS服务的主要几个动作如下,接下来分别讲解每个过程</p> <p>PKMS.main()</p> <p>PKMS.performBootDexOpt</p> <p>PKMS.systemReady</p> <h2>PKMS.main()</h2> <pre> <code class="language-java">public static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { // Self-check for initial settings. PackageManagerServiceCompilerMapping.checkProperties(); //构造一个包管理服务对象 PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore); m.enableSystemUserPackages(); // Disable any carrier apps. We do this very early in boot to prevent the apps from being // disabled after already being started. CarrierAppUtils.disableCarrierAppsUntilPrivileged(context.getOpPackageName(), m, UserHandle.USER_SYSTEM); //将包管理服务对象添加到ServiceManager ServiceManager.addService("package", m); return m; }</code></pre> <p>该方法的主要功能创建PKMS对象,并将其注册到ServiceManager。 关于PKMS对象的构造方法很长,分为以下几个阶段,每个阶段会输出相应的EventLog: 除了阶段1的开头部分代码,后续代码都是同时持有同步锁mPackages和mInstallLock的过程中执行的。</p> <p>阶段1:BOOT_PROGRESS_PMS_START</p> <p>阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START</p> <p>阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START</p> <p>阶段4:BOOT_PROGRESS_PMS_SCAN_END</p> <p>阶段5:BOOT_PROGRESS_PMS_READY</p> <h2>阶段1:BOOT_PROGRESS_PMS_START</h2> <p>阶段1 PMS_START有两部分组成,由无需加锁的前部分和同时持有两个锁的后半部分,先来说说前半部分:</p> <p>前半部分</p> <pre> <code class="language-java">//向事件日志写入事件,标识PackageManagerService启动 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, SystemClock.uptimeMillis()); //SDK版本检查 if (mSdkVersion <= 0) { Slog.w(TAG, "**** ro.build.version.sdk not set!"); } mContext = context; //开机模式是否为工厂模式 mFactoryTest = factoryTest; //是否仅启动内核 mOnlyCore = onlyCore; //构造DisplayMetrics对象以便获取尺寸数据 mMetrics = new DisplayMetrics(); //构造Settings对象存储运行时的设置信息 mSettings = new Settings(mPackages); //添加一些用户uid 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); //判断是否在不同的进程 String separateProcesses = SystemProperties.get("debug.separate_processes"); if (separateProcesses != null && separateProcesses.length() > 0) { if ("*".equals(separateProcesses)) { mDefParseFlags = PackageParser.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; } //installer由SystemServer构造,这里通过该对象与底层进行通信,进行具体安装与卸载的操作 mInstaller = installer; //创建PackageDexOptimizer,该类用于辅助进行dex优化 mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context, "*dexopt*"); mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper()); mOnPermissionChangeListeners = new OnPermissionChangeListeners( FgThread.get().getLooper()); getDefaultDisplayMetrics(context, mMetrics); //获取系统配置信息 SystemConfig systemConfig = SystemConfig.getInstance(); mGlobalGids = systemConfig.getGlobalGids(); mSystemPermissions = systemConfig.getSystemPermissions(); mAvailableFeatures = systemConfig.getAvailableFeatures();</code></pre> <p>接下来,再来看看后半部分:</p> <pre> <code class="language-java">synchronized (mInstallLock) { // writer synchronized (mPackages) { //启动消息处理线程 mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/); mHandlerThread.start(); //通过消息处理线程的Looper对象构造一个处理消息的Handler对象 mHandler = new PackageHandler(mHandlerThread.getLooper()); mProcessLoggingHandler = new ProcessLoggingHandler(); //使用看门狗检测当前消息处理线程 Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT); //获取当前的Data目录 File dataDir = Environment.getDataDirectory(); mAppInstallDir = new File(dataDir, "app"); mAppLib32InstallDir = new File(dataDir, "app-lib"); mEphemeralInstallDir = new File(dataDir, "app-ephemeral"); mAsecInternalPath = new File(dataDir, "app-asec").getPath(); mDrmAppPrivateInstallDir = new File(dataDir, "app-private"); //构造UserManagerService对象,创建用户管理服务 sUserManager = new UserManagerService(context, this, mPackages); // Propagate permission configuration in to package manager. //读取权限配置文件中的信息,保存到mPermissions这个ArrayMap中 ArrayMap<String, SystemConfig.PermissionEntry> permConfig = systemConfig.getPermissions(); for (int i=0; i<permConfig.size(); i++) { SystemConfig.PermissionEntry perm = permConfig.valueAt(i); BasePermission bp = mSettings.mPermissions.get(perm.name); if (bp == null) { bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN); mSettings.mPermissions.put(perm.name, bp); } if (perm.gids != null) { bp.setGids(perm.gids, perm.perUser); } } //获取所有外部lib ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries(); for (int i=0; i<libConfig.size(); i++) { mSharedLibraries.put(libConfig.keyAt(i), new SharedLibraryEntry(libConfig.valueAt(i), null)); } //尝试读取mac_permissions.xml并解析 mFoundPolicyFile = SELinuxMMAC.readInstallPolicy(); //读取并解析packages-backup.xml等文件 mRestoredSettings = mSettings.readLPw(sUserManager.getUsers(false)); //判断是否自定义的解析界面 String customResolverActivity = Resources.getSystem().getString( R.string.config_customResolverActivity); if (TextUtils.isEmpty(customResolverActivity)) { customResolverActivity = null; } else { mCustomResolverComponentName = ComponentName.unflattenFromString( customResolverActivity); } ................ }</code></pre> <p>这个过程涉及的几个重要变量:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/b52e72eac1eab769cc019a69d0c6b6af.png"></p> <p>创建Settings</p> <p>在阶段1中创建了Settings对象,我们看看里面做了什么</p> <pre> <code class="language-java">Settings(File dataDir, Object lock) { mLock = lock; mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock); mSystemDir = new File(dataDir, "system"); mSystemDir.mkdirs();//创建/data/system 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"); }</code></pre> <p>此处mSystemDir是指目录/data/system,在该目录有以下5个文件:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/c477e532cf518d7730a8a6a3f9b4060d.png"></p> <p>SystemConfig阶段1中还调用SystemConfig.getInstance()方法来获取SystemConfig</p> <pre> <code class="language-java">public static SystemConfig getInstance() { synchronized (SystemConfig.class) { if (sInstance == null) { sInstance = new SystemConfig(); } return sInstance; } }</code></pre> <pre> <code class="language-java">SystemConfig() { // Read configuration from system readPermissions(Environment.buildPath( Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL); // Read configuration from the old permissions dir readPermissions(Environment.buildPath( Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL); // Allow ODM to customize system configs around libs, features and apps int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS; readPermissions(Environment.buildPath( Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag); readPermissions(Environment.buildPath( Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag); // Only allow OEM to customize features readPermissions(Environment.buildPath( Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES); readPermissions(Environment.buildPath( Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES); }</code></pre> <p>readPermissions()解析指定目录下的所有xml文件,比如将标签所指的动态库保存到 PKMS的成员变量mSharedLibraries。可见,SystemConfig创建过程是对以下这六个目录中的所有xml进行解析:</p> <p>/system/etc/sysconfig</p> <p>/system/etc/permissions</p> <p>/odm/etc/sysconfig</p> <p>/odm/etc/permissions</p> <p>/oem/etc/sysconfig</p> <p>/oem/etc/permissions</p> <p>SystemConfig.readPermissions</p> <pre> <code class="language-java">void readPermissions(File libraryDir, int permissionFlag) { // Read permissions from given directory. if (!libraryDir.exists() || !libraryDir.isDirectory()) { if (permissionFlag == ALLOW_ALL) { Slog.w(TAG, "No directory " + libraryDir + ", skipping"); } return; } if (!libraryDir.canRead()) { Slog.w(TAG, "Directory " + libraryDir + " cannot be read"); return; } // Iterate over the files in the directory and scan .xml files File platformFile = null; for (File f : libraryDir.listFiles()) { // We'll read platform.xml last if (f.getPath().endsWith("etc/permissions/platform.xml")) { platformFile = f; continue; } if (!f.getPath().endsWith(".xml")) { Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring"); continue; } if (!f.canRead()) { Slog.w(TAG, "Permissions library file " + f + " cannot be read"); continue; } readPermissionsFromXml(f, permissionFlag); } // Read platform permissions last so it will take precedence if (platformFile != null) { readPermissionsFromXml(platformFile, permissionFlag); } }</code></pre> <p>该方法是解析指定目录下所有的具有可读权限的,且以xml后缀文件。</p> <h2>阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START</h2> <pre> <code class="language-java">//标记扫描开始的时间 long startTime = SystemClock.uptimeMillis(); //将扫描开始的事件写入日志 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START, startTime); // Set flag to monitor and not change apk file paths when // scanning install directories. //设置扫描的模式 final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING | SCAN_INITIAL; //获取java启动类库的路径 final String bootClassPath = System.getenv("BOOTCLASSPATH"); //获取systemServer的路径 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 List<String> allInstructionSets = InstructionSets.getAllInstructionSets(); final String[] dexCodeInstructionSets = getDexCodeInstructionSets( allInstructionSets.toArray(new String[allInstructionSets.size()])); /** * Ensure all external libraries have had dexopt run on them. */ //确保所有的外部lib都被dexopt优化 if (mSharedLibraries.size() > 0) { // NOTE: For now, we're compiling these system "shared libraries" // (and framework jars) into all available architectures. It's possible // to compile them only when we come across an app that uses them (there's // already logic for that in scanPackageLI) but that adds some complexity. for (String dexCodeInstructionSet : dexCodeInstructionSets) { for (SharedLibraryEntry libEntry : mSharedLibraries.values()) { final String lib = libEntry.path; if (lib == null) { continue; } try { // Shared libraries do not have profiles so we perform a full // AOT compilation (if needed). int dexoptNeeded = DexFile.getDexOptNeeded( lib, dexCodeInstructionSet, getCompilerFilterForReason(REASON_SHARED_APK), false /* newProfile */); if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) { mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet, dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/, getCompilerFilterForReason(REASON_SHARED_APK), StorageManager.UUID_PRIVATE_INTERNAL, SKIP_SHARED_LIBRARY_CHECK); } } catch (FileNotFoundException e) { Slog.w(TAG, "Library not found: " + lib); } catch (IOException | InstallerException e) { Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? " + e.getMessage()); } } } } File frameworkDir = new File(Environment.getRootDirectory(), "framework"); final VersionInfo ver = mSettings.getInternalVersion(); mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint); // when upgrading from pre-M, promote system app permissions from install to runtime mPromoteSystemApps = mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1; // When upgrading from pre-N, we need to handle package extraction like first boot, // as there is no profiling data available. mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N; // save off the names of pre-existing system packages prior to scanning; we don't // want to automatically grant runtime permissions for new system apps if (mPromoteSystemApps) { Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator(); while (pkgSettingIter.hasNext()) { PackageSetting ps = pkgSettingIter.next(); if (isSystemApp(ps)) { mExistingSystemPackages.add(ps.name); } } } // Collect vendor overlay packages. // (Do this before scanning any apps.) // For security and version matching reason, only consider // overlay packages if they reside in VENDOR_OVERLAY_DIR. //收集供应商包名:/vendor/overlay File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR); scanDirTracedLI(vendorOverlayDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0); // Find base frameworks (resource packages without code). //扫描frameworkDir目录下的apk进行安装,扫描模式为非优化模式 scanDirTracedLI(frameworkDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED, scanFlags | SCAN_NO_DEX, 0); // Collected privileged system packages. final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app"); scanDirTracedLI(privilegedAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0); // Collect ordinary system packages. final File systemAppDir = new File(Environment.getRootDirectory(), "app"); scanDirTracedLI(systemAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0); // Collect all vendor packages. File vendorAppDir = new File("/vendor/app"); try { vendorAppDir = vendorAppDir.getCanonicalFile(); } catch (IOException e) { // failed to look up canonical path, continue with original one } scanDirTracedLI(vendorAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0); // Collect all OEM packages. final File oemAppDir = new File(Environment.getOemDirectory(), "app"); scanDirTracedLI(oemAppDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0); // Prune any system packages that no longer exist. //构造一个List来存放不存在的packages路径 final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>(); if (!mOnlyCore) { //遍历mSettings.mPackages Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator(); while (psit.hasNext()) { PackageSetting ps = psit.next(); /* * If this is not a system app, it can't be a * disable system app. */ //如果不是系统app,不处理 if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) { continue; } /* * If the package is scanned, it's not erased. */ final PackageParser.Package scannedPkg = mPackages.get(ps.name); if (scannedPkg != null) { /* * If the system app is both scanned and in the * disabled packages list, then it must have been * added via OTA. Remove it from the currently * scanned package so the previously user-installed * application can be scanned. */ //如果在disable列表中,那么,说明它是通过OTA方式进行升级更新添加的,因此,清楚相应数据 if (mSettings.isDisabledSystemPackageLPr(ps.name)) { logCriticalInfo(Log.WARN, "Expecting better updated system app for " + ps.name + "; removing system app. Last known codePath=" + ps.codePathString + ", installStatus=" + ps.installStatus + ", versionCode=" + ps.versionCode + "; scanned versionCode=" + scannedPkg.mVersionCode); //移除其信息 removePackageLI(scannedPkg, true); mExpectingBetter.put(ps.name, ps.codePath); } continue; } //如果不在disable列表中,则直接清楚相应的数据 if (!mSettings.isDisabledSystemPackageLPr(ps.name)) { psit.remove(); logCriticalInfo(Log.WARN, "System package " + ps.name + " no longer exists; it's data will be wiped"); // Actual deletion of code and data will be handled by later // reconciliation step } else { //否则,通过codePath判断其是否有可能被更新或删除 final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name); if (disabledPs.codePath == null || !disabledPs.codePath.exists()) { possiblyDeletedUpdatedSystemApps.add(ps.name); } } } } //look for any incomplete package installations //获取未完成安装的apk包的PackageSetting列表 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr(); //清除未安装的安装包 for (int i = 0; i < deletePkgsList.size(); i++) { // Actual deletion of code and data will be handled by later // reconciliation step final String packageName = deletePkgsList.get(i).name; logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + packageName); synchronized (mPackages) { mSettings.removePackageLPw(packageName); } } //delete tmp files //清除临时文件 deleteTempPackageFiles(); // Remove any shared userIDs that have no associated packages //清除在mSettings中没有被使用的SharedUserSettings mSettings.pruneSharedUsersLPw();</code></pre> <p>环境变量: 那可通过adb shell env来查看系统所有的环境变量及相应值。也可通过命令adb shell echo $SYSTEMSERVERCLASSPATH。</p> <p>SYSTEMSERVERCLASSPATH:主要包括/system/framework目录下services.jar,ethernet-service.jar,wifi-service.jar这3个文件。</p> <p>BOOTCLASSPATH:该环境变量内容较多,不同ROM可能有所不同,常见内容包含/system/framework目录下的framework.jar,ext.jar,core-libart.jar,telephony-common.jar,ims-common.jar,core-junit.jar等文件。</p> <p>scanDirLI(): 扫描指定目录下的apk文件,最终调用PackageParser.parseBaseApk来完成AndroidManifest.xml文件的解析,生成Application, activity,service,broadcast, provider等信息。</p> <p>/vendor/overlay</p> <p>/system/framework</p> <p>/system/priv-app</p> <p>/system/app</p> <p>/vendor/priv-app</p> <p>/vendor/app</p> <p>/oem/app</p> <h2>阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START</h2> <pre> <code class="language-java">// Remove any shared userIDs that have no associated packages //清除在mSettings中没有被使用的SharedUserSettings mSettings.pruneSharedUsersLPw(); //如果是普通模式,则需要进行一些额外处理 if (!mOnlyCore) { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START, SystemClock.uptimeMillis()); //扫描该目录 scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0); scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags | PackageParser.PARSE_FORWARD_LOCK, scanFlags | SCAN_REQUIRE_KNOWN, 0); scanDirLI(mEphemeralInstallDir, mDefParseFlags | PackageParser.PARSE_IS_EPHEMERAL, scanFlags | SCAN_REQUIRE_KNOWN, 0); /** * Remove disable package settings for any updated system * apps that were removed via an OTA. If they're not a * previously-updated app, remove them completely. * Otherwise, just revoke their system-level permissions. */ //后面这部分代码逻辑简单,就是遍历possiblyDeletedUpdatedSystemApps,处理通过OTA更新和删除的APK文件 for (String deletedAppName : possiblyDeletedUpdatedSystemApps) { PackageParser.Package deletedPkg = mPackages.get(deletedAppName); mSettings.removeDisabledSystemPackageLPw(deletedAppName); String msg; if (deletedPkg == null) { msg = "Updated system package " + deletedAppName + " no longer exists; it's data will be wiped"; // Actual deletion of code and data will be handled by later // reconciliation step } else { msg = "Updated system app + " + deletedAppName + " no longer present; removing system privileges for " + deletedAppName; deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM; PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName); deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM; } logCriticalInfo(Log.WARN, msg); } /** * 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"); int reparseFlags = mDefParseFlags; if (FileUtils.contains(privilegedAppDir, scanFile)) { reparseFlags = PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED; } else if (FileUtils.contains(systemAppDir, scanFile)) { reparseFlags = PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR; } else if (FileUtils.contains(vendorAppDir, scanFile)) { reparseFlags = PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR; } else if (FileUtils.contains(oemAppDir, scanFile)) { reparseFlags = PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR; } else { Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile); continue; } mSettings.enableSystemPackageLPw(packageName); try { scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null); } catch (PackageManagerException e) { Slog.e(TAG, "Failed to parse original system package: " + e.getMessage()); } } } } mExpectingBetter.clear(); // Resolve protected action filters. Only the setup wizard is allowed to // have a high priority filter for these actions. mSetupWizardPackage = getSetupWizardPackageName(); if (mProtectedFilters.size() > 0) { if (DEBUG_FILTERS && mSetupWizardPackage == null) { Slog.i(TAG, "No setup wizard;" + " All protected intents capped to priority 0"); } for (ActivityIntentInfo filter : mProtectedFilters) { if (filter.activity.info.packageName.equals(mSetupWizardPackage)) { if (DEBUG_FILTERS) { Slog.i(TAG, "Found setup wizard;" + " allow priority " + filter.getPriority() + ";" + " package: " + filter.activity.info.packageName + " activity: " + filter.activity.className + " priority: " + filter.getPriority()); } // skip setup wizard; allow it to keep the high priority filter continue; } Slog.w(TAG, "Protected action; cap priority to 0;" + " package: " + filter.activity.info.packageName + " activity: " + filter.activity.className + " origPrio: " + filter.getPriority()); filter.setPriority(0); } } mDeferProtectedFilters = false; mProtectedFilters.clear(); // Now that we know all of the shared libraries, update all clients to have // the correct library paths. //给需要使用shared libraries的package找到相应的路径,并将其保存至package的usesLibraryFiles中 updateAllSharedLibrariesLPw(); 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. adjustCpuAbisForSharedUserLPw(setting.packages, null /* scanned package */, false /* boot complete */); } // Now that we know all the packages we are keeping, // read and update their last usage times. mPackageUsage.readLP();</code></pre> <p>当mOnlyCore = false时,则scanDirLI()还会收集如下目录中的apk</p> <p>/data/app</p> <p>/data/app-private</p> <h2>阶段4:BOOT_PROGRESS_PMS_SCAN_END</h2> <pre> <code class="language-java">EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END, SystemClock.uptimeMillis()); Slog.i(TAG, "Time to scan packages: " + ((SystemClock.uptimeMillis()-startTime)/1000f) + " seconds"); // If the platform SDK 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. int updateFlags = UPDATE_PERMISSIONS_ALL; if (ver.sdkVersion != mSdkVersion) { Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to " + mSdkVersion + "; regranting permissions for internal storage"); updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL; } //当sdk版本不一致时,,更新相关信息,并给需要使用权限的apk分配相应的权限 updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags); 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. //当这是ota后的首次启动,正常启动则需要清除目录的缓存代码 if (!onlyCore && (mPromoteSystemApps || !mRestoredSettings)) { for (UserInfo user : sUserManager.getUsers(true)) { mSettings.applyDefaultPreferredAppsLPw(this, user.id); applyFactoryDefaultBrowserLPw(user.id); primeDomainVerificationsLPw(user.id); } } // Prepare storage for system user really early during boot, // since core system apps like SettingsProvider and SystemUI // can't wait for user to start final int storageFlags; if (StorageManager.isFileEncryptedNativeOrEmulated()) { storageFlags = StorageManager.FLAG_STORAGE_DE; } else { storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; } reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM, storageFlags); // If this is first boot after an OTA, and a normal boot, 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). if (mIsUpgrade && !onlyCore) { Slog.i(TAG, "Build fingerprint changed; clearing code caches"); for (int i = 0; i < mSettings.mPackages.size(); i++) { final PackageSetting ps = mSettings.mPackages.valueAt(i); if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) { // No apps are running this early, so no need to freeze clearAppDataLIF(ps.pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); } } ver.fingerprint = Build.FINGERPRINT; } checkDefaultBrowser(); // clear only after permissions and other defaults have been updated //当权限和其他默认项都完成更新,则清理相关信息 mExistingSystemPackages.clear(); mPromoteSystemApps = false; // All the changes are done during package scanning. ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION; // can downgrade to reader //信息写回packages.xml文件 mSettings.writeLPr(); // Perform dexopt on all apps that mark themselves as coreApps. We do this pretty // early on (before the package manager declares itself as early) because other // components in the system server might ask for package contexts for these apps. // // Note that "onlyCore" in this context means the system is encrypted or encrypting // (i.e, that the data partition is unavailable). if ((isFirstBoot() || isUpgrade() || VMRuntime.didPruneDalvikCache()) && !onlyCore) { long start = System.nanoTime(); List<PackageParser.Package> coreApps = new ArrayList<>(); for (PackageParser.Package pkg : mPackages.values()) { if (pkg.coreApp) { coreApps.add(pkg); } } int[] stats = performDexOpt(coreApps, false, getCompilerFilterForReason(REASON_CORE_APP)); final int elapsedTimeSeconds = (int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start); MetricsLogger.histogram(mContext, "opt_coreapps_time_s", elapsedTimeSeconds); if (DEBUG_DEXOPT) { Slog.i(TAG, "Dex-opt core apps took : " + elapsedTimeSeconds + " seconds (" + stats[0] + ", " + stats[1] + ", " + stats[2] + ")"); } // TODO: Should we log these stats to tron too ? // MetricsLogger.histogram(mContext, "opt_coreapps_num_dexopted", stats[0]); // MetricsLogger.histogram(mContext, "opt_coreapps_num_skipped", stats[1]); // MetricsLogger.histogram(mContext, "opt_coreapps_num_failed", stats[2]); // MetricsLogger.histogram(mContext, "opt_coreapps_num_total", coreApps.size()); }</code></pre> <h2>阶段5:BOOT_PROGRESS_PMS_READY</h2> <pre> <code class="language-java">EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis()); if (!mOnlyCore) { mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr(); mRequiredInstallerPackage = getRequiredInstallerLPr(); mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr(); mIntentFilterVerifier = new IntentVerifierProxy(mContext, mIntentFilterVerifierComponent); mServicesSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr( PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES); mSharedSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr( PackageManager.SYSTEM_SHARED_LIBRARY_SHARED); } else { mRequiredVerifierPackage = null; mRequiredInstallerPackage = null; mIntentFilterVerifierComponent = null; mIntentFilterVerifier = null; mServicesSystemSharedLibraryPackageName = null; mSharedSystemSharedLibraryPackageName = null; } mInstallerService = new PackageInstallerService(context, this); final ComponentName ephemeralResolverComponent = getEphemeralResolverLPr(); final ComponentName ephemeralInstallerComponent = getEphemeralInstallerLPr(); // both the installer and resolver must be present to enable ephemeral if (ephemeralInstallerComponent != null && ephemeralResolverComponent != null) { if (DEBUG_EPHEMERAL) { Slog.i(TAG, "Ephemeral activated; resolver: " + ephemeralResolverComponent + " installer:" + ephemeralInstallerComponent); } mEphemeralResolverComponent = ephemeralResolverComponent; mEphemeralInstallerComponent = ephemeralInstallerComponent; setUpEphemeralInstallerActivityLP(mEphemeralInstallerComponent); mEphemeralResolverConnection = new EphemeralResolverConnection(mContext, mEphemeralResolverComponent); } else { if (DEBUG_EPHEMERAL) { final String missingComponent = (ephemeralResolverComponent == null) ? (ephemeralInstallerComponent == null) ? "resolver and installer" : "resolver" : "installer"; Slog.i(TAG, "Ephemeral deactivated; missing " + missingComponent); } mEphemeralResolverComponent = null; mEphemeralInstallerComponent = null; mEphemeralResolverConnection = null; } mEphemeralApplicationRegistry = new EphemeralApplicationRegistry(this); } // synchronized (mPackages) } // synchronized (mInstallLock) // Now after opening every single application zip, make sure they // are all flushed. Not really needed, but keeps things nice and // tidy. Runtime.getRuntime().gc(); // The initial scanning above does many calls into installd while // holding the mPackages lock, but we're mostly interested in yelling // once we have a booted system. mInstaller.setWarnIfHeld(mPackages); // Expose private service for system components to use. LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());</code></pre> <p>PKMS初始化完成阶段,还会创建一个PackageInstaller服务。</p> <pre> <code class="language-java">public PackageInstallerService(Context context, PackageManagerService pm) { mContext = context; mPm = pm; //创建名为”PackageInstaller“的Handler线程 mInstallThread = new HandlerThread(TAG); mInstallThread.start(); mInstallHandler = new Handler(mInstallThread.getLooper()); mCallbacks = new Callbacks(mInstallThread.getLooper()); mSessionsFile = new AtomicFile( new File(Environment.getSystemSecureDirectory(), "install_sessions.xml")); mSessionsDir = new File(Environment.getSystemSecureDirectory(), "install_sessions"); mSessionsDir.mkdirs(); synchronized (mSessions) { readSessionsLocked(); reconcileStagesLocked(StorageManager.UUID_PRIVATE_INTERNAL); final ArraySet<File> unclaimedIcons = newArraySet( mSessionsDir.listFiles()); for (int i = 0; i < mSessions.size(); i++) { final PackageInstallerSession session = mSessions.valueAt(i); unclaimedIcons.remove(buildAppIconFile(session.sessionId)); } for (File icon : unclaimedIcons) { icon.delete(); } } }</code></pre> <p>PKMS初始化过程,分为5个阶段:</p> <p><strong>PMS_START阶段:</strong></p> <p>创建Settings对象;</p> <p>将6类shareUserId到mSettings;</p> <p>初始化SystemConfig;</p> <p>创建名为“PackageManager”的handler线程mHandlerThread;</p> <p>创建UserManagerService多用户管理服务;</p> <p>通过解析4大目录中的xmL文件构造共享mSharedLibraries;</p> <p><strong>PMS_SYSTEM_SCAN_START阶段:</strong></p> <p>扫描系统apk;</p> <p><strong>PMS_DATA_SCAN_START阶段:</strong></p> <p>扫描/data/app目录下的apk;</p> <p>扫描/data/app-private目录下的apk;</p> <p><strong>PMS_SCAN_END阶段:</strong></p> <p>将上述信息写回/data/system/packages.xml;</p> <p>PMS_READY阶段:创建服务PackageInstallerService;</p> <h2>PKMS.systemReady</h2> <pre> <code class="language-java">@Override public void systemReady() { mSystemReady = true; // Read the compatibilty setting when the system is ready. boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt( mContext.getContentResolver(), android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1; PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled); if (DEBUG_SETTINGS) { Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled); } int[] grantPermissionsUserIds = EMPTY_INT_ARRAY; synchronized (mPackages) { // Verify that all of the preferred activity components actually // exist. It is possible for applications to be updated and at // that point remove a previously declared activity component that // had been set as a preferred activity. We try to clean this up // the next time we encounter that preferred activity, but it is // possible for the user flow to never be able to return to that // situation so here we do a sanity check to make sure we haven't // left any junk around. ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>(); for (int i=0; i<mSettings.mPreferredActivities.size(); i++) { PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i); removed.clear(); for (PreferredActivity pa : pir.filterSet()) { if (mActivities.mActivities.get(pa.mPref.mComponent) == null) { removed.add(pa); } } if (removed.size() > 0) { for (int r=0; r<removed.size(); r++) { PreferredActivity pa = removed.get(r); Slog.w(TAG, "Removing dangling preferred activity: " + pa.mPref.mComponent); pir.removeFilter(pa); } mSettings.writePackageRestrictionsLPr( mSettings.mPreferredActivities.keyAt(i)); } } for (int userId : UserManagerService.getInstance().getUserIds()) { if (!mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) { grantPermissionsUserIds = ArrayUtils.appendInt( grantPermissionsUserIds, userId); } } } sUserManager.systemReady();//多用户服务 // If we upgraded grant all default permissions before kicking off. //升级所有已获取的默认权限 for (int userId : grantPermissionsUserIds) { mDefaultPermissionPolicy.grantDefaultPermissions(userId); } // Kick off any messages waiting for system ready //处理所有等待系统准备就绪的消息 if (mPostSystemReadyMessages != null) { for (Message msg : mPostSystemReadyMessages) { msg.sendToTarget(); } mPostSystemReadyMessages = null; } // Watch for external volumes that come and go over time //观察外部存储设备 final StorageManager storage = mContext.getSystemService(StorageManager.class); storage.registerListener(mStorageListener); mInstallerService.systemReady(); mPackageDexOptimizer.systemReady(); MountServiceInternal mountServiceInternal = LocalServices.getService( MountServiceInternal.class); mountServiceInternal.addExternalStoragePolicy( new MountServiceInternal.ExternalStorageMountPolicy() { @Override public int getMountMode(int uid, String packageName) { if (Process.isIsolated(uid)) { return Zygote.MOUNT_EXTERNAL_NONE; } if (checkUidPermission(WRITE_MEDIA_STORAGE, uid) == PERMISSION_GRANTED) { return Zygote.MOUNT_EXTERNAL_DEFAULT; } if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) { return Zygote.MOUNT_EXTERNAL_DEFAULT; } if (checkUidPermission(WRITE_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) { return Zygote.MOUNT_EXTERNAL_READ; } return Zygote.MOUNT_EXTERNAL_WRITE; } @Override public boolean hasExternalStorage(int uid, String packageName) { return true; } }); // Now that we're mostly running, clean up stale users and apps reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL); reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL); }</code></pre> <p>至此,PackageManagerService启动流程分析完毕,如有错误之处,欢迎留言指正。</p> <p> </p> <p>来自:http://blog.csdn.net/u012124438/article/details/54882771</p> <p> </p>
本文由用户 weizhenggen 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
转载本站原创文章,请注明出处,并保留原始链接、图片水印。
本站是一个以用户分享为主的开源技术平台,欢迎各类分享!