PKMS 就是 PackageManagerServervice:它是透过 SystemServer 进程 启动,该服务会 扫描系统中特定的目录,寻找里面的APK格式文件,并对这些文件进行解析(得到AppInfo相关讯息),最后完成安装
PKMS 会在安装应用的过程中解析 APK 中的 AndroidManifest.xml 文件(解析出 Android 四大组件),这些解析完的信息会保存在 Android 系统中,方便系统随时取用

PMS - 主要功能

扫描 .apk 文件,安装 系统应用本地应用
Parser AndroidManifest.xml 清单文件,分析出四大零组件、权限…等等信息,并储存在 PKMS 方便查询
管理本地应用,其中包括 安装卸载查询 APK 信息 …等等功能
分配应用程序的 UID、GID

透过GID(Group群组ID)来管理权限管理,在某个群组中才能使用某些功能

PKMS - AIDL 使用

一般来说我们可以透过Context#getPackageManager()方法 来取得 PKMS 服务(其实它是取得 KMS 的代理),PackageManager 是抽象,实作类是 ApplicationPackageManager

// 调用 PKMS 方式

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // AIDL 代理对象
        // @ getPackageManager 分析
        PackageManager packageManager = this.getBaseContext().getPackageManager();
    }

ServiceManager 取得 PKMS - IPackageManager 代理

ActivityThread 透过 ServiceManager 取得 PKMS 的 IBinder,这里的
IPackageManager 是透过 AIDL 自动产生的类,IPackageManager 透过 asInterface 来取得 Java 代理类,透过该代理类来与 PKMS 通信

// ActivityThread.java

    @UnsupportedAppUsage
    public static IPackageManager getPackageManager() {
        if (sPackageManager != null) {
            return sPackageManager;
        }
        
        // 1.取得ServiceManager的代理
        // 2.透过代理传入“package”来取得PKMS的句柄(handle)
        // 3.返回PKMS的代理
        final IBinder b = ServiceManager.getService("package");
        
        // 创建 AIDL 的代理类
        sPackageManager = IPackageManager.Stub.asInterface(b);
        
        return sPackageManager;
    }

SystemServer 初始化 PKMS

SystemServer 是 init 进程所孵化的第一个进程,在里面会有许多系统服务会启动,而其中又区分为三种
启动引导服务(startBootstrapServices):PKMS 就是在这里启动
核心进程(startCoreServices)
其他服务(startOtherServices)

// SystemServer.java

public static void main(String[] args) {
    new SystemServer().run();
}


private void run() {
    ... 省略部分

    try {
        startBootstrapServices(t);
        startCoreServices(t);
        startOtherServices(t);
    } /* 省略 catch */

    ... 省略部分

    // Loop forever.
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}


private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) 
    ... 省略部分

    // 安装服务
    Installer installer = mSystemServiceManager.startService(Installer.class);

    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

    ... 省略部分

    try {
        ... watch dog

        // 呼叫 PackageManagerService 的静态 main 方法
        // @ 分析 main
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                domainVerificationService, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF,
                mOnlyCore);
    } ... watch dog

    ... 省略部分
}

分析 startBootstrapServices - PKMS 启动部分

启动 Installer 服务,之后会用这个服务来安装所有应用

// SystemServer.java

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
    ... 省略部分

    Installer installer = mSystemServiceManager.startService(Installer.class);

    ... 省略部分
}

VoldProperties#decrypt 判断手机装置是否加密(读取 init.rc 档的设定),mOnlyCore = true 代表只运行核心程序(创建一个极简的启动环境)

// SystemServer.java

private static final String ENCRYPTING_STATE = "trigger_restart_min_framework";

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
    ... 省略部分

    // Only run "core" apps if we're encrypting the device.
    String cryptState = VoldProperties.decrypt().orElse("");

    if (ENCRYPTING_STATE.equals(cryptState)) {
        // 只运行核心程序
        ... log msg

        mOnlyCore = true;
    } else if (ENCRYPTED_STATE.equals(cryptState)) {
        ... log msg

        mOnlyCore = true;
    }

    ...
}

调用PKMS#main方法,创建 PKMS 对象

// SystemServer.java

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
    ... 省略部分

    try {
        ...

        PackageManagerService.main(mSystemContext, installer,
                domainVerificationService, 
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF,
                mOnlyCore);    // 假设传入 false
    } /* 省略 finally */
    
    ... 省略部分
}

如果设备没有加密,就执行A/B OTA dexopting,OtaDexoptService#main方法

// SystemServer.java

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
    ... 省略部分

    if (!mOnlyCore) {
        boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                false);

        if (!disableOtaDexopt) {
            ... trace log
            try {
                ... watch dog
                    
                OtaDexoptService.main(mSystemContext, mPackageManagerService);
            } /* 省略 catch、finally */
        }
    }

    ... 省略部分
}

分析 startOtherServices - PKMS 后续操作

PKMS在 SystemServer#startBootstrapServices函数 完成初始化操作后,会在 startOtherServices 做后续的操作(完成Dex优化、systemReady)
透过PKMS#performFstrimIfNeeded完成 dex 优化

// SystemServer.java

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {

    ... 省略部分

    try {
        mPackageManagerService.performFstrimIfNeeded();
    } ...

    ... 省略部分
}

PKMS 准备就绪调用 systemReady加载预设权限

PKMS 分析

PKMS#main - 初始化 PKMS 物件 - Injector

透过PackageManagerService#main方法就可以创建 PackageManagerService 物件,并且将 PKMS 透过 packagepackage_native 添加到 ServiceManager 中

// PackageManagerService.java

