The starting chapter of PackageManagerService principle

Posted by mdmann on Mon, 28 Feb 2022 15:10:21 +0100

PackageManagerService is a very important module in the Android framework. It is related to application installation, uninstallation, Intent matching, package parsing, etc. Next, start PackageManagerService and get PackageManager object in Context to deal with the whole process.

  this article is based on Android 10 source code analysis. There may be slight differences in other versions, but the overall process is almost the same. The classes involved are:

frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/core/java/android/content/pm/IPackageManager.aidl
frameworks/base/core/java/android/content/pm/PakcageManager.java
frameworks/base/core/java/android/app/ApplicationPakcageManager.java
frameworks/base/services/core/java/com/android/server/pm/PakcageManagerservice.java
frameworks/base/core/java/android/os/ServiceManagerNative.java

The article directory structure is as follows:

PackageManagerService started

  PackageManagerService (hereinafter referred to as PMS) is pulled up during the startup of the SystemServer process. The specific sequence is as follows:

//frameworks/base/services/java/com/android/server/SystemServer.java
private void startBootstrapServices() {
     // Omit some codes
     Installer installer = mSystemServiceManager.startService(Installer.class);
     //Omit part of the code
     //Call PackageManagerService Main() method to create PackageManagerService object
     mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
             mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
     mFirstBoot = mPackageManagerService.isFirstBoot();
     mPackageManager = mSystemContext.getPackageManager();
     if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
         MetricsLogger.histogram(null, "boot_package_manager_init_ready",
                 (int) SystemClock.elapsedRealtime());
     }
     // Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename
     // A/B artifacts after boot, before anything else might touch/need them.
     // Note: this isn't needed during decryption (we don't have /data anyways).
     if (!mOnlyCore) {
         boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",false);
         if (!disableOtaDexopt) {
             traceBeginAndSlog("StartOtaDexOptService");
             try {
                 OtaDexoptService.main(mSystemContext, mPackageManagerService);
             } catch (Throwable e) {
                 reportWtf("starting OtaDexOptService", e);
             } finally {
                 traceEnd();
             }
         }
     }
 }

  you can see that the PackageManagerService object is in systemserver Created in the startbootstrapservices () method, let's take a look at PackageManagerService Main() method.

//frameworks/base/services/core/java/com/android/server/pm/PakcageManagerservice.java
public static PackageManagerService main(Context context, Installer installer,
        boolean factoryTest, boolean onlyCore) {
    //Test PM dexopt. Whether the system attribute of type XXX is set and whether the value is legal
    PackageManagerServiceCompilerMapping.checkProperties();
    //Create PackageManagerService object
    PackageManagerService m = new PackageManagerService(context, installer,
            factoryTest, onlyCore);
    m.enableSystemUserPackages();
    ServiceManager.addService("package", m);
    //Create PackageManagerNative object
    final PackageManagerNative pmn = m.new PackageManagerNative();
    ServiceManager.addService("package_native", pmn);
    return m;
}

Before understanding the initialization of PackageManagerService object, let's take a look at the class diagram related to PackageManagerService

  • IPackageManager: AIDL interface, which defines the methods provided by PackageManagerService.
  • PackageManagerService: the implementation class of IPackageManager interface, which implements IPackageManager Methods defined in Aidl.
  • Installer: system service, which is actually an installd client. It is used to provide application installation, uninstallation and other interfaces.
  • PackageManager: PackageManagerService is an abstract class that provides an interface to the application layer. The application obtains the PackageManager object through the getPackageManager() abstract method of Context; The final implementation is to return the ApplicationPackageManager object in the getPackageManager() method of ContextImpl.
  • ApplicationPackageManager: subclass of PackageManager, which depends on PakcageManagerService. The functions of the implemented abstract methods are implemented through PackageManagerService. In this way, the application PackageManager associates the application layer interface PackageManager with PackageManagerService.
  • PackageManagerInternal: PackageManagerService interface provided for local system services
  • IPackageManagerNative: defines the methods that need to be exposed to the native layer in PackageManager. These methods should be the same as PackageManager Methods in Java correspond to.
  • PackageManagerNative: IPackageManagerNative interface implementation class.

PackageManagerService object initialization

The construction method of PackageManagerService is very long. According to the definition in EventLogTags, it can be divided into five stages, which are expressed as

public PackageManagerService(Context context, Installer installer,
        boolean factoryTest, boolean onlyCore) {
        ...
        //Stage 1: BOOT_PROGRESS_PMS_START
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                SystemClock.uptimeMillis());
 
        //Stage 2: BOOT_PROGRESS_PMS_SYSTEM_SCAN_START 
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                    startTime);
        ...
        
        //Stage 3: BOOT_PROGRESS_PMS_DATA_SCAN_START 
        if (!mOnlyCore) {
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                        SystemClock.uptimeMillis());
        }
        ...
        //Stage 4: BOOT_PROGRESS_PMS_SCAN_END 
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                    SystemClock.uptimeMillis());
        ...
        //Stage 5: BOOT_PROGRESS_PMS_READY
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                    SystemClock.uptimeMillis());
}

