PackageManagerService的启动流程分析

605 阅读19分钟

1. PackageManagerService简介:

PackageManagerService简称PKMS,是Android系统中的核心服务之一,管理着Package相关的所有工作,例如应用安装、卸载、解析apk文件、验证apk文件的签名、检查AndroidManifest.xml文件中的权限设置、检查应用程序的存储位置、安装应用程序所需的库和框架等。

Android版本:Android P

参考文档:

google官方文档: developer.android.com/reference/a…

袁辉辉博客:gityuan.com/2016/11/06/…

2.PKMS的启动流程

2.1 SystemServer启动PKMS

Android系统大多服务都是从system_server中启动。PKMS也是在system_server中启动。 system_server.java位置:

platform/frameworks/base/services/java/com/android/server/SystemServer.java

private void run() {
// Start services.
        try {
            traceBeginAndSlog("StartServices");
            // 2.1.1 启动BootstrapService
            startBootstrapServices();
            // 2.1.2 启动OtherService
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        }
}

在System_Server中启动pkms需要执行两个函数:

  1. startBootstrapServices();
  2. startOtherServices();

2.1.1 startBootstrapServices()

/**
 * Starts the small tangle of critical services that are needed to get
 * the system off the ground.  These services have complex mutual dependencies
 * which is why we initialize them all in one place here.  Unless your service
 * is also entwined in these dependencies, it should be initialized in one of
 * the other functions.
 */
private void startBootstrapServices() {
    ......
    // 由SystemServiceManager启动installer服务;
    // installer服务在这里主要使用恰当的权限创建例如/data/user的绝对路径
    // 必须等待installer起来之后才能去初始化别的服务
    traceBeginAndSlog("StartInstaller");
    // 由SystemServiceManager启动installer服务
    Installer installer = mSystemServiceManager.startService(Installer.class);
    traceEnd();
    ......
    // 当加处于加密状态的时候只解析核心应用
    String cryptState = SystemProperties.get("vold.decrypt");
    if (ENCRYPTING_STATE.equals(cryptState)) {
        Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
        mOnlyCore = true;
    } else if (ENCRYPTED_STATE.equals(cryptState)) {
        Slog.w(TAG, "Device encrypted - only parsing core apps");
        mOnlyCore = true;
    }

    // 开启PackageManager进程
    if (!mRuntimeRestart) {
        MetricsLogger.histogram(null, "boot_package_manager_init_start",
                (int) SystemClock.elapsedRealtime());
    }
    traceBeginAndSlog("StartPackageManagerService");
    // 调用PackageManagerService的静态方法main(),创建一个PackageManager对象
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    // 判断PackageManagerService是否首次启动
    mFirstBoot = mPackageManagerService.isFirstBoot();
    // 初始化PackageManager,创建PKM对象
    mPackageManager = mSystemContext.getPackageManager();
    traceEnd();
    if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
        MetricsLogger.histogram(null, "boot_package_manager_init_ready",
                (int) SystemClock.elapsedRealtime());
    }
    
    // 如果设备未加密,开启OtaDexoptService。管理A/B分区OTA dexopting
    if (!mOnlyCore) {
        // 读取系统属性,读取config.disable_otadexopt的值
        boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                false);
        if (!disableOtaDexopt) {
            traceBeginAndSlog("StartOtaDexOptService");
            try {
                // 开启OtaDexoptService服务。
                OtaDexoptService.main(mSystemContext, mPackageManagerService);
            } catch (Throwable e) {
                reportWtf("starting OtaDexOptService", e);
            } finally {
                traceEnd();
            }
        }
}

    ......
}

PKMS在SystemServer.java->startBootstrapServices()中启动,在启动PKMS时,主要做了以下工作:

  1. 启动installer服务。
  2. 判断当前是否是加密状态,加密状态只解析核心应用
  3. 使用PackageManagerService.main()创建一个pkms对象
  4. 创建一个pkm
  5. 管理A/B OTA dexopting

2.1.2 startOtherServices()

为保证pkms等服务顺利启动且可用,SystemServer还需要执行startOtherServices()。以下列出为保证pkms需要的代码。

    /**
     * Starts a miscellaneous grab bag of stuff that has yet to be refactored
     * and organized.
     */
private void startOtherServices() {
    ......
    // 开启mount service
    storageManager = IStorageManager.Stub.asInterface(
        ServiceManager.getService("mount"));
    ......
    // 开启BackgroundDexOptService
    traceBeginAndSlog("StartBackgroundDexOptService");
    try {
        BackgroundDexOptService.schedule(context);
    } catch (Throwable e) {
        reportWtf("starting StartBackgroundDexOptService", e);
    }
    traceEnd();
    ......
    // 设备未加密,做dex优化
    if (!mOnlyCore) {
            traceBeginAndSlog("UpdatePackagesIfNeeded");
            try {
                // 内部调用performDexOptUpgrade()做dex优化
                mPackageManagerService.updatePackagesIfNeeded();
            } catch (Throwable e) {
                reportWtf("update packages", e);
            }
            traceEnd();
        }
    // 执行performFstrimIfNeeded(),磁盘维护
    traceBeginAndSlog("PerformFstrimIfNeeded");
    try {
        mPackageManagerService.performFstrimIfNeeded();
    } catch (Throwable e) {
        reportWtf("performing fstrim", e);
    }
    traceEnd();
    ......
    // 确保SystemManagerService可用
    traceBeginAndSlog("MakePackageManagerServiceReady");
    mPackageManagerService.systemReady();
    traceEnd();
    ......
    // 等待所有包准备完毕
    mPackageManagerService.waitForAppDataPrepared();
    ......
   }

在startOtherServices()中,主要执行以下操作:

  1. 在设备未加密的状态下,做dex优化 ----详见2.1.2.1
  2. 磁盘维护 ----详见2.1.2.2
  3. 确保pkms准备完成 ----详见2.1.2.3

2.1.2.1 dex优化

在设备未加密的状态下,可能需要做一次dex优化。具体的优化策略见代码详情。