public static PackageManagerService main(Context context, Installer installer,
        @NonNull DomainVerificationService domainVerificationService, boolean factoryTest,
        boolean onlyCore) {

    // 检查 package 编译相关系统属性
    PackageManagerServiceCompilerMapping.checkProperties();

    ... 省略部分

    // Injector是内部类,之后会使用这个注入取得需要的东西,
    //而Injector取得的数据则是单例
    Injector injector = new Injector(
            context, lock, installer, installLock, new PackageAbiHelperImpl(),
            backgroundHandler,
            SYSTEM_PARTITIONS,
            (i, pm) -> new ComponentResolver(i.getUserManagerService(), pm.mPmInternal, lock),
            (i, pm) -> PermissionManagerService.create(context,
                    i.getSystemConfig().getAvailableFeatures()),
            (i, pm) -> new UserManagerService(context, pm,
                    new UserDataPreparer(installer, installLock, context, onlyCore),
                    lock),
            (i, pm) -> new Settings(Environment.getDataDirectory(),
                    RuntimePermissionsPersistence.createInstance(),
                    i.getPermissionManagerServiceInternal(),
                    domainVerificationService, lock),
            (i, pm) -> AppsFilter.create(pm.mPmInternal, i),
            (i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"),
            (i, pm) -> SystemConfig.getInstance(),
            (i, pm) -> new PackageDexOptimizer(i.getInstaller(), i.getInstallLock(),
                    i.getContext(), "*dexopt*"),
            (i, pm) -> new DexManager(i.getContext(), pm, i.getPackageDexOptimizer(),
                    i.getInstaller(), i.getInstallLock()),
            (i, pm) -> new ArtManagerService(i.getContext(), pm, i.getInstaller(),
                    i.getInstallLock()),
            (i, pm) -> ApexManager.getInstance(),
            (i, pm) -> new ViewCompiler(i.getInstallLock(), i.getInstaller()),
            (i, pm) -> (IncrementalManager)
                    i.getContext().getSystemService(Context.INCREMENTAL_SERVICE),
            (i, pm) -> new DefaultAppProvider(() -> context.getSystemService(RoleManager.class),
                    () -> LocalServices.getService(UserManagerInternal.class)),
            (i, pm) -> new DisplayMetrics(),
            (i, pm) -> new PackageParser2(pm.mSeparateProcesses, pm.mOnlyCore,
                    i.getDisplayMetrics(), pm.mCacheDir,
                    pm.mPackageParserCallback) /* scanningCachingPackageParserProducer */,
            (i, pm) -> new PackageParser2(pm.mSeparateProcesses, pm.mOnlyCore,
                    i.getDisplayMetrics(), null,
                    pm.mPackageParserCallback) /* scanningPackageParserProducer */,
            (i, pm) -> new PackageParser2(pm.mSeparateProcesses, false, i.getDisplayMetrics(),
                    null, pm.mPackageParserCallback) /* preparingPackageParserProducer */,
            // Prepare a supplier of package parser for the staging manager to parse apex file
            // during the staging installation.
            (i, pm) -> new PackageInstallerService(
                    i.getContext(), pm, i::getScanningPackageParser),
            (i, pm, cn) -> new InstantAppResolverConnection(
                    i.getContext(), cn, Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE),
            (i, pm) -> new ModuleInfoProvider(i.getContext(), pm),
            (i, pm) -> LegacyPermissionManagerService.create(i.getContext()),
            (i, pm) -> domainVerificationService,
            (i, pm) -> {
                // 负责 apk 安装、卸载
                HandlerThread thread = new ServiceThread(TAG,
                        Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
                thread.start();
                return pm.new PackageHandler(thread.getLooper());
            },
            new DefaultSystemWrapper(),
            LocalServices::getService,
            context::getSystemService);

    // 调用 PackageMangerService 的构造函数
    PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest,
            Build.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG, Build.VERSION.SDK_INT,
            Build.VERSION.INCREMENTAL);

    ... 省略部分

    // 透过 package、package_native 添加到 ServiceManager中
    ServiceManager.addService("package", m);
    final PackageManagerNative pmn = m.new PackageManagerNative();
    ServiceManager.addService("package_native", pmn);
    return m;
}

IInject 是 PKMS 中的一个内部类,可以透过它来达到 单例的功能 (并且有延迟加载的功能)、其他类可以取得PKMS实例

// PackageManagerService.java

public static class Injector {

    @VisibleForTesting(visibility = Visibility.PRIVATE)
    interface Producer<T> {
        /** Produce an instance of type {@link T} */
        T produce(Injector injector, PackageManagerService packageManager);
    }

    ... 省略部分

    @VisibleForTesting(visibility = Visibility.PRIVATE)
    static class Singleton<T> {
        private final Producer<T> mProducer;
        private volatile T mInstance = null;

        Singleton(Producer<T> producer) {
            this.mProducer = producer;
        }

        T get(Injector injector, PackageManagerService packageManagerService) {
            if (mInstance == null) {
                mInstance = mProducer.produce(injector, packageManagerService);
            }
            return mInstance;
        }
    }

    // 透过 Singleton 泛型创建出来的都是单例对象

    private final Singleton<PermissionManagerServiceInternal> mPermissionManagerServiceProducer;
    private final Singleton<UserManagerService> mUserManagerProducer;
    private final Singleton<Settings> mSettingsProducer;
    private final Singleton<AppsFilter> mAppsFilterProducer;
    ... 省略部分
    private final Singleton<DisplayMetrics> mDisplayMetricsProducer;

    Injector(Context context, PackageManagerTracedLock lock, Installer installer,
            Object installLock, PackageAbiHelper abiHelper,
            Handler backgroundHandler,
            List<ScanPartition> systemPartitions, /* 省略部分入參 */,

            Producer<PermissionManagerServiceInternal> permissionManagerServiceProducer,
            Producer<UserManagerService> userManagerProducer,
            Producer<Settings> settingsProducer,
            Producer<DisplayMetrics> displayMetricsProducer,
            ) {

        ... 省略部分

        mPermissionManagerServiceProducer = new Singleton<>(permissionManagerServiceProducer);
        mUserManagerProducer = new Singleton<>(userManagerProducer);
        mSettingsProducer = new Singleton<>(settingsProducer);

        ... 省略部分

        mDisplayMetricsProducer = new Singleton<>(displayMetricsProducer);
    }

    public PermissionManagerServiceInternal getPermissionManagerServiceInternal() {
        return mPermissionManagerServiceProducer.get(this, mPackageManager);
    }

    public Context getContext() {
        return mContext;
    }

    public Settings getSettings() {
        return mSettingsProducer.get(this, mPackageManager);
    }

    public DisplayMetrics getDisplayMetrics() {
        return mDisplayMetricsProducer.get(this, mPackageManager);
    }

    ... 省略部分

}

PKMS 构造方法

PackageManagerService 的构造函数中可以发现 PKMS 构造有 5个阶段 (写在 EventLog 中)

阶段标志说明其他
BOOT_PROGRESS_PMS_START初始阶段,透过Inject内部类来取得 单例 的各种服务、对象DisplayMetrics、Installer、mPermissionManager、mSettings、mPackageDexOptimizer
BOOT_PROGRESS_PMS_SYSTEM_SCAN_START扫描系统
BOOT_PROGRESS_PMS_DATA_SCAN_START扫描 data 区块
BOOT_PROGRESS_PMS_SCAN_END扫描结束
BOOT_PROGRESS_PMS_READY准备阶段

PKMS 有使用到多 Thread,而里面有两个重要的 需要注意

锁名称说明补充
mPackages(小锁)用于保护所有内存中解析 Package 的细节、状态、更新在持有 mInstallLock 的时候,获取 mPackages 是安全的
mInstallLock(大锁)用于保护所有安装 APK 时的锁,通常是有关到应用 APP 的重载(单线程、涉及繁重的 IO 操作在获取 mPackages 时,不该再获取此锁

第一阶段 - BOOT_PROGRESS_PMS_START

第一阶段的重点是 Settings#readLPw方法,读取 /data/system 目录下的文件
BOOT_PROGRESS_PMS_START:取得 DisplayMetrics(分辨率)、Installer(安装)、PermissionManager (权限管理)、mSettings(保存安装信息、清除不存在的应用)、PackageDexOptimizer(Dex优化)…详细请看注释
// PackageManagerService.java

    public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
            final String buildFingerprint, final boolean isEngBuild,
            final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

        ... 省略部分

        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                SystemClock.uptimeMillis());


        mOnlyCore = onlyCore;

        // 透过 injector 取得需要物件
        mMetrics = injector.getDisplayMetrics();    // 分辨率
        mInstaller = injector.getInstaller();        // 安裝器

        mUserManager = injector.getUserManagerService(); // 多用戶管理

        // 权限管理服务
        mPermissionManager = injector.getPermissionManagerServiceInternal();

        // 涉及 'data/system/' packages.xml
        // packages-backup.xml
        // packages.list
        // packages-stopped.xml
        // packages-stopped-backup.xml 文件
        mSettings = injector.getSettings();    // 保存安裝訊息、清除不存在的應用

        ... 省略部分

        // 添加 system、phone、log、nfc、bluetooth、shell、se、
        //     networkstack、uwb 这几个 sharedUserLPw 到 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);
        mSettings.addSharedUserLPw("android.uid.networkstack", NETWORKSTACK_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.uwb", UWB_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

        ... 省略部分

        // 处理 dex 优化(DexOpt 优化)
        mPackageDexOptimizer = injector.getPackageDexOptimizer();
        mDexManager = injector.getDexManager();
        // Art 虚拟机管理
        mArtManagerService = injector.getArtManagerService();

        ... 省略部分

        // 创建 /data/app 文件夹
        mAppInstallDir = new File(Environment.getDataDirectory(), "app");

        // 安装 APK 时需要的锁,保护所有对 installed 的访问
        // CHECKSTYLE:OFF IndentationCheck
        synchronized (mInstallLock) {
        // writer
        synchronized (mLock) {
            // 启动 PackageManager Thread,负责 apk 安装、卸载
            mHandler = injector.getHandler();
            // 进程纪录 Handler
            mProcessLoggingHandler = new ProcessLoggingHandler();
            
            // 监听 PackageManager Thread 是否超时10分钟
            Watchdog.getInstance().addThread(mHandler, 
                                     // WATCHDOG_TIMEOUT => 10 分鐘
                                     WATCHDOG_TIMEOUT);
        
            ... 省略部分
                
            // 读取安装相关的 SELinux 策略
            SELinuxMMAC.readInstallPolicy();
            
            // 读取并解析 /data/system 中的 xml 文件
            // 
            // @ 分析 readLPw 方法 !!!!!
            mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
            
            t.traceEnd();
        }
        
        }
    }

其中 mSettings.addSharedUserLPw 方法是将 SharedUserId 添加到Setting中;一般来讲进程间数据不可共享,但 有共同 SharedUserId 就可以共享数据
mPackageDexOptimizer 是 Dex 的优化工具
mHandler 绑定后台 ServiceThread 的消息队列,PKMS 通过它来驱动 APK 复制&安装,并且该 Handler 会由 WatchDog 来监看(防止花费过多时间)
PKMD 会访问几个重要的文件夹

访问资料夾
File(Environment.getDataDirectory(), “app”)/data/app
File(Environment.getDataDirectory(), “app-lib”)/data/app-lib

Settings 创建

先复习 Settings 对象由来:PKMS 的 Settings 对象会由PKMS#Inject类提供

// PackageManager

    public static class Injector {

        private final Singleton<Settings> mSettingsProducer;

        Injector(/* 省略参数 */) {
            ... 省略部分
            mSettingsProducer = new Singleton<>(settingsProducer);
        }

        public Settings getSettings() {
            return mSettingsProducer.get(this, mPackageManager);
        }

    }

    public static PackageManagerService main(Context context, Installer installer,
            @NonNull DomainVerificationService domainVerificationService, boolean factoryTest,
            boolean onlyCore) {
        
        Injector injector = new Injector(
                context, lock, installer, installLock, new PackageAbiHelperImpl(),
                backgroundHandler,
                SYSTEM_PARTITIONS,
            ... 省略部分

            //真正new出物件的地方
            // @追踪Settings建构方法
            (i, pm) -> new Settings(Environment.getDataDirectory(),    // /data 資料夾
                        RuntimePermissionsPersistence.createInstance(),
                        i.getPermissionManagerServiceInternal(),
                        domainVerificationService, 
                        lock),
        );
    }

Settings 类 的构造函数会创建所需文件&文件夹,并设定它们的权限

// Settings.java

Settings(File dataDir,    //带入的 dataDir 是 /data
         RuntimePermissionsPersistence runtimePermissionsPersistence,
        LegacyPermissionDataProvider permissionDataProvider,
        @NonNull DomainVerificationManagerInternal domainVerificationManager,
        @NonNull PackageManagerTracedLock lock)  {

    ... 省略部分

    // 创建 /data/system 目录
    mSystemDir = new File(dataDir, "system");    // mSystemDir 目錄指向 '/data/system'
    mSystemDir.mkdirs();    // 创建 /data/system
    // 设定文件夹权限 775
    FileUtils.setPermissions(mSystemDir.toString(),
            FileUtils.S_IRWXU|FileUtils.S_IRWXG
            |FileUtils.S_IROTH|FileUtils.S_IXOTH,
            -1, -1);

    // 创建 /data/system/packages.xml 档案
    mSettingsFilename = new File(mSystemDir, "packages.xml");
    // 创建 /data/system/packages-backup.xml 档案
    mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
    // 创建 data/system/packages.list 档案
    mPackageListFilename = new File(mSystemDir, "packages.list");

    // 设定 chmod 0640
    FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);

    final File kernelDir = new File("/config/sdcardfs");
    mKernelMappingFilename = kernelDir.exists() ? kernelDir : null;

    // Deprecated: Needed for migration
    // 创建 data/system/packages-stopped.list 档案
    mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
    // 创建 data/system/packages-stopped-backup.list 档案
    mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");

    ... 省略部分

}