BOOT_PROGRESS_PMS_START

At this stage, the following work has been done

  • Encapsulate the PMS object into PackageManagerInternal object and save it in LocalService so that the same process can access it;
  • Create UserManagerService object;
  • Create a ComponentResolver object, which is used to parse the four Android components.
  • Create PermissionManagerService object;
  • Create a settings object. Note that the object is not a Settings Provider, but com android. server. pm. Settingsï¼› It is used to save the information of dynamic settings, such as application permission and signature information.
  • Add different permissions for different shareduserids;
  • Loading the signature file MAC of the application_ permissions. xml
  • Create PackageDexOptimizer, DexManager and ArtManagerService objects;
  • Create a SystemConfig instance, obtain system configuration information, configure shared lib library and permission configuration information
  • Create HandlerThread and Handler objects for different purposes

To sum up, this process is to make great efforts. What do you make? Make objects.

public PackageManagerService(Context context, Installer installer,
           boolean factoryTest, boolean onlyCore) {
       LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
       Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "create package manager");
       EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
               SystemClock.uptimeMillis());

       if (mSdkVersion <= 0) {
           Slog.w(TAG, "**** ro.build.version.sdk not set!");
       }

       mContext = context;

       mFactoryTest = factoryTest;
       mOnlyCore = onlyCore;
       mMetrics = new DisplayMetrics();
       mInstaller = installer;

       // Create sub-components that provide services / data. Order here is important.
       synchronized (mInstallLock) {
       synchronized (mPackages) {
           //Encapsulate PackageManagerService into PackageManagerInternal object and save it in LocalService. The objects in LocalService can only be accessed in the same process.
           LocalServices.addService(
                   PackageManagerInternal.class, new PackageManagerInternalImpl());
           sUserManager = new UserManagerService(context, this,
                   new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
           mComponentResolver = new ComponentResolver(sUserManager,
                   LocalServices.getService(PackageManagerInternal.class),
                   mPackages);
           mPermissionManager = PermissionManagerService.create(context,
                   mPackages /*externalLock*/);
           mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
           mSettings = new Settings(Environment.getDataDirectory(),
                   mPermissionManager.getPermissionSettings(), mPackages);
       }
       }
		//Add different permissions for different shareduserids;
       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);

       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;
       }

       mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
               "*dexopt*");
       mDexManager = new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock);
       mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock);
       mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());

       mViewCompiler = new ViewCompiler(mInstallLock, mInstaller);

       mOnPermissionChangeListeners = new OnPermissionChangeListeners(
               FgThread.get().getLooper());

       getDefaultDisplayMetrics(context, mMetrics);

       Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "get system config");
       //Resolve the configuration and permission files in the root directory of the device, vendor, odm, oem and etc/sysconfig and etc/permissions under the product directory.
       SystemConfig systemConfig = SystemConfig.getInstance();
       mAvailableFeatures = systemConfig.getAvailableFeatures();
       Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

       mProtectedPackages = new ProtectedPackages(mContext);

       mApexManager = new ApexManager(context);
       synchronized (mInstallLock) {
       // writer
       synchronized (mPackages) {
           //Create a HandlerThread object.
           mHandlerThread = new ServiceThread(TAG,
                   Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
           mHandlerThread.start();
           //Create a PackageHandler object, which processes messages in the child thread.
           mHandler = new PackageHandler(mHandlerThread.getLooper());
           mProcessLoggingHandler = new ProcessLoggingHandler();
           Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
           mInstantAppRegistry = new InstantAppRegistry(this);

           ArrayMap<String, SystemConfig.SharedLibraryEntry> libConfig
                   = systemConfig.getSharedLibraries();
           final int builtInLibCount = libConfig.size();
           for (int i = 0; i < builtInLibCount; i++) {
               String name = libConfig.keyAt(i);
               SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);
               addBuiltInSharedLibraryLocked(entry.filename, name);
           }

           // 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 =
                       getSharedLibraryInfoLPr(entry.dependencies[j], undefinedVersion);
                   if (dependency != null) {
                       getSharedLibraryInfoLPr(name, undefinedVersion).addDependency(dependency);
                   }
               }
           }
           //Loading application signature file mac_permissions.xml file
           SELinuxMMAC.readInstallPolicy();

           Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "loadFallbacks");
           FallbackCategoryProvider.loadFallbacks();
           Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

           Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
           mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
           Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

           // Clean up orphaned packages for which the code path doesn't exist
           // and they are an update to a system app - caused by bug/32321269
           final int packageSettingCount = mSettings.mPackages.size();
           for (int i = packageSettingCount - 1; i >= 0; i--) {
               PackageSetting ps = mSettings.mPackages.valueAt(i);
               if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
                       && mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
                   mSettings.mPackages.removeAt(i);
                   mSettings.enableSystemPackageLPw(ps.name);
               }
           }

           if (!mOnlyCore && mFirstBoot) {
               requestCopyPreoptedFiles();
           }

           String customResolverActivityName = Resources.getSystem().getString(
                   R.string.config_customResolverActivity);
           if (!TextUtils.isEmpty(customResolverActivityName)) {
               mCustomResolverComponentName = ComponentName.unflattenFromString(
                       customResolverActivityName);
           }
}