@Override
    public void updatePackagesIfNeeded() {
        enforceSystemOrRoot("Only the system can request package update");

        // We need to re-extract after an OTA.
        // 1.是否进行了OTA升级,OTA升级后需要重新提取
        boolean causeUpgrade = isUpgrade();

        // First boot or factory reset.
        // Note: we also handle devices that are upgrading to N right now as if it is their
        //       first boot, as they do not have profile data.
        // 2.是否是第一次启动或者升级至N
        boolean causeFirstBoot = isFirstBoot() || mIsPreNUpgrade;

        // We need to re-extract after a pruned cache, as AoT-ed files will be out of date.
        // 3.判断是否进行过虚拟机缓存清理,如果清理过了,AOT编译后的文件就过时了,需要重新编译
        boolean causePrunedCache = VMRuntime.didPruneDalvikCache();
        // 如果123都不满足,那么就不需要进行优化。不执行任何操作,退出。
        if (!causeUpgrade && !causeFirstBoot && !causePrunedCache) {
            return;
        }
        // 否则,进行优化
        List<PackageParser.Package> pkgs;
        synchronized (mPackages) {
        // 按照package的优先级进行排序,并返回一个list.优先级为:core apps > system apps > other apps
        // 代码详见 2.1.2.1.1 
            pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);
        }
        // 开始时间,用于计时
        final long startTime = System.nanoTime();
        // 执行编译优化
        // 代码详见:2.1.2.1.2
        final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */,
                    causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT,
                    false /* bootComplete */);
        // 编译优化消耗的时间
        final int elapsedTimeSeconds =
                (int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime);

        MetricsLogger.histogram(mContext, "opt_dialog_num_dexopted", stats[0]);
        MetricsLogger.histogram(mContext, "opt_dialog_num_skipped", stats[1]);
        MetricsLogger.histogram(mContext, "opt_dialog_num_failed", stats[2]);
        MetricsLogger.histogram(mContext, "opt_dialog_num_total", getOptimizablePackages().size());
        MetricsLogger.histogram(mContext, "opt_dialog_time_s", elapsedTimeSeconds);
    }

在做dex优化前,需要进行判断,如果以下三个条件都不满足,则不需要进行dex优化:

  1. 是否进行了OTA升级,OTA升级后需要重新提取
  2. 是否是第一次启动或者升级至N
  3. 判断是否进行过虚拟机缓存清理

在执行dex优化时,核心方法主要有两个:

  1. PackageManagerServiceUtils.getPackagesForDexopt():根据优先级返回待优化的list
  2. performDexOptUpgrade(); 将list中的package依次优化
2.1.2.1.1 获取待优化列表

依据dex优化的优先级返回一个list。优先级:core apps > system apps > other apps

// Sort apps by importance for dexopt ordering. Important apps are given
    // more priority in case the device runs out of space.
    public static List<PackageParser.Package> getPackagesForDexopt(
            Collection<PackageParser.Package> packages,
            PackageManagerService packageManagerService) {
        ArrayList<PackageParser.Package> remainingPkgs = new ArrayList<>(packages);
        LinkedList<PackageParser.Package> result = new LinkedList<>();
        ArrayList<PackageParser.Package> sortTemp = new ArrayList<>(remainingPkgs.size());

        // Give priority to core apps.
        applyPackageFilter((pkg) -> pkg.coreApp, result, remainingPkgs, sortTemp,
                packageManagerService);

        // Give priority to system apps that listen for pre boot complete.
        Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
        final ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
        applyPackageFilter((pkg) -> pkgNames.contains(pkg.packageName), result, remainingPkgs,
                sortTemp, packageManagerService);

        // Give priority to apps used by other apps.
        DexManager dexManager = packageManagerService.getDexManager();
        applyPackageFilter((pkg) ->
                dexManager.getPackageUseInfoOrDefault(pkg.packageName)
                        .isAnyCodePathUsedByOtherApps(),
                result, remainingPkgs, sortTemp, packageManagerService);

        // Filter out packages that aren't recently used, add all remaining apps.
        // TODO: add a property to control this?
        Predicate<PackageParser.Package> remainingPredicate;
        if (!remainingPkgs.isEmpty() && packageManagerService.isHistoricalPackageUsageAvailable()) {
            if (DEBUG_DEXOPT) {
                Log.i(TAG, "Looking at historical package use");
            }
            // Get the package that was used last.
            PackageParser.Package lastUsed = Collections.max(remainingPkgs, (pkg1, pkg2) ->
                    Long.compare(pkg1.getLatestForegroundPackageUseTimeInMills(),
                            pkg2.getLatestForegroundPackageUseTimeInMills()));
            if (DEBUG_DEXOPT) {
                Log.i(TAG, "Taking package " + lastUsed.packageName + " as reference in time use");
            }
            long estimatedPreviousSystemUseTime =
                    lastUsed.getLatestForegroundPackageUseTimeInMills();
            // Be defensive if for some reason package usage has bogus data.
            if (estimatedPreviousSystemUseTime != 0) {
                final long cutoffTime = estimatedPreviousSystemUseTime - SEVEN_DAYS_IN_MILLISECONDS;
                remainingPredicate =
                        (pkg) -> pkg.getLatestForegroundPackageUseTimeInMills() >= cutoffTime;
            } else {
                // No meaningful historical info. Take all.
                remainingPredicate = (pkg) -> true;
            }
            sortPackagesByUsageDate(remainingPkgs, packageManagerService);
        } else {
            // No historical info. Take all.
            remainingPredicate = (pkg) -> true;
        }
        applyPackageFilter(remainingPredicate, result, remainingPkgs, sortTemp,
                packageManagerService);

        if (DEBUG_DEXOPT) {
            Log.i(TAG, "Packages to be dexopted: " + packagesToString(result));
            Log.i(TAG, "Packages skipped from dexopt: " + packagesToString(remainingPkgs));
        }

        return result;
    }