Settings - readLPw 读取 package 文件

mSettings#readLPw() 函数:读取 /data/system 目录下的文件,并保存到Setting对象中,而文件又分为以下几种(提出较为重要的几个)

文件名说明其他
packages.xml安装 app 信息PKMS 扫描完目录文件后会创建该文件,当系统执行 安装、卸载、更新 等操作时都会更新这个文件
packages-backup.xml安装 app 的备份信息避免在安装时关机,产生意外
packages.list所有安装的app信息(非系统APP)描述所有非系统APK信息,当有第三方APP变更时就会修改该文件
packages-stopped.xml强制停止 app 信息强制停止某个应用时(用户操作),系统会将该应用的相关讯息记录到该文件中
packages-stopped-backup.xml强制停止 app 的备份信息

mSettings#readLPw() 功能:首先扫描 packages.xmlpackages-backup.xml 文件,其中与Linux使用 UID 有关的函数如下
“package”标签:使用 readPackageLPw 函数,读取上一次分配的 Linux UID
“shared-user”标签:使用 readSharedUserLPw 函数,读取上一次应用共享的shared ID

// Settings.java

boolean readLPw(@NonNull List<UserInfo> users) {
    FileInputStream str = null;

    // 如果有 packages-backup.xml的话取得backup IO流
    if (mBackupSettingsFilename.exists()) {
        try {
            str = new FileInputStream(mBackupSettingsFilename);
            ...
        } /* 省略 catch */
    }

    try {
        if (str == null) {
            ...

            // 没有 backup 就使用 packages.xml
            str = new FileInputStream(mSettingsFilename);
        }

        // 解析 xml
        final TypedXmlPullParser parser = Xml.resolvePullParser(str);
        int type;
        // 调整 xml 指标位置
        while ((type = parser.next()) != XmlPullParser.START_TAG
                && type != XmlPullParser.END_DOCUMENT) {
            ;
        }
        // 解析格式,判断 xml 格式是否正确
        if (type != XmlPullParser.START_TAG) {
            ... err log
            return false;
        }


        int outerDepth = parser.getDepth();
        // 开始分析 xml
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                continue;
            }

            // 解析节点名称
            String tagName = parser.getName();
            if (tagName.equals("package")) {
                // 读取上一次分配的 Linux UID
                // @ 分析 readPackageLPw
                readPackageLPw(parser, users);

            } else if (tagName.equals("permissions")) {
                mPermissions.readPermissions(parser);

            } else if (tagName.equals("permission-trees")) {
                mPermissions.readPermissionTrees(parser);

            } else if (tagName.equals("shared-user")) {
                // 读取上一次应用共享的 GID
                // @ 分析 readSharedUserLPw
                readSharedUserLPw(parser, users);

            } ... 省略部分 else if

            else {
                ... log

                XmlUtils.skipCurrentTag(parser);
            }
        }
        str.close();
    } /* 省略 catch、finally */ 

    ... 省略部分

    return true;
}