In this process, we mainly look at the following two objects: Settings and SystemConfig objects.

Settings object

//frameworks/base/ervices/core/java/com/android/server/pm/Settings.java
Settings(File dataDir, PermissionSettings permission,
        Object lock) {
    mLock = lock;
    mPermissions = permission;
    mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);

    mSystemDir = new File(dataDir, "system");
    //Create / data/system folder
    mSystemDir.mkdirs();
    FileUtils.setPermissions(mSystemDir.toString(),
            FileUtils.S_IRWXU|FileUtils.S_IRWXG
            |FileUtils.S_IROTH|FileUtils.S_IXOTH,
            -1, -1);
    //Create / data / system / packages XML and other file instances
    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;

    
    mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
    mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}

SystemConfig object

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);

    // Vendors are only allowed to customize these
    int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
            | ALLOW_ASSOCIATIONS;
    if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
        // For backward compatibility
        vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
    }
    readPermissions(Environment.buildPath(
            Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);

    // Allow ODM to customize system configs as much as Vendor, because /odm is another
    // vendor partition other than /vendor.
    int odmPermissionFlag = vendorPermissionFlag;
    readPermissions(Environment.buildPath(
            Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);

    String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
    if (!skuProperty.isEmpty()) {
        String skuDir = "sku_" + skuProperty;

        readPermissions(Environment.buildPath(
                Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
        readPermissions(Environment.buildPath(
                Environment.getOdmDirectory(), "etc", "permissions", skuDir),
                odmPermissionFlag);
    }

    // Allow OEM to customize these
    int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS;
    readPermissions(Environment.buildPath(
            Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);

    // Allow Product to customize all system configs
    readPermissions(Environment.buildPath(
            Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
    readPermissions(Environment.buildPath(
            Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);

    // Allow /product_services to customize all system configs
    readPermissions(Environment.buildPath(
            Environment.getProductServicesDirectory(), "etc", "sysconfig"), ALLOW_ALL);
    readPermissions(Environment.buildPath(
            Environment.getProductServicesDirectory(), "etc", "permissions"), ALLOW_ALL);
}

In the SystemConfig construction method, the system configuration and permission information under different paths are parsed through the readPermissions() method. The name of the readPermissions() method is a bit misleading. In fact, it reads the xml files in the sysconfig and permissions folders, parses these files, and then caches the parsed attributes according to different tag s.

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()) {
        if (!f.isFile()) {
            continue;
        }

        // 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;
        }
        //Parse the xml file.
        readPermissionsFromXml(f, permissionFlag);
    }

    //Finally, parse etc / permissions / platform XML file
    if (platformFile != null) {
        readPermissionsFromXml(platformFile, permissionFlag);
    }
}

BOOT_PROGRESS_PMS_SYSTEM_SCAN_START

  • Read the environment variables BOOTCLASSPATH and SYSTEMSERVERCLASSPATH;
  • For the upgrade of the old version, change the permission obtained during installation to the permission applied during operation;
  • Scan / vendor, / product, / product_services, overlay under / odm, priv app, applications under the app directory, and applications under / system / priv app, / system/app, / system/framework are parsed (we call these apps system apps here).
  • Clearing temporary files and clearing SharedUserId information without associated app s
    synchronized (mPackages) {
	    //Omit part of the code
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                startTime);
        //Read the BOOTCLASSPATH and SYSTEMSERVERCLASSPATH environment variables. You can view all the environment variable values of the current device through the env command
        final String bootClassPath = System.getenv("BOOTCLASSPATH");
        final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
        if (bootClassPath == null) {
            Slog.w(TAG, "No BOOTCLASSPATH found!");
        }
        if (systemServerClassPath == null) {
            Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!");
        }
        File frameworkDir = new File(Environment.getRootDirectory(), "framework");
        final VersionInfo ver = mSettings.getInternalVersion();
        mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
        if (mIsUpgrade) {
            logCriticalInfo(Log.INFO,
                    "Upgrading from " + ver.fingerprint + " to " + Build.FINGERPRINT);
        }
        // When upgrading from the version before Android M, upgrade the system application permission from installation 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;
        mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
        mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;
        int preUpgradeSdkVersion = ver.sdkVersion;
        // 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);
                }
            }
        }
        mCacheDir = preparePackageParserCache();
        // Set flag to monitor and not change apk file paths when
        // scanning install directories.
        int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
        if (mIsUpgrade || mFirstBoot) {
            scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
        }
        // Scan / vendor, / product, / product_services, overlay under / odm, priv app and applications under app directory
        // And the applications under / system / priv app, / system/app, / system/framework.
        scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
                mDefParseFlags
                | PackageParser.PARSE_IS_SYSTEM_DIR,
                scanFlags
                | SCAN_AS_SYSTEM
                | SCAN_AS_VENDOR,
                0);
        //Omit part of the code
        // Prune any system packages that no longer exist.
        final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
        // Stub packages must either be replaced with full versions in the /data
        // partition or be disabled.
        final List<String> stubSystemApps = new ArrayList<>();
        if (!mOnlyCore) {
            // do this first before mucking with mPackages for the "expecting better" case
            final Iterator<PackageParser.Package> pkgIterator = mPackages.values().iterator();
            while (pkgIterator.hasNext()) {
                final PackageParser.Package pkg = pkgIterator.next();
                if (pkg.isStub) {
                    stubSystemApps.add(pkg.packageName);
                }
            }
            final 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.
                 */
                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.
                     */
                    if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
                        logCriticalInfo(Log.WARN,
                                "Expecting better updated system app for " + ps.name
                                + "; removing system app.  Last known"
                                + " codePath=" + ps.codePathString
                                + ", versionCode=" + ps.versionCode
                                + "; scanned versionCode=" + scannedPkg.getLongVersionCode());
                        removePackageLI(scannedPkg, true);
                        mExpectingBetter.put(ps.name, ps.codePath);
                    }
                    continue;
                }
                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 {
                    // we still have a disabled system package, but, it still might have
                    // been removed. check the code path still exists and check there's
                    // still a package. the latter can happen if an OTA keeps the same
                    // code path, but, changes the package name.
                    final PackageSetting disabledPs =
                            mSettings.getDisabledSystemPkgLPr(ps.name);
                    if (disabledPs.codePath == null || !disabledPs.codePath.exists()
                            || disabledPs.pkg == null) {
                        possiblyDeletedUpdatedSystemApps.add(ps.name);
                    } else {
                        // We're expecting that the system app should remain disabled, but add
                        // it to expecting better to recover in case the data version cannot
                        // be scanned.
                        mExpectingBetter.put(disabledPs.name, disabledPs.codePath);
                    }
                }
            }
        }
        //delete tmp files
        deleteTempPackageFiles();
        final int cachedSystemApps = PackageParser.sCachedPackageReadCount.get();
        // Remove any shared userIDs that have no associated packages
        mSettings.pruneSharedUsersLPw();
        final long systemScanTime = SystemClock.uptimeMillis() - startTime;
        final int systemPackagesCount = mPackages.size();
        Slog.i(TAG, "Finished scanning system apps. Time: " + systemScanTime
                + " ms, packageCount: " + systemPackagesCount
                + " , timePerPackage: "
                + (systemPackagesCount == 0 ? 0 : systemScanTime / systemPackagesCount)
                + " , cached: " + cachedSystemApps);
        if (mIsUpgrade && systemPackagesCount > 0) {
            MetricsLogger.histogram(null, "ota_package_manager_system_app_avg_scan_time",
                    ((int) systemScanTime) / systemPackagesCount);
        }
		//Omit part of the code
    }
        