2.1.2.1.2 执行dex优化
    /**
     * Performs dexopt on the set of packages in {@code packages} and returns an int array
     * containing statistics about the invocation. The array consists of three elements,
     * which are (in order) {@code numberOfPackagesOptimized}, {@code numberOfPackagesSkipped}
     * and {@code numberOfPackagesFailed}.
     */
     // 根据列表中的packages做dex优化,最终返回一个包括启动数据的整型数组,数组包含:1.第几个优化的package,跳过了几个package,失败了几个package。
    private int[] performDexOptUpgrade(List<PackageParser.Package> pkgs, boolean showDialog,
            final int compilationReason, boolean bootComplete) {
        // 统计变量
        int numberOfPackagesVisited = 0;
        int numberOfPackagesOptimized = 0;
        int numberOfPackagesSkipped = 0;
        int numberOfPackagesFailed = 0;
        // package总数
        final int numberOfPackagesToDexopt = pkgs.size();
        // 遍历数组,依次进行dex优化
        for (PackageParser.Package pkg : pkgs) {
            numberOfPackagesVisited++;
            // 是否使用profile进行dex优化
            boolean useProfileForDexopt = false;
            // (首次启动||OTA升级之后)&& 是系统应用,则进行odex优化
            if ((isFirstBoot() || isUpgrade()) && isSystemApp(pkg)) {
                // Copy over initial preopt profiles since we won't get any JIT samples for methods
                // that are already compiled.
                // 如果不存在JIT已经编译好的某些方法,则直接复制初始化的预处理文件
                File profileFile = new File(getPrebuildProfilePath(pkg));
                // Copy profile if it exists.
                // profile文件存在就copy过来
                if (profileFile.exists()) {
                    try {
                        // We could also do this lazily before calling dexopt in
                        // PackageDexOptimizer to prevent this happening on first boot. The issue
                        // is that we don't have a good way to say "do this only once".
                        // 也可以偷懒在PackageDexOptimizer之前进行优化,防止这样的情况在首次启动时发生。但是
                        if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(),
                                pkg.applicationInfo.uid, pkg.packageName,
                                ArtManager.getProfileName(null))) {
                            Log.e(TAG, "Installer failed to copy system profile!");
                        } else {
               
                            // Disabled as this causes speed-profile compilation during first boot
                            // even if things are already compiled.
                     // 禁止这种情况导致的首次启动时speed-profile编译,即使已经编译过了
                            // useProfileForDexopt = true;
                        }
                    } catch (Exception e) {
                        Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ",
                                e);
                    }
                } else {
                    PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(pkg.packageName);
                    // Handle compressed APKs in this path. Only do this for stubs with profiles to
                    // minimize the number off apps being speed-profile compiled during first boot.
                    // The other paths will not change the filter.
                    // 在这里处理压缩的apk文件
                    if (disabledPs != null && disabledPs.pkg.isStub) {
                        // The package is the stub one, remove the stub suffix to get the normal
                        // package and APK names.
                        String systemProfilePath =
                                getPrebuildProfilePath(disabledPs.pkg).replace(STUB_SUFFIX, "");
                        profileFile = new File(systemProfilePath);
                        // If we have a profile for a compressed APK, copy it to the reference
                        // location.
                        // Note that copying the profile here will cause it to override the
                        // reference profile every OTA even though the existing reference profile
                        // may have more data. We can't copy during decompression since the
                        // directories are not set up at that point.
                        if (profileFile.exists()) {
                            try {
                                // We could also do this lazily before calling dexopt in
                                // PackageDexOptimizer to prevent this happening on first boot. The
                                // issue is that we don't have a good way to say "do this only
                                // once".
                                if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(),
                                        pkg.applicationInfo.uid, pkg.packageName,
                                        ArtManager.getProfileName(null))) {
                                    Log.e(TAG, "Failed to copy system profile for stub package!");
                                } else {
                                    useProfileForDexopt = true;
                                }
                            } catch (Exception e) {
                                Log.e(TAG, "Failed to copy profile " +
                                        profileFile.getAbsolutePath() + " ", e);
                            }
                        }
                    }
                }
            }
            // PackageDexOptimizer无法处理的,跳过
            if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
                if (DEBUG_DEXOPT) {
                    Log.i(TAG, "Skipping update of of non-optimizable app " + pkg.packageName);
                }
                numberOfPackagesSkipped++;
                continue;
            }

            if (DEBUG_DEXOPT) {
                Log.i(TAG, "Updating app " + numberOfPackagesVisited + " of " +
                        numberOfPackagesToDexopt + ": " + pkg.packageName);
            }

            if (showDialog) {
                try {
                    ActivityManager.getService().showBootMessage(
                            mContext.getResources().getString(R.string.android_upgrading_apk,
                                    numberOfPackagesVisited, numberOfPackagesToDexopt), true);
                } catch (RemoteException e) {
                }
                synchronized (mPackages) {
                    mDexOptDialogShown = true;
                }
            }
            // 编译原因
            int pkgCompilationReason = compilationReason;
            // 使用profile编译
            if (useProfileForDexopt) {
                // Use background dexopt mode to try and use the profile. Note that this does not
                // guarantee usage of the profile.
                pkgCompilationReason = PackageManagerService.REASON_BACKGROUND_DEXOPT;
            }

            // checkProfiles is false to avoid merging profiles during boot which
            // might interfere with background compilation (b/28612421).
            // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
            // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a
            // trade-off worth doing to save boot time work.
            // 检查profile文件是否为false,防止文件在启动时使用后台编译的时候合并
            // 这意味着pm.dexopt.boot=speed-profile和pm.dexopt.bg-dexopt=speed-profile的表现不一样
            int dexoptFlags = bootComplete ? DexoptOptions.DEXOPT_BOOT_COMPLETE : 0;
            // 编译原因为首次启动
            if (compilationReason == REASON_FIRST_BOOT) {
                // TODO: This doesn't cover the upgrade case, we should check for this too.
                dexoptFlags |= DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE;
            }
            // 执行performDexOptTraced(),返回编译结果
            // 最终是由mInstaller.dexopt 完成优化的,installd守护进程,installer安装器和Installd通信
            int primaryDexOptStaus = performDexOptTraced(new DexoptOptions(
                    pkg.packageName,
                    pkgCompilationReason,
                    dexoptFlags));
            // 检查编译状态,修改统计变量
            switch (primaryDexOptStaus) {
                case PackageDexOptimizer.DEX_OPT_PERFORMED:
                    // 完成优化的数量
                    numberOfPackagesOptimized++;
                    break;
                case PackageDexOptimizer.DEX_OPT_SKIPPED:
                    // 跳过优化的数量
                    numberOfPackagesSkipped++;
                    break;
                case PackageDexOptimizer.DEX_OPT_FAILED:
                    // 优化失败的数量
                    numberOfPackagesFailed++;
                    break;
                default:
                    Log.e(TAG, "Unexpected dexopt return code " + primaryDexOptStaus);
                    break;
            }
        }
        // 返回以上统计变量
        return new int[] { numberOfPackagesOptimized, numberOfPackagesSkipped,
                numberOfPackagesFailed };
    }