Setting - readPackageLPw 应用分配独立Linux ID

接下来我们主要关注“package”标签中的3元素

元素名功能补充
name应用包名必须要有 package 包名
userIdLinux上次为该应用分配的 独立UID
sharedUserId该应用 没有独立UID,与其它应用共享UID将该应用添加进 mPendingPackages 列表之后判断
// Setting.java

public static final String ATTR_NAME = "name";

private final WatchedArrayList<PackageSetting> mPendingPackages = new WatchedArrayList<>();

private void readPackageLPw(TypedXmlPullParser parser, List<UserInfo> users,
        ArrayMap<String, Long> originalFirstInstallTimes)
        throws XmlPullParserException, IOException {

    String name = null;
    int userId = 0;
    int sharedUserAppId = 0;

    try {
        // App package name
        name = parser.getAttributeValue(null, ATTR_NAME);

        ...

        userId = parser.getAttributeInt(null, "userId", 0);
        sharedUserAppId = parser.getAttributeInt(null, "sharedUserId", 0);

        // package name 是必须
        if (name == null) {
            PackageManagerService.reportSettingsProblem(Log.WARN,
                    "Error in package manager settings: <package> has no name at "
                            + parser.getPositionDescription());
        } else if (codePathStr == null) {
            ...

        } else if (userId > 0) {    // 已分配到独立 ID
            // @ 分析 addPackageLPw
            packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
                    legacyNativeLibraryPathStr, primaryCpuAbiString, secondaryCpuAbiString,
                    cpuAbiOverrideString, userId, versionCode, pkgFlags, pkgPrivateFlags,
                    null /* usesSdkLibraries */, null /* usesSdkLibraryVersions */,
                    null /* usesStaticLibraries */, null /* usesStaticLibraryVersions */,
                    null /* mimeGroups */, domainSetId);

            ... 省略部分

        } else if (sharedUserAppId != 0) {    // 未分配獨立 ID
            if (sharedUserAppId > 0) {

                // 保存该应用信息
                packageSetting = new PackageSetting(name.intern(), realName,
                        new File(codePathStr), legacyNativeLibraryPathStr,
                        primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
                        versionCode, pkgFlags, pkgPrivateFlags, sharedUserAppId,
                        null /* usesSdkLibraries */,
                        null /* usesSdkLibrariesVersions */,
                        null /* usesStaticLibraries */,
                        null /* usesStaticLibraryVersions */,
                        null /* mimeGroups */, domainSetId);
                ...

                // 添加到 `mPendingPackages` 列表
                mPendingPackages.add(packageSetting);
                ...
            } else {
                ...
            }
        } else {
            ...
        }
    } /* 省略 catch */
}