There are two important functions in this process: one is to update the runtime permissions of the app when upgrading from the version before Android m to the version after Android M. The second is to scan the app in the system, and then parse it into parellelpackageparser Parseresult object. Let's take a look at the process of system app parsing:

//frameworks/base/services/core/java/com/android/server/pm/PakcageManagerservice.java
private void scanDirTracedLI(File scanDir, final int parseFlags, int scanFlags, long currentTime) {
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]");
    try {
        scanDirLI(scanDir, parseFlags, scanFlags, currentTime);
    } finally {
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
}

private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime) {
    final File[] files = scanDir.listFiles();
    if (ArrayUtils.isEmpty(files)) {
        Log.d(TAG, "No files in app dir " + scanDir);
        return;
    }

    if (DEBUG_PACKAGE_SCANNING) {
        Log.d(TAG, "Scanning app dir " + scanDir + " scanFlags=" + scanFlags
                + " flags=0x" + Integer.toHexString(parseFlags));
    }
    //Create a concurrent parsing class and call parallelpackageparser automatically at the end of the code block by 'try()' Close() method
    try (ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
            mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
            mParallelPackageParserCallback)) {
        // Submit files for parsing in parallel
        int fileCount = 0;
        for (File file : files) {
            final boolean isPackage = (isApkFile(file) || file.isDirectory())
                    && !PackageInstallerService.isStageName(file.getName());
            if (!isPackage) {
                // Ignore entries which are not packages
                continue;
            }
            //Submit the parsing task. After parsing, the parsing result object parallelpackageparser Parseresult is stored in the blocking queue.
            parallelPackageParser.submit(file, parseFlags);
            fileCount++;
        }

        // Process results one by one
        for (; fileCount > 0; fileCount--) {
            //Extract a parsing result object from the queue
            ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
            Throwable throwable = parseResult.throwable;
            int errorCode = PackageManager.INSTALL_SUCCEEDED;

            if (throwable == null) {
                // TODO(toddke): move lower in the scan chain
                // Static shared libraries have synthetic package names
                if (parseResult.pkg.applicationInfo.isStaticSharedLibrary()) {
                    renameStaticSharedLibraryPackage(parseResult.pkg);
                }
                try {
                    scanPackageChildLI(parseResult.pkg, parseFlags, scanFlags,
                            currentTime, null);
                } catch (PackageManagerException e) {
                    errorCode = e.error;
                    Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage());
                }
            } else if (throwable instanceof PackageParser.PackageParserException) {
                PackageParser.PackageParserException e = (PackageParser.PackageParserException)
                        throwable;
                errorCode = e.error;
                Slog.w(TAG, "Failed to parse " + parseResult.scanFile + ": " + e.getMessage());
            } else {
                throw new IllegalStateException("Unexpected exception occurred while parsing "
                        + parseResult.scanFile, throwable);
            }

            // Delete invalid userdata apps
            if ((scanFlags & SCAN_AS_SYSTEM) == 0 &&
                    errorCode != PackageManager.INSTALL_SUCCEEDED) {
                logCriticalInfo(Log.WARN,
                        "Deleting invalid package at " + parseResult.scanFile);
                removeCodePathLI(parseResult.scanFile);
            }
        }
    }
}