dex优化方案比较复杂,在这个方法中做了许多判断。按照list中的优先级,依次完成优化。最终都是由Install的dexopt进行dex优化。后续单独开文章讲述dex优化方案。

2.1.2.2 磁盘维护

 @Override
    public void performFstrimIfNeeded() {
        // 只有system或者root用户才可以请求fstrim
        enforceSystemOrRoot("Only the system can request fstrim");

        // Before everything else, see whether we need to fstrim.
        // 在所有事情开始之前,查看是否需要执行fstrim
        try {
            // 获取StorageManager对象
            IStorageManager sm = PackageHelper.getStorageManager();
            if (sm != null) {
                boolean doTrim = false;
                // 获取执行fstrim执行间隔
                // private static final long DEFAULT_MANDATORY_FSTRIM_INTERVAL = 3 * DateUtils.DAY_IN_MILLIS;

                final long interval = android.provider.Settings.Global.getLong(
                        mContext.getContentResolver(),
                        android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,
                        DEFAULT_MANDATORY_FSTRIM_INTERVAL);
                if (interval > 0) {
                    final long timeSinceLast = System.currentTimeMillis() - sm.lastMaintenance();
                    if (timeSinceLast > interval) {
                    // 超过三天自动清理
                        doTrim = true;
                        Slog.w(TAG, "No disk maintenance in " + timeSinceLast
                                + "; running immediately");
                    }
                }
                // 清理
                if (doTrim) {
                    final boolean dexOptDialogShown;
                    synchronized (mPackages) {
                        dexOptDialogShown = mDexOptDialogShown;
                    }
                    // 不是首次启动并且显示dex优化弹窗
                    if (!isFirstBoot() && dexOptDialogShown) {
                        try {
                            ActivityManager.getService().showBootMessage(
                                    mContext.getResources().getString(
                                            R.string.android_upgrading_fstrim), true);
                        } catch (RemoteException e) {
                        }
                    }
                    // StorageManagerService发送消息给handler,然后执行fstrim()向Vold发消息
                    sm.runMaintenance();
                }
            } else {
                Slog.e(TAG, "storageManager service unavailable!");
            }
        } catch (RemoteException e) {
            // Can't happen; StorageManagerService is local
        }
    }

看起来主要是执行磁盘清理工作,释放磁盘空间。在指定的时间内,依次发送消息,最终执行fstrim()向Vold发送消息。

2.1.2.3 PKMS准备完成

    @Override
        public void systemReady() {
            // 系统和root用户才可以声明系统准准备好了
            enforceSystemOrRoot("Only the system can claim the system is ready");
            
            mSystemReady = true;
            final ContentResolver resolver = mContext.getContentResolver();
            ContentObserver co = new ContentObserver(mHandler) {
                ......
            };
            ......
            // 注册监听
            co.onChange(true);
            ......
            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);
                        }
                    }
                    // 移除不存在的先前用户设置保存的优先选择的activity组件
                    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);
                    }
                }
            }
            // 多用户服务systemReady
            sUserManager.systemReady();
            // If we upgraded grant all default permissions before kicking off.
            // 升级所有已获取的权限
            for (int userId : grantPermissionsUserIds) {
                // 默认授权
                mDefaultPermissionPolicy.grantDefaultPermissions(userId);
            }
            ......
            // Now that we've scanned all packages, and granted any default
            // permissions, ensure permissions are updated. Beware of dragons if you
            // try optimizing this.
            synchronized (mPackages) {
                // 更新权限信息
                mPermissionManager.updateAllPermissions(
                        StorageManager.UUID_PRIVATE_INTERNAL, false, mPackages.values(),
                        mPermissionCallback);
            }
            ......
            // Watch for external volumes that come and go over time
            // 注意随时间变化的外部存储设备
            final StorageManager storage = mContext.getSystemService(StorageManager.class);
            storage.registerListener(mStorageListener);
            // installerService等ready
            mInstallerService.systemReady();
            mDexManager.systemReady();
            mPackageDexOptimizer.systemReady();

            StorageManagerInternal StorageManagerInternal = LocalServices.getService(
                    StorageManagerInternal.class);
            StorageManagerInternal.addExternalStoragePolicy(
                    new StorageManagerInternal.ExternalStorageMountPolicy() {
                @Override
                public int getMountMode(int uid, String packageName) {
                    if (Process.isIsolated(uid)) {
                        return Zygote.MOUNT_EXTERNAL_NONE;
                    }
                    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
            sUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
            reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
            // PermissionManager systemReady
            mPermissionManager.systemReady();

            if (mInstantAppResolverConnection != null) {
                mContext.registerReceiver(new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        mInstantAppResolverConnection.optimisticBind();
                        mContext.unregisterReceiver(this);
                    }
                }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
            }

        }
  

在systemReady()中,主要做了以下工作:

  1. 完成默认授权
  2. 更新pakcage信息
  3. 通知一些pkms的组件,告知systemReady

2.2 PKMS.main()

pkms位置:

platform/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

PKMS.main()函数如下:

public static PackageManagerService main(Context context, Installer installer,
        boolean factoryTest, boolean onlyCore) {
    // 检查Package编译相关系统属性
    PackageManagerServiceCompilerMapping.checkProperties();
    // 初始化PackageManagerService对象
    PackageManagerService m = new PackageManagerService(context, installer,
            factoryTest, onlyCore);
    // 启动部分应用服务于多用户场景       
    m.enableSystemUserPackages();
    // 将package作为PackageManagerService的名字注册到ServiceManager。binder注册的接口
    ServiceManager.addService("package", m);
    // 通过PackageManagerService获得一个PackageManagerNative对象 pmn
    final PackageManagerNative pmn = m.new PackageManagerNative();
    // 将package_native作为PackageManagerNative的名字注册到ServiceManager
    ServiceManager.addService("package_native", pmn);
    return m;
}

PKMS.main()中,主要工作如下:

  1. 检查Package编译相关系统属性
  2. 调用PackageManagerService的构造方法,创建一个PackageManagerService对象
  3. 启动部分应用服务于多用户场景
  4. 分别以package和package_native作为PackageManagerService和PackageManagerNative的名称注册到ServiceManager中

依次查看以上几个核心工作的代码,其中重点查看创建PackageManagerService对象。

  1. 检查Package编译相关系统属性

PackageManagerServiceCompilerMapping位置:

/frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
// Check that the properties are set and valid.
// Note: this is done in a separate method so this class can be statically initialized.
static void checkProperties() {
    // We're gonna check all properties and collect the exceptions, so we can give a general
    // overview. Store the exceptions here.
    RuntimeException toThrow = null;

    for (int reason = 0; reason <= PackageManagerService.REASON_LAST; reason++) {
        try {
            // Check that the system property name is legal.
            String sysPropName = getSystemPropertyName(reason);
            if (sysPropName == null || sysPropName.isEmpty()) {
                throw new IllegalStateException("Reason system property name \"" +
                        sysPropName +"\" for reason " + REASON_STRINGS[reason]);
            }

            // Check validity, ignore result.
            getAndCheckValidity(reason);
        } catch (Exception exc) {
            if (toThrow == null) {
                toThrow = new IllegalStateException("PMS compiler filter settings are bad.");
            }
            toThrow.addSuppressed(exc);
        }
    }

    if (toThrow != null) {
        throw toThrow;
    }
}

在这个函数中,检查一些编译过程中的系统属性,略过。

  1. 调用PackageManagerService的构造方法,创建一个PackageManagerService对象
public PackageManagerService(Context context, Installer installer,
        boolean factoryTest, boolean onlyCore) {
    // 阶段1:BOOT_PROGRESS_PMS_START    
    LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "create package manager");
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
            SystemClock.uptimeMillis());
    ......
    // 阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
    long startTime = SystemClock.uptimeMillis();
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                    startTime);
    ......
    // 阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START
    if(!mOlnyCore){
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
        SystemClock.uptimeMillis());
    scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
    scanDirTracedLI(sDrmAppPrivateInstallDir, mDefParseFlags
        | PackageParser.PARSE_FORWARD_LOCK,
        scanFlags | SCAN_REQUIRE_KNOWN, 0);
    ......
    }
    ......
    // 阶段4:BOOT_PROGRESS_PMS_SCAN_END
    mPackageUsage.read(mPackages);
    mCompilerStats.read();
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
    ......
    // 阶段5:BOOT_PROGRESS_PMS_READY
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings");
    mSettings.writeLPr();
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                    SystemClock.uptimeMillis());  
    ......
    
    }
        