Setting#addPackageLPw 函数:在PKMS中 每个应用都是以 PackageSetting 对象存在,并将其储存在以 package name 为 Key 的 HashMap 中

// Setting.java

// 储存全部应用的信息
final WatchedArrayMap<String, PackageSetting> mPackages;

private final AppIdSettingMap mAppIds;

PackageSetting addPackageLPw(String name, String realName, File codePath,
        String legacyNativeLibraryPathString, String primaryCpuAbiString,
        String secondaryCpuAbiString, String cpuAbiOverrideString, int uid, 
        ... /* 省略部分 */) {

    // 以 name 来取得 PackageSetting
    PackageSetting p = mPackages.get(name);
    if (p != null) {
        // 判断 uid 
        if (p.getAppId() == uid) {
            // 相等代表已分配独立 UID
            return p;
        }
        PackageManagerService.reportSettingsProblem(Log.ERROR,
                "Adding duplicate package, keeping first: " + name);
        return null;
    }
    p = new PackageSetting(name, realName, codePath, legacyNativeLibraryPathString,
            primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, 
            ... /* 省略部分 */);

    // 设定 UID 给该 PackageSetting
    p.setAppId(uid);

    // 注册该 ID 至系统
    if (mAppIds.registerExistingAppId(uid, p, name)) {
        mPackages.put(name, p);
        return p;
    }
    return null;
}

AppIdSettingMap#registerExistingAppId函数:已分配的应用会从 mNonSystemSettings 取出null

// Process.java

public static final int FIRST_APPLICATION_UID = 10000;

// ------------------------------------------------------------
// AppIdSettingMap.java

private final WatchedArrayList<SettingBase> mNonSystemSettings;

public boolean registerExistingAppId(int appId, SettingBase setting, Object name) {

    // 大于 FIRST_APPLICATION_UID 代表是独立应用
    if (appId >= Process.FIRST_APPLICATION_UID) {
        int size = mNonSystemSettings.size();
        final int index = appId - Process.FIRST_APPLICATION_UID;
        // fill the array until our index becomes valid
        while (index >= size) {
            mNonSystemSettings.add(null);
            size++;
        }
        // 已分配会取出 null
        if (mNonSystemSettings.get(index) != null) {
            // 重复 UID
           
            ...err msg
            return false;
        }
        mNonSystemSettings.set(index, setting);
    } else {
        // 小于 FIRST_APPLICATION_UID 代表是共享应用
        ...
    }
    return true;
}

Setting - readPackageLPw 应用分配共享 Linux ID

接下来我们主要关注“shared-user”标签中的3元素

元素名功能补充
name用来描述一个共享 Linux 使用者的名称
userId用来描述一个共享 Linux 使用者的 ID
system描述该 ID 是系统型态、使用者型态
// Setting.java

private void readSharedUserLPw(TypedXmlPullParser parser, List<UserInfo> users)
        throws XmlPullParserException, IOException {
    String name = null;
    int pkgFlags = 0;
    int pkgPrivateFlags = 0;
    SharedUserSetting su = null;
    {
        name = parser.getAttributeValue(null, ATTR_NAME);    // "name"
        int userId = parser.getAttributeInt(null, "userId", 0);
        if (parser.getAttributeBoolean(null, "system", false)) {
            pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
        }
        
        if (name == null) {
            ...
        } else if (userId == 0) {
            ...
        } else {
            // @ 分析 addSharedUserLPw 函數
            if ((su = addSharedUserLPw(name.intern(), userId, pkgFlags, pkgPrivateFlags))
                    == null) 
                ...
            }
        }
    }

    ...
}

Setting#addSharedUserLPw 函数:使用 SharedUserSetting 来描述一个共享应用;比对ID确认没问题后,就可以加入 mSharedUsers 列表

// Setting.java

final WatchedArrayMap<String, SharedUserSetting> mSharedUsers 
            = new WatchedArrayMap<>();

SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
    SharedUserSetting s = mSharedUsers.get(name);
    if (s != null) {
        if (s.mAppId == uid) {
            return s;
        }
        ...err

        return null;
    }
    // 创建对应对象
    s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
    // 设定 ID
    s.mAppId = uid;
    
    // 尝试注册
    if (mAppIds.registerExistingAppId(uid, s, name)) {
        mSharedUsers.put(name, s);
        return s;
    }
    return null;
}

AppIdSettingMap#registerExistingAppId 函数:已分配的应用会从 mNonSystemSettings 取出null

// Process.java

public static final int FIRST_APPLICATION_UID = 10000;

// ------------------------------------------------------------
// AppIdSettingMap.java

private final WatchedArrayList<SettingBase> mNonSystemSettings;

public boolean registerExistingAppId(int appId, SettingBase setting, Object name) {

    // 大于 FIRST_APPLICATION_UID 代表是独立应用
    if (appId >= Process.FIRST_APPLICATION_UID) {
        ...
    } else {
        // 小于 FIRST_APPLICATION_UID 代表是共享应用
        if (mSystemSettings.get(appId) != null) {
            ...err

            return false;
        }
        mSystemSettings.put(appId, setting);
    }
    return true;
}

回到 Setting#readLPw 函数:经过上面分析 “shared-user”“package” 后可以得到共享、独立应用的相关讯息,接着就是要处理共享应用的ID

// Settings.java

private final AppIdSettingMap mAppIds;

boolean readLPw(@NonNull List<UserInfo> users) {

    ... 省略上面分析

    final int N = mPendingPackages.size();

    for (int i = 0; i < N; i++) {
        final PackageSetting p = mPendingPackages.get(i);
        final int sharedUserAppId = p.getSharedUserAppId();
        
        // 共享 ID 一定大于 0
        if (sharedUserAppId <= 0) {
            continue;
        }
        // 使用共享 ID,取得对应的安装物件
        final Object idObj = getSettingLPr(sharedUserAppId);
        if (idObj instanceof SharedUserSetting) {
            final SharedUserSetting sharedUser = (SharedUserSetting) idObj;
            // @ 查看 addPackageSettingLPw
            addPackageSettingLPw(p, sharedUser);
        } else if (idObj != null) {
            ...
        } else {
            ...
        }
    }
    mPendingPackages.clear();

    return true;
}


public SettingBase getSettingLPr(int appId) {
    return mAppIds.getSetting(appId);
}