The whole parsing process is to first submit the parsing task to the thread pool, and then obtain the parsing result from the blocking queue that saves the parsing result.

apk file parsing is realized as follows, by submitting the task of parsing apk file to the thread pool; apk is parsed by Android content. pm. PackageParser. Parsepackage() completed; Finally, the parsing result is stored in the blocking queue mQueue.

//frameworks/base/services/core/java/com/android/server/pm/ParallelPackageParser.java
public void submit(File scanFile, int parseFlags) {
    mService.submit(() -> {
        ParseResult pr = new ParseResult();
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parallel parsePackage [" + scanFile + "]");
        try {
            PackageParser pp = new PackageParser();
            pp.setSeparateProcesses(mSeparateProcesses);
            pp.setOnlyCoreApps(mOnlyCore);
            pp.setDisplayMetrics(mMetrics);
            pp.setCacheDir(mCacheDir);
            pp.setCallback(mPackageParserCallback);
            pr.scanFile = scanFile;
            pr.pkg = parsePackage(pp, scanFile, parseFlags);
        } catch (Throwable e) {
            pr.throwable = e;
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
        try {
            //Add the result to the blocking queue mQueue after parsing
            mQueue.put(pr);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            // Propagate result to callers of take().
            // This is helpful to prevent main thread from getting stuck waiting on
            // ParallelPackageParser to finish in case of interruption
            mInterruptedInThread = Thread.currentThread().getName();
        }
    });
}

@VisibleForTesting
protected PackageParser.Package parsePackage(PackageParser packageParser, File scanFile,
        int parseFlags) throws PackageParser.PackageParserException {
    //Through packageparser Parsepackage parses apk files, mainly Android manifest XML file to get the information in the file
    return packageParser.parsePackage(scanFile, parseFlags, true /* useCaches */);
}

BOOT_PROGRESS_PMS_DATA_SCAN_START

At this stage, the following work has been done:

  • Scan the apk file under / data/app and parse it to get the Package information.
  • Delete the permission configuration information of apps that have been upgraded through OTA; Delete apps that no longer exist.
  • Update App shared library path information
    

   //Omit part of the code
	
    if (!mOnlyCore) {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                SystemClock.uptimeMillis());
        //Scan and parse apk files in the data/app directory
        scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
        
        for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) {
            final String packageName = possiblyDeletedUpdatedSystemApps.get(i);
            final PackageParser.Package pkg = mPackages.get(packageName);
            final String msg;
            //Delete the permission configuration information of app s that have been upgraded through OTA;
            mSettings.removeDisabledSystemPackageLPw(packageName);
            if (pkg == null) {
                // should have found an update, but, we didn't; remove everything
                msg = "Updated system package " + packageName
                        + " no longer exists; removing its data";
                // Actual deletion of code and data will be handled by later
                // reconciliation step
            } else {
                // found an update; revoke system privileges
                msg = "Updated system package " + packageName
                        + " no longer exists; rescanning package on data";
                // NOTE: We don't do anything special if a stub is removed from the
                // system image. But, if we were [like removing the uncompressed
                // version from the /data partition], this is where it'd be done.
                // remove the package from the system and re-scan it without any
                // special privileges
                removePackageLI(pkg, true);
                try {
                    final File codePath = new File(pkg.applicationInfo.getCodePath());
                    scanPackageTracedLI(codePath, 0, scanFlags, 0, null);
                } catch (PackageManagerException e) {
                    Slog.e(TAG, "Failed to parse updated, ex-system package: "
                            + e.getMessage());
                }
            }
            // one final check. if we still have a package setting [ie. it was
            // previously scanned and known to the system], but, we don't have
            // a package [ie. there was an error scanning it from the /data
            // partition], completely remove the package data.
            final PackageSetting ps = mSettings.mPackages.get(packageName);
            if (ps != null && mPackages.get(packageName) == null) {
                removePackageDataLIF(ps, null, null, 0, false);
            }
            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");
                final @ParseFlags int reparseFlags;
                final @ScanFlags int rescanFlags;
                if (FileUtils.contains(privilegedAppDir, scanFile)) {
                    reparseFlags =
                            mDefParseFlags |
                            PackageParser.PARSE_IS_SYSTEM_DIR;
                    rescanFlags =
                            scanFlags
                            | SCAN_AS_SYSTEM
                            | SCAN_AS_PRIVILEGED;
                } else if (FileUtils.contains(systemAppDir, scanFile)) {
                    reparseFlags =
                            mDefParseFlags |
                            PackageParser.PARSE_IS_SYSTEM_DIR;
                    rescanFlags =
                            scanFlags
                            | SCAN_AS_SYSTEM;
                } else if (FileUtils.contains(privilegedVendorAppDir, scanFile)
                        || FileUtils.contains(privilegedOdmAppDir, scanFile)) {
                    reparseFlags =
                            mDefParseFlags |
                            PackageParser.PARSE_IS_SYSTEM_DIR;
                    rescanFlags =
                            scanFlags
                            | SCAN_AS_SYSTEM
                            | SCAN_AS_VENDOR
                            | SCAN_AS_PRIVILEGED;
                } else if (FileUtils.contains(vendorAppDir, scanFile)
                        || FileUtils.contains(odmAppDir, scanFile)) {
                    reparseFlags =
                            mDefParseFlags |
                            PackageParser.PARSE_IS_SYSTEM_DIR;
                    rescanFlags =
                            scanFlags
                            | SCAN_AS_SYSTEM
                            | SCAN_AS_VENDOR;
                } else if (FileUtils.contains(oemAppDir, scanFile)) {
                    reparseFlags =
                            mDefParseFlags |
                            PackageParser.PARSE_IS_SYSTEM_DIR;
                    rescanFlags =
                            scanFlags
                            | SCAN_AS_SYSTEM
                            | SCAN_AS_OEM;
                } else if (FileUtils.contains(privilegedProductAppDir, scanFile)) {
                    reparseFlags =
                            mDefParseFlags |
                            PackageParser.PARSE_IS_SYSTEM_DIR;
                    rescanFlags =
                            scanFlags
                            | SCAN_AS_SYSTEM
                            | SCAN_AS_PRODUCT
                            | SCAN_AS_PRIVILEGED;
                } else if (FileUtils.contains(productAppDir, scanFile)) {
                    reparseFlags =
                            mDefParseFlags |
                            PackageParser.PARSE_IS_SYSTEM_DIR;
                    rescanFlags =
                            scanFlags
                            | SCAN_AS_SYSTEM
                            | SCAN_AS_PRODUCT;
                } else if (FileUtils.contains(privilegedProductServicesAppDir, scanFile)) {
                    reparseFlags =
                            mDefParseFlags |
                            PackageParser.PARSE_IS_SYSTEM_DIR;
                    rescanFlags =
                            scanFlags
                            | SCAN_AS_SYSTEM
                            | SCAN_AS_PRODUCT_SERVICES
                            | SCAN_AS_PRIVILEGED;
                } else if (FileUtils.contains(productServicesAppDir, scanFile)) {
                    reparseFlags =
                            mDefParseFlags |
                            PackageParser.PARSE_IS_SYSTEM_DIR;
                    rescanFlags =
                            scanFlags
                            | SCAN_AS_SYSTEM
                            | SCAN_AS_PRODUCT_SERVICES;
                } else {
                    Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                    continue;
                }
                mSettings.enableSystemPackageLPw(packageName);
                try {
                    scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);
                } catch (PackageManagerException e) {
                    Slog.e(TAG, "Failed to parse original system package: "
                            + e.getMessage());
                }
            }
        }
        // Uncompress and install any stubbed system applications.
        // This must be done last to ensure all stubs are replaced or disabled.
        installSystemStubPackages(stubSystemApps, scanFlags);
        final int cachedNonSystemApps = PackageParser.sCachedPackageReadCount.get()
                        - cachedSystemApps;
        final long dataScanTime = SystemClock.uptimeMillis() - systemScanTime - startTime;
        final int dataPackagesCount = mPackages.size() - systemPackagesCount;
        Slog.i(TAG, "Finished scanning non-system apps. Time: " + dataScanTime
                + " ms, packageCount: " + dataPackagesCount
                + " , timePerPackage: "
                + (dataPackagesCount == 0 ? 0 : dataScanTime / dataPackagesCount)
                + " , cached: " + cachedNonSystemApps);
        if (mIsUpgrade && dataPackagesCount > 0) {
            MetricsLogger.histogram(null, "ota_package_manager_data_app_avg_scan_time",
                    ((int) dataScanTime) / dataPackagesCount);
        }
    }
    mExpectingBetter.clear();
    // Resolve the storage manager.
    mStorageManagerPackage = getStorageManagerPackageName();
    // Resolve protected action filters. Only the setup wizard is allowed to
    // have a high priority filter for these actions.
    mSetupWizardPackage = getSetupWizardPackageName();
    mComponentResolver.fixProtectedFilterPriorities();
    mSystemTextClassifierPackage = getSystemTextClassifierPackageName();
    mWellbeingPackage = getWellbeingPackageName();
    mDocumenterPackage = getDocumenterPackageName();
    mConfiguratorPackage =
            mContext.getString(R.string.config_deviceConfiguratorPackageName);
    mAppPredictionServicePackage = getAppPredictionServicePackageName();
    mIncidentReportApproverPackage = getIncidentReportApproverPackageName();
    //Update application shared library information
    updateAllSharedLibrariesLocked(null, Collections.unmodifiableMap(mPackages));
    for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
        // NOTE: We ignore potential failures here during a system scan (like
        // the rest of the commands above) because there's precious little we
        // can do about it. A settings error is reported, though.
        final List<String> changedAbiCodePath =
                adjustCpuAbisForSharedUserLPw(setting.packages, 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();
    }
    // Now that we know all the packages we are keeping,
    // read and update their last usage times.
    mPackageUsage.read(mPackages);
    mCompilerStats.read();
    
	//Omit part of the code