PackageManagerService()的构造主要分为五个阶段,这五个阶段分别是:

  • 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

以上五个阶段除了BOOT_PROGRESS_PMS_START,其余阶段均位于轻量级同步锁mInstallLock和mPackages中。

此部分代码较多较复杂,且为PKMS.main()的核心方法,详细解析见2.3

  1. 启动部分应用服务于多用户场景
private void enableSystemUserPackages() {
        // 系统是否是多用户
        if (!UserManager.isSplitSystemUser()) {
            return;
        }
        // For system user, enable apps based on the following conditions:
        // - app is whitelisted or belong to one of these groups:
        //   -- system app which has no launcher icons
        //   -- system app which has INTERACT_ACROSS_USERS permission
        //   -- system IME app
        // - app is not in the blacklist
        AppsQueryHelper queryHelper = new AppsQueryHelper(this);
        Set<String> enableApps = new ArraySet<>();
        enableApps.addAll(queryHelper.queryApps(AppsQueryHelper.GET_NON_LAUNCHABLE_APPS
                | AppsQueryHelper.GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM
                | AppsQueryHelper.GET_IMES, /* systemAppsOnly */ true, UserHandle.SYSTEM));
        // 获取白名单应用。如上google注释:需要判断白名单中的应用是否满足注释中的情况        
        ArraySet<String> wlApps = SystemConfig.getInstance().getSystemUserWhitelistedApps();
        enableApps.addAll(wlApps);
        enableApps.addAll(queryHelper.queryApps(AppsQueryHelper.GET_REQUIRED_FOR_SYSTEM_USER,
                /* systemAppsOnly */ false, UserHandle.SYSTEM));
        // 获取黑名单应用。        
        ArraySet<String> blApps = SystemConfig.getInstance().getSystemUserBlacklistedApps();
        enableApps.removeAll(blApps);
        Log.i(TAG, "Applications installed for system user: " + enableApps);
        List<String> allAps = queryHelper.queryApps(0, /* systemAppsOnly */ false,
                UserHandle.SYSTEM);
        final int allAppsSize = allAps.size();
        synchronized (mPackages) {
            for (int i = 0; i < allAppsSize; i++) {
                String pName = allAps.get(i);
                PackageSetting pkgSetting = mSettings.mPackages.get(pName);
                // Should not happen, but we shouldn't be failing if it does
                if (pkgSetting == null) {
                    continue;
                }
                boolean install = enableApps.contains(pName);
                if (pkgSetting.getInstalled(UserHandle.USER_SYSTEM) != install) {
                    Log.i(TAG, (install ? "Installing " : "Uninstalling ") + pName
                            + " for system user");
                    pkgSetting.setInstalled(install, UserHandle.USER_SYSTEM);
                }
            }
            scheduleWritePackageRestrictionsLocked(UserHandle.USER_SYSTEM);
        }
    }

在系统多用户的情况下,通过白名单和黑名单来确认某些应用是否能够使用。

2.3 PKMS对象创建的五个阶段

2.3.1 BOOT_PROGRESS_PMS_START

LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "create package manager");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
        SystemClock.uptimeMillis());