void addPackageSettingLPw(PackageSetting p, SharedUserSetting sharedUser) {
    mPackages.put(p.getPackageName(), p);
    
    // 如果是共享应用还要再判断
    if (sharedUser != null) {
        SharedUserSetting existingSharedUserSetting = getSharedUserSettingLPr(p);

        if (existingSharedUserSetting != null && existingSharedUserSetting != sharedUser) {
            ...err msg

            sharedUser.removePackage(p);
        } else if (p.getAppId() != sharedUser.mAppId) {
            ...err msg

        }

        sharedUser.addPackage(p);
        p.setSharedUserAppId(sharedUser.mAppId);
        // 决定最终 ID
        p.setAppId(sharedUser.mAppId);
    }

    Object userIdPs = getSettingLPr(p.getAppId());
    if (sharedUser == null) {
        if (userIdPs != null && userIdPs != p) {
            mAppIds.replaceSetting(p.getAppId(), p);
        }
    } else {
        if (userIdPs != null && userIdPs != sharedUser) {
            mAppIds.replaceSetting(p.getAppId(), sharedUser);
        }
    }
}

第二阶段 - BOOT_PROGRESS_PMS_SYSTEM_SCAN_START

BOOT_PROGRESS_PMS_SYSTEM_SCAN_START:扫描系统阶段,其中目录包括(systemvendorproductodmoem …等等目录中的 priv-appappoverlay)并且该步骤 仍在两个锁内执行
scanDirTracedLI 方法:该方法扫描APK包,会针对传入的路径扫描内部的 APK 档案,之后会再针对 scanDirTracedLI 进行分析(先缓缓)

// PackageManagerService.java

// Key 是应用包名,Value 是应用包
final ArrayMap<String, PackageParser.Package> mPackages =
        new ArrayMap<String, PackageParser.Package>();

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
        final String buildFingerprint, final boolean isEngBuild,
        final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

    ... 省略第一阶段

    // CHECKSTYLE:OFF IndentationCheck
    synchronized (mInstallLock) {
    // writer
    synchronized (mLock) {

        ... 省略第一步骤

        // 纪录开始时间
        long startTime = SystemClock.uptimeMillis();
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
            startTime);

        // 从 init.rc 中获取环境变量 BOOTCLASSPATH、
        //                        SYSTEMSERVERCLASSPATH
        final String bootClassPath = 
            System.getenv("BOOTCLASSPATH");

        final String systemServerClassPath = 
            System.getenv("SYSTEMSERVERCLASSPATH");


        // 获取 /system/framework 目录
        File frameworkDir = new File(Environment.getRootDirectory(), "framework");

        // 获取内部版本
        final VersionInfo ver = mSettings.getInternalVersion();

        // 判断是否需要更新
        mIsUpgrade =
            !buildFingerprint.equals(ver.fingerprint);

        // Android M 升级上来的版本,须将系统应用权限从安装时申请,改为运行时申请
        mPromoteSystemApps =
            mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;

        // Android N升级上来的版本,需要像首次启动一样处理包提取,因为没有可用的分析数据
        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;

        ... 省略部分

        // 准备解析 package 的缓存
        mCacheDir = preparePackageParserCache(mIsEngBuild);

        // 设定 flag,当扫描安装文件夹时不改变 apk 路径
        int scanFlags = SCAN_BOOTING | SCAN_INITIAL;

        // 收集 vendor/product/system_ext overlay packages.
        for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
            final ScanPartition partition = mDirsToScanAsSystem.get(i);
            if (partition.getOverlayFolder() == null) {
                continue;
            }
            // 扫描 overlay… 等等文件夹内的 apk
            scanDirTracedLI(partition.getOverlayFolder(), systemParseFlags,
                    systemScanFlags | partition.scanFlag, 0,
                    packageParser, executorService);
        }

        // 扫描 framework 文件夹内的 apk
        scanDirTracedLI(frameworkDir, systemParseFlags,
            systemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0,
            packageParser, executorService);

        // 判断安装包是否是 android
        if (!mPackages.containsKey("android")) {
            throw new IllegalStateException(
                    "Failed to load frameworks package; check log for warnings");
        }

        for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) {
            final ScanPartition partition = mDirsToScanAsSystem.get(i);
            if (partition.getPrivAppFolder() != null) {
                // 扫描 priv-app 文件夹
                scanDirTracedLI(partition.getPrivAppFolder(), systemParseFlags,
                        systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0,
                        packageParser, executorService);
            }
            // 扫描 /system/app 文件夹
            // @ 查看 scanDirTracedLI
            scanDirTracedLI(partition.getAppFolder(), systemParseFlags,
                    systemScanFlags | partition.scanFlag, 0,
                    packageParser, executorService);
        }

        ... 省略部分

        if (!mOnlyCore) {
            // do this first before mucking with mPackages for the "expecting better" case
            final int numPackages = mPackages.size();
            for (int index = 0; index < numPackages; index++) {
                final AndroidPackage pkg = mPackages.valueAt(index);
                if (pkg.isStub()) {
                    stubSystemApps.add(pkg.getPackageName());
                }
            }

            // 倒序扫描所有应用
            for (int index = packageSettings.size() - 1; index >= 0; index--) {
                final PackageSetting ps = packageSettings.valueAt(index);

                // 如果包有 FLAG_SYSTEM 則忽略
                if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                    continue;
                }
                /*
                 * If the package is scanned, it's not erased.
                 */
                final AndroidPackage scannedPkg = mPackages.get(ps.name);
                if (scannedPkg != null) {
                    //若在disabled packages list,添加进
                    // via OTA,再将其移除
                    if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
                        ...
                        //将系统 App 的 PackageSetting 从 PKMS 中 mPackage 移除
                        removePackageLI(scannedPkg, true);

                        // 将升级包的路径添加到 mExpectingBetter 列表中
                        mExpectingBetter.put(ps.name, ps.getPath());
                    }
                    continue;
                }

                if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
                    logCriticalInfo(Log.WARN, "System package " + ps.name
                            + " no longer exists; it's data will be wiped");
                    // 系统 APP 将不存在,移除该 APP 的数据
                    removePackageDataLIF(ps, userIds, null, 0, false);
                } 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.getPath() == null || !disabledPs.getPath().exists()
                            || disabledPs.pkg == null) {
                        // 该系统 APP 在 isDisabledSystemPackage 中,并且没有发现升级包
                        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.getPath());
                    }
                }
            }
        }

        ... 省略部分

    }

    }

}