BOOT_PROGRESS_PMS_SCAN_END

At this stage, the following work has been done:

  • If the sdk version changes, the permissions are updated
  • The OTA is started for the first time after upgrading to clear unnecessary cache data
  • Clean up relevant data after default updates such as permissions
  • Update / data / system / packages xml
           //Omit some codes
            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.
            final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion);
            if (sdkUpdated) {
                Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
                        + mSdkVersion + "; regranting permissions for internal storage");
            }
            //Update permissions
            mPermissionManager.updateAllPermissions(
                    StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, mPackages.values(),
                    mPermissionCallback);
            ver.sdkVersion = mSdkVersion;

            
            //If you are starting for the first time or upgrading from a version before M, you need to initialize the xml configuration file under the / etc / preferred apps path
            if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
                for (UserInfo user : sUserManager.getUsers(true)) {
                    mSettings.applyDefaultPreferredAppsLPw(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;
            }
            List<String> deferPackages = reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL,
                    UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
                    true /* onlyCoreApps */);
            mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> {
                TimingsTraceLog traceLog = new TimingsTraceLog("SystemServerTimingAsync",
                        Trace.TRACE_TAG_PACKAGE_MANAGER);
                traceLog.traceBegin("AppDataFixup");
                try {
                    mInstaller.fixupAppData(StorageManager.UUID_PRIVATE_INTERNAL,
                            StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
                } catch (InstallerException e) {
                    Slog.w(TAG, "Trouble fixing GIDs", e);
                }
                traceLog.traceEnd();

                traceLog.traceBegin("AppDataPrepare");
                if (deferPackages == null || deferPackages.isEmpty()) {
                    return;
                }
                int count = 0;
                for (String pkgName : deferPackages) {
                    PackageParser.Package pkg = null;
                    synchronized (mPackages) {
                        PackageSetting ps = mSettings.getPackageLPr(pkgName);
                        if (ps != null && ps.getInstalled(UserHandle.USER_SYSTEM)) {
                            pkg = ps.pkg;
                        }
                    }
                    if (pkg != null) {
                        synchronized (mInstallLock) {
                            prepareAppDataAndMigrateLIF(pkg, UserHandle.USER_SYSTEM, storageFlags,
                                    true /* maybeMigrateAppData */);
                        }
                        count++;
                    }
                }
                traceLog.traceEnd();
                Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages");
            }, "prepareAppData");

            
            //After OTA upgrade, clear the cache directory after the first boot.
            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,
                                FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
                                        | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
                    }
                }
                ver.fingerprint = Build.FINGERPRINT;
            }

            // Grandfather existing (installed before Q) non-system apps to hide
            // their icons in launcher.
            if (!onlyCore && mIsPreQUpgrade) {
                Slog.i(TAG, "Whitelisting all existing apps to hide their icons");
                int size = mSettings.mPackages.size();
                for (int i = 0; i < size; i++) {
                    final PackageSetting ps = mSettings.mPackages.valueAt(i);
                    if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                        continue;
                    }
                    ps.disableComponentLPw(PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,
                            UserHandle.USER_SYSTEM);
                }
            }

            // clear only after permissions and other defaults have been updated
            mExistingSystemPackages.clear();
            mPromoteSystemApps = false;

            // All the changes are done during package scanning.
            ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;

            // can downgrade to reader
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings");
            //Update the setting information to / data / system / packages XML file
            mSettings.writeLPr();
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