......
// context
mContext = context;
// 工厂模式;一般为false,也就是默认非工厂模式
mFactoryTest = factoryTest;
// 标记是否只加载核心服务
mOnlyCore = onlyCore;
// 标记分辨率
mMetrics = new DisplayMetrics();
// installer对象
mInstaller = installer;
// 创建子组件用于提供服务、数据。
synchronized (mInstallLock) {
synchronized (mPackages) {
    // 暴露私有服务给系统组件使用
    LocalServices.addService(
            PackageManagerInternal.class, new PackageManagerInternalImpl());
    // 创建UserManagerService服务,用于用户管理,在后续代码中会用到
    sUserManager = new UserManagerService(context, this,
            new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
    // 初始化permissionManagerService        
    mPermissionManager = PermissionManagerService.create(context,
            new DefaultPermissionGrantedCallback() {
                @Override
                public void onDefaultRuntimePermissionsGranted(int userId) {
                    synchronized(mPackages) {
                        mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
                    }
                }
            }, mPackages /*externalLock*/);
    // 获取默认权限控制策略        
    mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
    // 创建settings对象
    mSettings = new Settings(mPermissionManager.getPermissionSettings(), mPackages);
}
}
// 添加system、phone、log、nfc、bluetooth、shell、se这7中sharedUserId到mSettings中
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);
        
        // 获取SystemProperties中的debug.separate_processes属性
        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;
}
    // dex优化类。在Android 8.0之后,dex优化由PackageDexOptimizer解决。
    mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
            "*dexopt*");
    DexManager.Listener dexManagerListener = DexLogger.getListener(this,
            installer, mInstallLock);
     // 创建dexManager对象
    mDexManager = new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock,
            dexManagerListener);
     // 获取ArtManagerService对象,art虚拟机管理服务
    mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock);
    mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
    // 权限改动监听器
    mOnPermissionChangeListeners = new OnPermissionChangeListeners(
            FgThread.get().getLooper());
    // 获取默认分辨率
    getDefaultDisplayMetrics(context, mMetrics);
    
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "get system config");
    // 获取系统配置systemconfig对象,其中会调用systemcomfig.readPermission()完成权限读取
    SystemConfig systemConfig = SystemConfig.getInstance();
    // 查看系统配置中的可用特点
    mAvailableFeatures = systemConfig.getAvailableFeatures();
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    mProtectedPackages = new ProtectedPackages(mContext);
    
    synchronized (mInstallLock) {
    // writer
    synchronized (mPackages) {
        // 创建一个“PackageManager”的handler线程,负责apk的安装、卸载
        mHandlerThread = new ServiceThread(TAG,
                Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
        mHandlerThread.start();
        mHandler = new PackageHandler(mHandlerThread.getLooper());
        // 进程记录handler
        mProcessLoggingHandler = new ProcessLoggingHandler();
        // watchdog监听是都超时:10分钟
        Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
        // instantApp应用注册
        mInstantAppRegistry = new InstantAppRegistry(this);

        // 获取共享库
        ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
        final int builtInLibCount = libConfig.size();
        for (int i = 0; i < builtInLibCount; i++) {
            String name = libConfig.keyAt(i);
            String path = libConfig.valueAt(i);
            addSharedLibraryLPw(path, null, name, SharedLibraryInfo.VERSION_UNDEFINED,
                    SharedLibraryInfo.TYPE_BUILTIN, PLATFORM_PACKAGE_NAME, 0);
        }
        // 读取selinux的install策略
        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) {
            // 拷贝预编译的dex文件
            requestCopyPreoptedFiles();
        }
        ......

从以上代码中,可以看到在BOOT_PROGRESS_PMS_START阶段主要做了以下工作:

  • 构造DisplayMetrics,保存分辨率等信息
  • 暴露私有服务给系统组件使用
  • 创建UserManagerService、permissionManagerService等服务的对象,用于管理多用户和方便后续代码的使用
  • 创建Settings对象,并添加system、phone、log、nfc、bluetooth、shell、se这7中sharedUserId到Settings中
  • 创建PackageDexOptimizer、DexManager等类,用于dex优化[android 6.0中字节码优化不在此处]
  • 创建一个“PackageManager”的handler线程,循环处理外部安装相关消息
  • 创建systemConfig实例,获取系统配置信息,获取共享库
  • 如果不是核心模式,并且是第一次重启机器,就复制优化完成的dex文件
  • 清理孤立的包:代码路径不存在的包。这些包是系统应用程序的更新

2.3.1.1 new Settings()

Settings.java:frameworks/base/services/core/java/com/android/server/pm/Settings.java

// 调用Settings(File dataDir, PermissionSettings permission, Object lock)
Settings(PermissionSettings permissions, Object lock) {
    this(Environment.getDataDirectory(), permissions, lock);
}

Settings(File dataDir, PermissionSettings permission, Object lock) {
    mLock = lock;
    mPermissions = permission;
    mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);

    // 创建mSystemDir目录
    mSystemDir = new File(dataDir, "system");
    mSystemDir.mkdirs();
    // 调用chmod接口给目录设置权限
    FileUtils.setPermissions(mSystemDir.toString(),
            FileUtils.S_IRWXU|FileUtils.S_IRWXG
            |FileUtils.S_IROTH|FileUtils.S_IXOTH,
            -1, -1);
    // 在mSystemDir目录下创建文件
    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");
}

在Settings()的初始化方法中,主要做了以下工作:

  • 创建mSystemDir 并为mSystemDir设置权限
  • 在mSystemDir目录下创建文件

其中mSystemDir路径为:data/system;在new settings()中添加了以下文件到该路径下:

路径文件名称功能
/data/systempackages.xml记录所有安装的app信息
packages-backup.xmlpackages的备份文件
packages.list记录应用的数据信息
packages-stopped.xml记录系统被强制停止的文件
packages-stopped-backup.xmlpackages-stopped的备份文件
/data/system /config/sdcardfs

2.3.1.2 SystemConfig.getInstance()

SystemConfig.java frameworks/base/core/java/com/android/server/SystemConfig.java

// 单例创建一个SystemConfig对象
public static SystemConfig getInstance() {
    synchronized (SystemConfig.class) {
        if (sInstance == null) {
            sInstance = new SystemConfig();
        }
        return sInstance;
    }
}

SystemConfig() {
    // 读取系统配置的权限
    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 customze libs, features and privapp permissions
    int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS;
    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);

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

    // Allow Product to customize system configs around libs, features, permissions and apps
    int productPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
            ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
    readPermissions(Environment.buildPath(
            Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
}


// 读取指定路径下的xml文件中包含的权限
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);
    }
}

readPermissions()解析指定目录下的XML文件,然后将读取到的权限保存到PKMS中。所以在SystemConfig的创建过程中,主要是将以下目录中的.xml文件进行解析:

  • /system/etc/sysconfig
  • /system/etc/permissions
  • /vendor/etc/sysconfig
  • /vendor/etc/permissions
  • /odm/etc/sysconfig
  • /odm/etc/permissions
  • /product/etc/sysconfig
  • /product/etc/permissions