扫描升级系统APP - system文件夹

目前阶段(BOOT_PROGRESS_PMS_SYSTEM_SCAN_START)主要是扫描 /system 文件夹:这个目录下文件夹都如何规划放置
Android 系统架构有分为应用层、应用框架层、系统运行层、硬件抽象层、内核层

system 内文件夹放置内容补充
app系统 app包括 google 内置、手机厂商 app
framework应用框架 jar 包主要放 jar 包、vdex
priv-app特权 app
lib放置动态 so 文件
fonts系统字体多是 ttf 档
media系统音效像是铃声、提示音、系统启动动画

第二个目的是扫描系统文件并处理,处理的 重点是 ^^OTA 升级^^系统会将可升级的系统应用标记为DisabledSystemPackage,并且有3种状况
系统APP有更新:透过 removePackageLI 将系统 App 的 PackageSetting 从 PKMS 中 mPackage 移除,并 添加到 mExpectingBetter 列表
系统APP被移除:透过 removePackageDataLIF 移除系统APP数据 没有升级包:系统应用为 DisabledSystemPackage,但没有发现升级包,代表代表系统升级包 可能 被删除

第三阶段- BOOT_PROGRESS_PMS_DATA_SCAN_START

BOOT_PROGRESS_PMS_DATA_SCAN_START:主要会 扫描 /data 文件夹
扫描处理、更新 /data 目录的应用信息(也会及时移除不需要的数据)
处理上一步遗留的 possiblyDeletedUpdatedSystemApps 列表
如果无法从 mPackage 中取得 Package 则会删除该 APP
如果可以取得 Package 但不是系统 APP,并且会做以下这些事情
移除 System 权限
移除 Package
重新扫描 Package 路径的 APK
扫描 mExpectingBetter 列表
取得系统 APP 升级包的路径,并且会做以下这些事情
根据系统 APP 所在的目录设定扫描的解析参数
将 PackageName 设定给mSetting#mPackages中(removeDisabledSystemPackageLPw 方法)
清除 mExpectingBetter 列表

// PackageManagerService.java

    private final File mAppInstallDir;

    public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
            final String buildFingerprint, final boolean isEngBuild,
            final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

        ... 省略第一阶段
       
        // 取得 /data/app 资料夾
        mAppInstallDir = new File(Environment.getDataDirectory(), "app");
        
         // CHECKSTYLE:OFF IndentationCheck
        synchronized (mInstallLock) {
        // writer
        synchronized (mLock) {
            
            ... 省略第一、二阶段
                
            if (!mOnlyCore) {
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                        SystemClock.uptimeMillis());
                
                // 1. 扫描 /data/app文件夹
                scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0,
                        packageParser, executorService);
            }
            
            // 关闭 Parser 流(解析 Package xml 的流)
            packageParser.close();
            
            // 关闭 Executor 的全部任务
            List<Runnable> unfinishedTasks = executorService.shutdownNow();
            if (!unfinishedTasks.isEmpty()) {
                throw new IllegalStateException("Not all tasks finished before calling close: "
                        + unfinishedTasks);
            }
            
            
            if (!mOnlyCore) {    // 非核心模式
                // 2. 扫描上一步所遗留的 APP 包(倒序)

                for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) {
                    final String packageName = possiblyDeletedUpdatedSystemApps.get(i);
                    final AndroidPackage pkg = mPackages.get(packageName);
                    final String msg;
                    
                    // 从禁用系统列表(mDisabledSystemPackage)中移除
                    mSettings.removeDisabledSystemPackageLPw(packageName);
                    
                    if (pkg == null) {
                        // 应该要找到升级包,但没找到~(移除该APP)
                        msg = "Updated system package " + packageName
                                + " no longer exists; removing its data";
                        // (实际上并非马上移除)
                    } else {
                        
                        // 如果有取到pkg,代表该APP存在Data区中,
                        // 不属于System app,移除系统权限
                        msg = "Updated system package " + packageName
                                + " no longer exists; rescanning package on data";
                        // 以下,删除并重新扫描数据包
                        removePackageLI(pkg, true);    // 删除
                        try {
                            final File codePath = new File(pkg.getPath());
                            // 重新扫描
                            scanPackageTracedLI(codePath, 0, scanFlags, 0, null);
                        } catch (PackageManagerException e) {
                            Slog.e(TAG, "Failed to parse updated, ex-system package: "
                                    + e.getMessage());
                        }
                    }
                    //最后一次检查!
                    //如果我们还有一个包设置[ie.它是以前扫描并为系统所知]
                    //但是,我们没有该Pkg [即。从/data扫描它时出错
                    // partition],彻底删除包数据。
                    final PackageSetting ps = mSettings.getPackageLPr(packageName);
                    if (ps != null && mPackages.get(packageName) == null) {
                        // 移除 data 内出错的数据包
                        removePackageDataLIF(ps, userIds, null, 0, false);
                    }
                    logCriticalInfo(Log.WARN, msg);

                }

                // 3. 遍历 mExpectingBetter 列表
                for (int i = 0; i < mExpectingBetter.size(); i++) {
                    final String packageName = mExpectingBetter.keyAt(i);
                    if (!mPackages.containsKey(packageName)) {
                        // 取得系统 APP 升级包的路径
                        final File scanFile = mExpectingBetter.valueAt(i);

                        for (int i1 = mDirsToScanAsSystem.size() - 1; i1 >= 0; i1--) {
                            final ScanPartition partition = mDirsToScanAsSystem.get(i1);
                            // 根据系统 APP 所在的目录设定扫描的解析参数
                            if (partition.containsPrivApp(scanFile)) {
                                reparseFlags = systemParseFlags;
                                // 设定扫描参数
                                rescanFlags = systemScanFlags | SCAN_AS_PRIVILEGED
                                        | partition.scanFlag;
                                break;
                            }
                            if (partition.containsApp(scanFile)) {
                                reparseFlags = systemParseFlags;
                                rescanFlags = systemScanFlags | partition.scanFlag;
                                break;
                            }
                        }
                        if (rescanFlags == 0) {
                            Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                            continue;
                        }

                        //将PackageName对应的包设置数据(PackagesSetting)
                        //添加到mSetting的mPackages中
                        mSettings.enableSystemPackageLPw(packageName);

                        try {
                            // 扫描系统 APP 的升级包
                            final AndroidPackage newPkg = scanPackageTracedLI(
                                    scanFile, reparseFlags, rescanFlags, 0, null);
                            // We rescanned a stub, add it to the list of stubbed system packages
                            if (newPkg.isStub()) {
                                stubSystemApps.add(packageName);
                            }
                        } /* 省略 catch */
                    }
                }

                //解压&安装根系统应用
                //该操做要确保最后执行,来确保所有存根被替代or禁用
                // Stub(存根)
                installSystemStubPackages(stubSystemApps, scanFlags);

                ... 省略部分
            }
            
            
            // 清除升级列表
            mExpectingBetter.clear();
            
            // 取得 Storage manage 包名
            mStorageManagerPackage = getStorageManagerPackageName();
            
            // 解决保护 action 过滤器,只允许 setup wizard 为这些 action 有最高权限的过滤
            mSetupWizardPackage = getSetupWizardPackageNameImpl();
            
            ... 省略部分
            
            // 读取并更新要保留的 package 的上次使用时间
            mPackageUsage.read(packageSettings);
            mCompilerStats.read();

        }
    }