BOOT_PROGRESS_PMS_READY

At this stage, the following work has been done:

  • Create PackageInstallerService pair
  • GC reclaims memory
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                    SystemClock.uptimeMillis());

            if (!mOnlyCore) {
                mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr();
                mRequiredInstallerPackage = getRequiredInstallerLPr();
                mRequiredUninstallerPackage = getRequiredUninstallerLPr();
                mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr();
                if (mIntentFilterVerifierComponent != null) {
                    mIntentFilterVerifier = new IntentVerifierProxy(mContext,
                            mIntentFilterVerifierComponent);
                } else {
                    mIntentFilterVerifier = null;
                }
                mServicesSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
                        PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES,
                        SharedLibraryInfo.VERSION_UNDEFINED);
                mSharedSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
                        PackageManager.SYSTEM_SHARED_LIBRARY_SHARED,
                        SharedLibraryInfo.VERSION_UNDEFINED);
            } else {
                mRequiredVerifierPackage = null;
                mRequiredInstallerPackage = null;
                mRequiredUninstallerPackage = null;
                mIntentFilterVerifierComponent = null;
                mIntentFilterVerifier = null;
                mServicesSystemSharedLibraryPackageName = null;
                mSharedSystemSharedLibraryPackageName = null;
            }
            // PermissionController hosts default permission granting and role management, so it's a
            // critical part of the core system.
            mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr();

            // Initialize InstantAppRegistry's Instant App list for all users.
            final int[] userIds = UserManagerService.getInstance().getUserIds();
            for (PackageParser.Package pkg : mPackages.values()) {
                if (pkg.isSystem()) {
                    continue;
                }
                for (int userId : userIds) {
                    final PackageSetting ps = (PackageSetting) pkg.mExtras;
                    if (ps == null || !ps.getInstantApp(userId) || !ps.getInstalled(userId)) {
                        continue;
                    }
                    mInstantAppRegistry.addInstantAppLPw(userId, ps.appId);
                }
            }
            //Create a PackageInstallerService object, which is responsible for installing and uninstalling applications.
            mInstallerService = new PackageInstallerService(context, this, mApexManager);
            final Pair<ComponentName, String> instantAppResolverComponent =
                    getInstantAppResolverLPr();
            if (instantAppResolverComponent != null) {
                if (DEBUG_INSTANT) {
                    Slog.d(TAG, "Set ephemeral resolver: " + instantAppResolverComponent);
                }
                mInstantAppResolverConnection = new InstantAppResolverConnection(
                        mContext, instantAppResolverComponent.first,
                        instantAppResolverComponent.second);
                mInstantAppResolverSettingsComponent =
                        getInstantAppResolverSettingsLPr(instantAppResolverComponent.first);
            } else {
                mInstantAppResolverConnection = null;
                mInstantAppResolverSettingsComponent = null;
            }
            updateInstantAppInstallerLocked(null);

            // Read and update the usage of dex files.
            // Do this at the end of PM init so that all the packages have their
            // data directory reconciled.
            // At this point we know the code paths of the packages, so we can validate
            // the disk file and build the internal cache.
            // The usage file is expected to be small so loading and verifying it
            // should take a fairly small time compare to the other activities (e.g. package
            // scanning).
            final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
            for (int userId : userIds) {
                userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList());
            }
            mDexManager.load(userPackages);
            if (mIsUpgrade) {
                MetricsLogger.histogram(null, "ota_package_manager_init_time",
                        (int) (SystemClock.uptimeMillis() - startTime));
            }
        } // synchronized (mPackages)
        } // synchronized (mInstallLock)

        mModuleInfoProvider = new ModuleInfoProvider(mContext, this);

        // Now after opening every single application zip, make sure they
        // are all flushed.  Not really needed, but keeps things nice and
        // tidy.
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "GC");
        //GC reclaims heap memory.
        Runtime.getRuntime().gc();
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

        // 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);

        PackageParser.readConfigUseRoundIcon(mContext.getResources());

        mServiceStartWithDelay = SystemClock.uptimeMillis() + (60 * 1000L);

        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

summary

PackageManagerService is one of the important system services in Android system. Application installation, uninstallation, parsing and permission management are related to it; PackageManagerService is started by SystemServer; PackageManagerService object creation is divided into five stages according to EventLogTags: BOOT_PROGRESS_PMS_START,BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,BOOT_PROGRESS_PMS_DATA_SCAN_START,BOOT_PROGRESS_PMS_SCAN_END,BOOT_PROGRESS_PMS_READY.

Topics: Android Framework source code analysis