2.3.2 BOOT_PROGRESS_PMS_SYSTEM_SCAN_START

long startTime = SystemClock.uptimeMillis();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
        startTime);

// 获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH
final String bootClassPath = System.getenv("BOOTCLASSPATH");
final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
......
// 创建framework路径:system/framework
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);
}

// 当从pre-M更新时,把系统app的权限提升到运行时
mPromoteSystemApps =
        mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;

// 当从pre-N更新时,我们需要像首次启动一样获取系统包信息,因为没有可用的分析数据
mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;
mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;

// 扫描之前存储下预先存在的系统包,我们不想要自动授予新的系统app运行时权限。区分新老应用
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(mIsUpgrade);

// 设置一个标签,用于在扫描安装路径的时候监听和不改变apk路径.
int scanFlags = SCAN_BOOTING | SCAN_INITIAL;

if (mIsUpgrade || mFirstBoot) {
    scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
}

// 收集vendor/product目录下面的包,这个目录下一般是供应商提供的apk。
// 为了安全和版本控制,只考虑正确目录下的包
scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM
        | SCAN_AS_VENDOR,
        0);
scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM
        | SCAN_AS_PRODUCT,
        0);

// 扫描framework/base
scanDirTracedLI(frameworkDir,
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_NO_DEX
        | SCAN_AS_SYSTEM
        | SCAN_AS_PRIVILEGED,
        0);

// 收集私有系统包名:system/priv-app目录下的包名
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirTracedLI(privilegedAppDir,
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM
        | SCAN_AS_PRIVILEGED,
        0);

// 收集一般包名:system/app目录下的包名
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir,
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM,
        0);

// 收集私有供应商包名:vendor/priv-app 目录下的包名
File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
try {
    privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile();
} catch (IOException e) {
    // failed to look up canonical path, continue with original one
}
scanDirTracedLI(privilegedVendorAppDir,
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM
        | SCAN_AS_VENDOR
        | SCAN_AS_PRIVILEGED,
        0);

// 收集一般供应商包名:vendor/app目录下的包名
File vendorAppDir = new File(Environment.getVendorDirectory(), "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_DIR,
        scanFlags
        | SCAN_AS_SYSTEM
        | SCAN_AS_VENDOR,
        0);

// 收集私有odm包名:odm/priv-app目录下的包名。/odm是另外一个供应商分区,和/vendor类似
File privilegedOdmAppDir = new File(Environment.getOdmDirectory(),
            "priv-app");
try {
    privilegedOdmAppDir = privilegedOdmAppDir.getCanonicalFile();
} catch (IOException e) {
    // failed to look up canonical path, continue with original one
}
scanDirTracedLI(privilegedOdmAppDir,
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM
        | SCAN_AS_VENDOR
        | SCAN_AS_PRIVILEGED,
        0);

// 收集一般odm包名:odm/app目录下的包名。/odm是另外一个供应商分区,和/vendor类似
File odmAppDir = new File(Environment.getOdmDirectory(), "app");
try {
    odmAppDir = odmAppDir.getCanonicalFile();
} catch (IOException e) {
    // failed to look up canonical path, continue with original one
}
scanDirTracedLI(odmAppDir,
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM
        | SCAN_AS_VENDOR,
        0);

// 收集所有OEM包名:/oem/app目录下的包名
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirTracedLI(oemAppDir,
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM
        | SCAN_AS_OEM,
        0);

// 收集私有product包名:product/priv-app目录下的包名
File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
try {
    privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile();
} catch (IOException e) {
    // failed to look up canonical path, continue with original one
}
scanDirTracedLI(privilegedProductAppDir,
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM
        | SCAN_AS_PRODUCT
        | SCAN_AS_PRIVILEGED,
        0);

// 收集普通product包名:product/app目录下的包名
File productAppDir = new File(Environment.getProductDirectory(), "app");
try {
    productAppDir = productAppDir.getCanonicalFile();
} catch (IOException e) {
    // failed to look up canonical path, continue with original one
}
scanDirTracedLI(productAppDir,
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM
        | SCAN_AS_PRODUCT,
        0);

// 删除不存在的系统包
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
final List<String> stubSystemApps = new ArrayList<>();
if (!mOnlyCore) {
    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 ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
            continue;
        }
        final PackageParser.Package scannedPkg = mPackages.get(ps.name);
        if (scannedPkg != null) {
            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 {
          
            final PackageSetting disabledPs =
                    mSettings.getDisabledSystemPkgLPr(ps.name);
            if (disabledPs.codePath == null || !disabledPs.codePath.exists()
                    || disabledPs.pkg == null) {
                possiblyDeletedUpdatedSystemApps.add(ps.name);
            }
        }
    }
    // 删除临时文件
    deleteTempPackageFiles();
    
    final int cachedSystemApps = PackageParser.sCachedPackageReadCount.get();
    
    // 删除所有不相干包中的共享userid
    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);
    }
}

  1. 在BOOT_PROGRESS_PMS_SYSTEM_SCAN_START阶段,主要做了以下工作:

    • 做扫描前的准备工作,例如创建相关变量、授予运行时权限、保存指定路径下的包名。
    • 使用scanDirL(),扫描指定的系统目录下的apk包名,最终调用PackageParser.parseBaseApk完成AndroidManifest.xml文件的解析后,根据xml标签,生成Application, activity,service,broadcast, provider等信息。系统目录主要包括:
      • system/framework
      • vendor/product
      • system/priv-app
      • system/app
      • vendor/priv-app
      • vendor/app
      • odm/priv-app
      • odm/app
      • oem/app
      • product/priv-app
      • product/app
    • 删除某些系统包、临时文件、不相干包中的共享userid。

2.3.3 BOOT_PROGRESS_PMS_DATA_SCAN_START

