PackageManagerService 启动流程源码解析

weizhenggen 7年前
   <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>