scanDirTracedLI - 分析 data 目录內容

/data 文件夹可成为 Data 分区,它个主用公用有两个
储存所有用户的 个人数据
储存所有用户的 配置文件
接着来看 /data 目录下的子目录都放那些数据

/data 底下目录含意
app储存该收机装置,自己安装的APP应用
data储存所有已安装的APP数据,其中也包括System APP数据
app-privateAPP 的私有儲存空間
app-lib储存所有APP的JNI Lib
system存放系统配置文件
anr用于存放ANR发生时,系统生成的 traces.text 文件

第四階段 - BOOT_PROGRESS_PMS_SCAN_END

BOOT_PROGRESS_PMS_SCAN_END阶段:OAT 升级后首次启动,要清除不必要的缓存数据、权限,更新 package.xml 档案 (packages.xml 用来储存所有 APP 的信息)
SDK 版本更变,重新更新权限
OTA 升级后首次启动,清除不要要缓存
OTA 英文全称是 Over-the-Air Technology ,即空间下载技术,是手机通过行动网络对手机系统,应用程序进行管理的技术
权限更新完成后清理相关数据
透过 mSetting 的内容保存并更新 package.xml 文件,这样以后 PKMS 创建时就会读取到新的 Setting

// PackageManagerService.java

    public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
            final String buildFingerprint, final boolean isEngBuild,
            final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

        ... 省略第一阶段

         // CHECKSTYLE:OFF IndentationCheck
        synchronized (mInstallLock) {
        // writer
        synchronized (mLock) {
            
            ... 省略第一、二、三阶段

            // 进入第四阶段
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                    SystemClock.uptimeMillis());

            // 权限重制
            mPermissionManager.onStorageVolumeMounted(
                    StorageManager.UUID_PRIVATE_INTERNAL, mIsUpgrade);
            ver.sdkVersion = mSdkVersion;

            // 如果是第一次启动或从pre-M升级上来,并且是正常启动,那我们需要初始化User定义的首选预设应用
            if (!mOnlyCore && (mPromoteSystemApps || mFirstBoot)) {
                for (UserInfo user : mInjector.getUserManagerInternal().getUsers(true)) {
                    mSettings.applyDefaultPreferredAppsLPw(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;
            }
            
            ... 省略部分
            
            // 在 OTA 升级成功后的首次启动,不必要的缓存,但不清除应用程序的配置文件
            if (mIsUpgrade && !mOnlyCore) {
                Slog.i(TAG, "Build fingerprint changed; clearing code caches");
                for (int i = 0; i < packageSettings.size(); i++) {
                    final PackageSetting ps = packageSettings.valueAt(i);
                    if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
                        // 没有应用会在这时启动,所以不必冻结
                        clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
                                FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
                                        | Installer.FLAG_CLEAR_CODE_CACHE_ONLY
                                        | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
                    }
                }
                ver.fingerprint = Build.FINGERPRINT;
            }
            
            // 在Launcher中隐藏他们的icon(Android-Q之前的非系统应用)
            if (!mOnlyCore && mIsPreQUpgrade) {
                Slog.i(TAG, "Whitelisting all existing apps to hide their icons");
                int size = packageSettings.size();
                for (int i = 0; i < size; i++) {
                    final PackageSetting ps = packageSettings.valueAt(i);
                    if ((ps.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
            mPromoteSystemApps = false;
            
            // 所有的改变都在扫描中完成
            ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;
            
            // 更新 package.xml 档案
            t.traceBegin("write settings");
            writeSettingsLPrTEMP();
            t.traceEnd();

            ... 省略部分

        }
            
        }
    }

第五阶段 - BOOT_PROGRESS_PMS_READY

BOOT_PROGRESS_PMS_READY:PKMS 最后阶段
PackageInstallerService 用于管理安装 Session 服务,每次安装过程都会分配一个 SessionId
要求触发 GC 回收内存

// PackageManagerService.java
    public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
            final String buildFingerprint, final boolean isEngBuild,
            final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

        ... 省略第一步骤
        
         // CHECKSTYLE:OFF IndentationCheck
        synchronized (mInstallLock) {
        // writer
        synchronized (mLock) {
            
            ... 省略第一、二、三、四步骤
            
            
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                    SystemClock.uptimeMillis());
            
            ... 省略部分
            
            // PermissionController 是一个系统核心,预设同意&管理权限
            mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr();
            
            ... 省略部分
            
            // 取得安装器服务
            mInstallerService = mInjector.getPackageInstallerService();
            
            ... 省略部分
            
            //读取&更新dex档案的用法
            //在PM init结束时执行这个操作,以便所有包都协调其数据目录
            //建构可以验证的文件并建构内存缓存
            //使用文件预计很小,因此与其它活动相比,加载&验证它都满花费时间的
            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) {
                FrameworkStatsLog.write(
                        FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,
                        BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME,
                        SystemClock.uptimeMillis() - startTime);
            }

            // 属性被重构后,重构 live computer
            mLiveComputer = createLiveComputer();

        }
            
        }
        
        ... 省略部分
        
        // 在打开应用 zip 后,确保他们都刷新,并进行 GC 回收
        VMRuntime.getRuntime().requestConcurrentGC();
        
        mInstaller.setWarnIfHeld(mLock);
        
        ... 省略部分
    }