// 处理非系统app
if (!mOnlyCore) {
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
            SystemClock.uptimeMillis());
    // 扫描/data/app目录,收集data/app目录下的包名        
    scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
    // 扫描data/priv-app目录,收集data/priv-app目录下的包名
    scanDirTracedLI(sDrmAppPrivateInstallDir, mDefParseFlags
            | PackageParser.PARSE_FORWARD_LOCK,
            scanFlags | SCAN_REQUIRE_KNOWN, 0);

    // 取消禁用更新的系统应用程序OTA取消的禁用设置,如果更新不再存在,则将应用程序完全删除,否则,将其系统权限撤消。
    for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
        PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
        mSettings.removeDisabledSystemPackageLPw(deletedAppName);
        final String msg;
        if (deletedPkg == null) {
            // should have found an update, but, we didn't; remove everything
            msg = "Updated system package " + deletedAppName
                    + " 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 + " + deletedAppName
                    + " no longer exists; revoking system privileges";

            // Don't do anything if a stub is removed from the system image. If
            // we were to remove the uncompressed version from the /data partition,
            // this is where it'd be done.

            final PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
            deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
            deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
        }
        logCriticalInfo(Log.WARN, msg);
    }

     // 确保我们期望在用户数据分区出现的所有系统apps真的出现。如果他们从未出现,回滚并恢复系统版本
    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");
            // 定义reparseFlags和rescanFlags,扫描/system/app、/system/priv-app等目录,初始化这两个变量
            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 {
                Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                continue;
            }
            // 使得system app可用
            mSettings.enableSystemPackageLPw(packageName);

            try {
                // 使用以上两个参数扫描apk包名
                scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);
            } catch (PackageManagerException e) {
                Slog.e(TAG, "Failed to parse original system package: "
                        + e.getMessage());
            }
        }
    }
    
    // 解压缩然后安装剩余系统软件,这个必须要最后执行,从而确保剩余的能替代或者不可用。
    decompressSystemApplications(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();

// 获取storage manager包名
mStorageManagerPackage = getStorageManagerPackageName();

// Resolve protected action filters. Only the setup wizard is allowed to
// have a high priority filter for these actions.
// 解决受保护的action过滤器,只允许开机向导setup_wizard(开机向导)为这些action设置高优先级过滤器
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;
        }
        if (DEBUG_FILTERS) {
            Slog.i(TAG, "Protected action; cap priority to 0;"
                    + " package: " + filter.activity.info.packageName
                    + " activity: " + filter.activity.className
                    + " origPrio: " + filter.getPriority());
        }
        filter.setPriority(0);
    }
}

mSystemTextClassifierPackage = getSystemTextClassifierPackageName();

mDeferProtectedFilters = false;
mProtectedFilters.clear();
// Now that we know all of the shared libraries, update all clients to have
// the correct library paths.
// 更新所有客户端以保证拥有正确的共享库的路径
updateAllSharedLibrariesLPw(null);

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) {
            }
        }
    }
    // 调整setInfo,确保共享sharedUserId的应用可以在同一个SELinux的范围内
    setting.fixSeInfoLocked();
}


主要工作:

  • 在非核心模式下,扫描和处理data/app、data/priv-app目录下的应用,更新并删除一些不必要的数据

2.3.4 BOOT_PROGRESS_PMS_SCAN_END

    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
            SystemClock.uptimeMillis());
    Slog.i(TAG, "Time to scan packages: "
            + ((SystemClock.uptimeMillis()-startTime)/1000f)
            + " seconds");
    
    // If the 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");
    }
    // SDK版本不一致时,需要更新权限
    mPermissionManager.updateAllPermissions(
            StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, mPackages.values(),
            mPermissionCallback);
    ver.sdkVersion = mSdkVersion;
    

    // 如果是首次启动或者是一个从pre-M的更新,或者是常规启动,接着需要初始化默认指定的app来满足所有的用户
    if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
        for (UserInfo user : sUserManager.getUsers(true)) {
            mSettings.applyDefaultPreferredAppsLPw(this, user.id);
            applyFactoryDefaultBrowserLPw(user.id);
            primeDomainVerificationsLPw(user.id);
        }
    }
    
    // 为系统用户在启动时准备内存,某些核心系统应用例如:SettingsProvider和SystemUI在系统之前启动
    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");
    
    // OTA后的首次启动,并且是常规启动,需要清除指定目录下的代码缓存,但不清除应用程序的配置文件
    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();
    
    // 当权限和其他默认更新已完成,清除相关信息
    mExistingSystemPackages.clear();
    mPromoteSystemApps = false;
    
    // All the changes are done during package scanning.
    // 所有的变更均在扫描中完成
    ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;

本阶段主要工作:

  • 检查权限:当sdk版本变更的时候,需要更新权限

  • 处理某些特殊情况:

    1. 从Android M更新或者第一次启动且常规启动,指定默认app满足所有用户
    2. 为系统用户在启动时准备内存,某些核心系统应用例如:SettingsProvider和SystemUI在系统之前启动
  • 权限更新后,处理相关数据

  • 更新package.xml

2.3.5 BOOT_PROGRESS_PMS_READY

// can downgrade to reader
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings");
    mSettings.writeLPr();
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    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;
    }
    // 开启packageInstallerService
    mInstallerService = new PackageInstallerService(context, this);
    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<>();
    // 获取userid
    final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
    for (int userId : currentUserIds) {
        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)

// Now after opening every single application zip, make sure they
// are all flushed.  Not really needed, but keeps things nice and
// tidy.
// 每次打开一个app的zip文件之后,都需要保证有充足的空间,因此这里清理一次虚拟机。
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "GC");
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);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

在PKMS创建的最后一个阶段,做了以下工作:

  1. 创建一个 PackageInstallerService对象
  2. 清理一次虚拟机,做一次GC

2.3.5.1 new PackageInstallerService

PackageInstallerService: frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java

public PackageInstallerService(Context context, PackageManagerService pm) {
    mContext = context;
    mPm = pm;
    // 初始化permissionManager
    mPermissionManager = LocalServices.getService(PermissionManagerInternal.class);
    // 创建一个新的线程
    mInstallThread = new HandlerThread(TAG);
    mInstallThread.start();

    mInstallHandler = new Handler(mInstallThread.getLooper());

    mCallbacks = new Callbacks(mInstallThread.getLooper());
    // 初始化mSessionsFile为AtomicFile
    mSessionsFile = new AtomicFile(
            new File(Environment.getDataSystemDirectory(), "install_sessions.xml"),
            "package-session");
    // 初始化mSessionsDir
    mSessionsDir = new File(Environment.getDataSystemDirectory(), "install_sessions");
    mSessionsDir.mkdirs();
}