PMS 创建之“软件包管理超级工厂”的建设

把这个复杂的 PMS 创建过程想象成一个 Android 世界里的"软件包管理超级工厂"的建设故事,结合代码一步步来揭秘。

​故事背景:​

Android 世界要运转起来,需要成千上万的服务(工人)。其中最重要的一批,叫"系统服务",它们由一位叫 SystemServer 的大管家负责招募和组织。PackageManagerService (PMS) 就是这位大管家招募的关键"工厂厂长",它的职责是管理整个 Android 世界里所有 App(软件包)的安装、卸载、信息查询、权限分配等等,相当于一个超级 App 仓库管理员兼质量检查员兼权限发放员。

​第一章:大管家 SystemServer 的筹备工作 (SystemServer 处理部分)​

  1. ​大管家登场 (SystemServer.main()):​

    typescript 复制代码
    java
    Copy
    public static void main(String[] args) {
        new SystemServer().run(); // 大管家启动,开始干活!
    }

    故事:Android 系统内核启动后,把接力棒交给了 SystemServermain 方法是大管家启动的入口,它二话不说就调用了自己的 run() 方法。

  2. ​搭建基础 (SystemServer.run()):​

    scss 复制代码
    java
    Copy
    private void run() {
        try {
            Looper.prepareMainLooper(); // 1. 建立消息传递系统(比如工厂内部电话网)
            System.loadLibrary("android_servers"); // 2. 加载关键工具库(基础施工设备进场)
            ... // (其他初始化,如关机处理)
            createSystemContext(); // 3. 创建系统全局上下文环境(给工厂画个规划图)
            mSystemServiceManager = new SystemServiceManager(mSystemContext); // 4. 创建服务经理(招个HR主管)
            ... // (把HR主管登记在册)
        } finally { ... }
        try {
            traceBeginAndSlog("StartServices");
            startBootstrapServices(); // 5. 启动"奠基性"服务(招核心骨干厂长)
            startCoreServices();       // 6. 启动"核心"服务(招重要部门主管)
            startOtherServices();      // 7. 启动"其他"服务(招普通工人)
        } catch (Throwable ex) { ... }
    }

    故事:

    • ​(1-4)​ ​ 大管家 SystemServer 首先要给自己搭好办公环境:建立消息循环系统(Looper)保证内部指令能传达;加载 libandroid_servers.so 这个包含了很多基础工具的库;创建全局的上下文 Context(可以理解为工厂的规划蓝图和基础资源);最重要的是创建 SystemServiceManager (SSM) ------ 相当于人力资源部主管,专门负责招募、启动和管理所有系统服务(厂长们)。

    • ​(5-7)​​ 环境搭好后,大管家开始分批次招募服务:

      • startBootstrapServices(): 招募​奠基性服务​ 。这些服务是系统最底层、最关键的,其他很多服务都依赖它们才能工作。就像工厂需要先有厂长(AMS)、电力主管(PowerManagerService)、原材料仓库主管(PMS)等核心人物,工厂才能开始运转。​PMS 就在这里被招募!​
      • startCoreServices(): 招募​核心服务​。这些服务也很重要,支撑着系统的基础功能,比如日志管理(DropBoxManagerService)、电池管理(BatteryService)等。相当于工厂的质检部、能源监控部。
      • startOtherServices(): 招募​其他服务​。这些服务功能相对独立或启动不那么紧急,比如摄像头管理(CameraService)、闹钟服务(AlarmManagerService)等。相当于工厂的食堂、运输队等。
  3. ​招募 PMS 厂长 (startBootstrapServices()):​

    csharp 复制代码
    java
    Copy
    private void startBootstrapServices() {
        ... // (检查设备加密状态,可能影响后续操作)
        traceBeginAndSlog("StartPackageManagerService");
        // 调用 PMS 的 main 方法!相当于给 PMS 厂长打电话:"快来建厂吧!"
        mPackageManagerService = PackageManagerService.main(
                mSystemContext, // 系统蓝图和环境
                installer,      // 施工队队长(Installer, 负责具体安装卸载操作)
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, // 是否在测试模式
                mOnlyCore       // 是否只处理核心App(比如加密设备刚启动时)
        );
        mFirstBoot = mPackageManagerService.isFirstBoot(); // 记录是不是第一次开机
        ... // (其他操作)
    }

    故事:在招募奠基性服务的环节,大管家 SystemServer 决定创建 PMS 工厂。它没有直接用 new 来建,而是调用了 PMS 类自己的 main() 方法。这相当于给 PMS 厂长打了个电话:"喂,PMS 吗?现在给你建厂授权(mSystemContext),给你配个施工队队长(installer),告诉你现在的模式(测试/正式、核心/全功能),你赶紧来把工厂建起来吧!"

  4. ​PMS 厂长报到建厂 (PackageManagerService.main()):​

    java 复制代码
    java
    Copy
    public static PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        ... // (检查编译配置)
        // 真正开始建设 PMS 工厂!
        PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore);
        ... // (设置多用户支持)
        // 向 ServiceManager 注册自己:"工厂建好了,以后找我就打这个电话(service name "package")"
        ServiceManager.addService("package", m);
        return m; // 把建好的工厂报告给 SystemServer 大管家
    }

    故事:PMS 厂长接到电话后,立刻行动。main() 方法做了两件大事:

    • ​建造工厂本体:​ 调用 PMS 的​构造函数​ new PackageManagerService(...)。这是最复杂、最耗时的部分,相当于把工厂的地基、厂房、仓库、质检线、管理系统都建好配置好。我们下一章重点讲这个。
    • ​开张营业:​ 工厂建好后,厂长立刻去 ServiceManager(可以理解为一个全球服务黄页)那里登记:"大家好,我是软件包管理服务,我叫 package,以后谁需要安装、卸载、查询 App,就打这个服务名找我!"。这样,其他系统服务(如 AMS)或 App 就能通过 ServiceManager.getService("package") 找到 PMS 来办事了。

​第二章:PMS 超级工厂的建设 (PMS 构造方法)​

PMS 的构造方法非常庞大(600+行),可以清晰地分为 5 个主要建设阶段,每个阶段开工时都会在工程日志(EventLog)上记一笔:

  1. ​阶段一:奠基与规划 (BOOT_PROGRESS_PMS_START)​

    scss 复制代码
    java
    Copy
    public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
        ... // (安装锁、Trace等)
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, SystemClock.uptimeMillis());
        // 1. 准备基础工具和蓝图库
        mMetrics = new DisplayMetrics(); // 屏幕规格信息(包装箱尺寸标准)
        mSettings = new Settings(mPackages); // 核心数据库!存储所有App的安装设置、权限、状态等。相当于工厂的中央档案库。
        // 初始化档案库:预置几个核心"共享用户ID"组 (如 android.uid.system)
        mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID, ...);
        mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ...);
        ... // (其他共享组)
        mInstaller = installer; // 施工队队长 (负责调用底层 installd)
        mPackageDexOptimizer = ... // Dex优化工具(打包优化机)
        mDexManager = ... // Dex管理器
        ... // (其他管理器:文件移动回调、权限监听)
        getDefaultDisplayMetrics(context, mMetrics); // 获取屏幕信息
        // 2. 加载系统全局配置 (SystemConfig)
        SystemConfig systemConfig = SystemConfig.getInstance();
        mGlobalGids = systemConfig.getGlobalGids(); // 全局用户组ID列表
        mSystemPermissions = systemConfig.getSystemPermissions(); // 系统定义的权限列表(所有App能申请哪些权限的基础)
        mAvailableFeatures = systemConfig.getAvailableFeatures(); // 系统支持的功能特性列表
        mProtectedPackages = new ProtectedPackages(mContext); // 受保护应用名单(VIP仓库区)
        // 3. 建立核心工作区和通信机制
        synchronized (mInstallLock) { ... } // 安装操作专用锁(仓库装卸区门禁)
        synchronized (mPackages) { ... }    // 内存数据结构锁(中央档案库门禁)
        mHandlerThread = new ServiceThread(...); // 创建后台工作线程(物流调度中心)
        mHandlerThread.start();
        mHandler = new PackageHandler(mHandlerThread.getLooper()); // PMS主处理器(物流调度主管),绑定到物流中心
        Watchdog.getInstance().addThread(mHandler, ...); // 调度主管纳入系统"看门狗"监控(防止死锁)
        ... // (权限策略、Instant App管理)
        // 4. 规划Data分区仓库布局
        File dataDir = Environment.getDataDirectory();
        mAppInstallDir = new File(dataDir, "app");         // 用户App主仓库 (/data/app)
        mAppLib32InstallDir = new File(dataDir, "app-lib"); // 32位库仓库
        mAsecInternalPath = new File(dataDir, "app-asec").getPath(); // 加密App仓库路径
        mDrmAppPrivateInstallDir = new File(dataDir, "app-private"); // DRM保护App仓库
        // 5. 启动多用户管理系统 (UserManagerService)
        sUserManager = new UserManagerService(..., this, ...);
        // 6. 读取上次建厂存档 (packages.xml, packages.list)
        mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false)); // 读档成功就不是第一次开机
        ... // (如果读档失败或第一次,mFirstBoot=true)
    }

    ​故事:​ ​ PMS 厂长拿着蓝图(context)和施工队长(installer)来到工地。

    • ​立档案库 (mSettings):​ 建一个核心的中央档案库 Settings,预先把几个最重要的"工作组"(SharedUserId,如 android.uid.system)登记进去。这些组里的 App 可以共享数据和进程。
    • ​配工具和标准:​ 确定屏幕标准 (mMetrics),领取官方颁发的权限清单、功能特性清单、受保护应用名单 (SystemConfig)。
    • ​建物流体系:​ 划分两个关键工作区(安装锁 mInstallLock 保护对施工队 installd 的访问;包信息锁 mPackages 保护内存中的 App 信息)。创建后勤物流中心 (ServiceThread) 和物流主管 (PackageHandler),主管被系统"看门狗"盯着,防止卡车堵死(死锁)。
    • ​划仓库用地:​/data 分区规划好普通 App 仓库 (/data/app)、32位库仓库、加密 App 仓库、DRM App 仓库的位置。
    • ​招用户管理员 (UserManagerService):​ Android 支持多用户,每个用户的 App 安装可能不同,需要专人管理。
    • ​查历史档案:​ 尝试读取上次工厂关闭时保存的档案 (packages.xml, packages.list)。如果成功读到,说明不是第一次开机 (mFirstBoot=false),档案里记录了所有已安装 App 的信息、权限授予状态等。如果读不到或文件损坏,那就是第一次开机 (mFirstBoot=true),档案库是空的。
  2. ​阶段二:扫描系统仓库 (BOOT_PROGRESS_PMS_SYSTEM_SCAN_START)​

    scss 复制代码
    java
    Copy
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START, startTime);
    // 扫描关键系统目录 (相当于扫描预制在手机/system分区里的App)
    File frameworkDir = new File(Environment.getRootDirectory(), "framework"); // /system/framework (系统核心组件)
    scanDirTracedLI(frameworkDir, PARSE_IS_SYSTEM | ..., ...);
    File privilegedAppDir = new File(..., "priv-app"); // /system/priv-app (高权限系统App)
    scanDirTracedLI(privilegedAppDir, PARSE_IS_SYSTEM | PARSE_IS_PRIVILEGED, ...);
    File systemAppDir = new File(..., "app"); // /system/app (普通系统App)
    scanDirTracedLI(systemAppDir, PARSE_IS_SYSTEM, ...);
    File vendorAppDir = new File("/vendor/app"); // /vendor/app (厂商提供的App)
    scanDirTracedLI(vendorAppDir, PARSE_IS_SYSTEM, ...);
    File oemAppDir = new File(..., "app"); // /oem/app (OEM合作伙伴App)
    scanDirTracedLI(oemAppDir, PARSE_IS_SYSTEM, ...);
    // 处理可能的OTA升级残留问题
    List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
    if (!mOnlyCore) { // 如果不是精简模式(加密设备刚启动)
        // 遍历中央档案库(mSettings)里标记为系统App的记录
        for (PackageSetting ps : mSettings.mPackages.values()) {
            if (不是系统App) continue;
            // 看看在刚扫描的/system分区里有没有找到这个App的安装文件?
            PackageParser.Package scannedPkg = mPackages.get(ps.name);
            if (scannedPkg != null) {
                if (档案库标记这个系统App被更新过且禁用) {
                    // 场景1:系统App有更新版存在 -> 移除旧版档案,期待在Data分区找到更新版
                    removePackageLI(scannedPkg, true);
                    mExpectingBetter.put(ps.name, ps.codePath); // 期待在Data仓库找到新版
                }
            } else {
                if (档案库标记这个系统App没被禁用) {
                    ... // 处理异常
                } else {
                    // 场景2:档案库标记有旧版系统App更新包,但扫描没找到文件 -> 可能是OTA后被删除了?
                    possiblyDeletedUpdatedSystemApps.add(ps.name); // 记下来,等扫描Data仓库后再处理
                }
            }
        }
    }

    ​故事:​ ​ 工厂奠基完成,厂长带着质检员 (scanDirTracedLI) 去扫描手机出厂时预装好 App 的系统分区 (/system, /vendor, /oem) 里的几个关键仓库:

    • /system/framework: 系统核心组件库。

    • /system/priv-app: 拥有高权限的系统 App (如设置、电话)。

    • /system/app: 普通系统 App。

    • /vendor/app: 芯片厂商或手机厂商提供的 App。

    • /oem/app: 运营商或合作伙伴预装的 App。

      ​质检员 (scanDirTracedLI) 的工作:​

      • 进入目录。
      • 对每个 .apk 文件进行"解析"(PackageParser)。
      • 提取 App 的名称、版本、权限声明、组件信息等。
      • 将这些信息封装成 Package 对象。
      • Package 对象放入 PMS 的内存仓库 (mPackages)。
      • 在中央档案库 (mSettings) 做相应记录。
        ​处理系统 App 的 OTA 问题:​ 上次系统升级后,有些系统 App 可能更新了,有些可能被删了。质检员在扫描系统分区时发现:
    • ​场景1 (找到文件且有更新标记):​ ​ 在系统分区找到了这个 App,但档案库显示它已被更新(更新包应该在 /data)。工厂决定:​​移除​ ​当前在系统分区找到的这个旧版本的信息(removePackageLI),并​​期待​ ​稍后在 /data 分区(用户仓库)能找到它的更新版(记录到 mExpectingBetter)。

    • ​场景2 (文件消失且有旧更新包标记):​ ​ 档案库里记录着这个系统 App 有一个旧版的更新包存在,但这次在系统分区​​没扫描到​ ​这个更新包文件!质检员怀疑这个更新包是不是在 OTA 后被删除了?先记下来 (possiblyDeletedUpdatedSystemApps),​​等扫描完用户仓库 (/data) 后再确认处理。​

  3. ​阶段三:扫描用户仓库 (BOOT_PROGRESS_PMS_DATA_SCAN_START)​

    scss 复制代码
    java
    Copy
    if (!mOnlyCore) { // 如果不是精简模式
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START, ...);
        // 扫描用户安装的App仓库 (/data/app, /data/app-private)
        scanDirTracedLI(mAppInstallDir, 0, ...); // /data/app
        scanDirTracedLI(mDrmAppPrivateInstallDir, ..., ...); // /data/app-private
        // 处理阶段二遗留的"可能被删除的更新包"
        for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
            // 在用户仓库(/data)扫描后,内存仓库(mPackages)里有没有这个App?
            PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
            if (deletedPkg == null) {
                // 没找到!确认是OTA后残留 -> 从档案库彻底删除记录(后续会清理数据)
                mSettings.removeDisabledSystemPackageLPw(deletedAppName);
                Log.w("Updated system package " + deletedAppName + " no longer exists; ...");
            } else {
                // 找到了!但它不应该再享有系统App特权(因为原系统文件没了)
                Log.w("Updated system app " + deletedAppName + " no longer present; removing system privileges");
                deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM; // 剥夺系统标志
                ... // 在档案库也移除系统标志
            }
        }
        // 处理阶段二记录的"期待找到的更新包" (mExpectingBetter)
        for (String packageName : mExpectingBetter.keySet()) {
            if (!mPackages.containsKey(packageName)) { // 在用户仓库没找到期待的更新包!
                Log.w("Expected better " + packageName + " but never showed up; reverting to system");
                File scanFile = mExpectingBetter.get(packageName);
                // 根据原系统文件位置,重新按系统App解析它(使用对应的特权标志)
                int reparseFlags = ... | (如果在priv-app目录? PARSE_IS_PRIVILEGED : 0);
                // 在档案库重新启用这个系统App的原始记录
                mSettings.enableSystemPackageLPw(packageName);
                // 重新扫描解析这个原始系统App文件
                scanPackageTracedLI(scanFile, reparseFlags, ...);
            }
        }
        mExpectingBetter.clear(); // 处理完毕,清空期待列表
    }

    ​故事:​ ​ 扫描完工厂自带的系统仓库,质检员们转向用户自己安装 App 的仓库 /data/app 和存放受保护 App 的 /data/app-private。流程和扫描系统仓库类似:解析 .apk,生成 Package 对象,放入 mPackages,更新 mSettings

    ​处理遗留问题:​

    • ​处理"可能被删除的更新包" (possiblyDeletedUpdatedSystemApps):​

      • ​在 /data 也没找到 (deletedPkg == null):​ 确认这个更新包被 OTA ​删除了​ !厂长下令从中央档案库 (mSettings) 里彻底清除关于这个旧更新包的记录。后续会清理它的残留数据。
      • ​在 /data 找到了 (deletedPkg != null):​ 这个 App 还在,但它​失去了作为系统 App 的资格​ (因为它的基础系统文件在阶段二扫描时没找到)。厂长下令:剥夺它的 FLAG_SYSTEM 标志(不再是系统 App),在档案库里也做相应修改。
    • ​处理"期待找到的更新包" (mExpectingBetter):​

      • ​在 /data 没找到期待的更新包 (!mPackages.containsKey):​ ​ 厂长很失望!期待中的更新包没出现。只能​​回退到使用原始的系统 App 版本​​。厂长下令:

        1. 根据这个系统 App 原始文件 (scanFile) 所在目录 (是 /system/priv-app 还是 /system/app),决定重新解析它时应该带哪些特权标志 (reparseFlags)。
        2. 在档案库 (mSettings) 里​重新启用​这个原始系统 App 的记录。
        3. ​重新扫描解析 (scanPackageTracedLI)​ 这个原始系统 App 文件,把它当作有效的系统 App 加回来。
      • (如果在 /data 找到了,那阶段二移除旧版+这里扫描到新版的流程就完成了,一切正常)

    • 清空 mExpectingBetter 列表。

  4. ​阶段四:收尾整理与权限更新 (BOOT_PROGRESS_PMS_SCAN_END)​

    scss 复制代码
    java
    Copy
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END, ...);
    Log.i("Time to scan packages: " + (timeTaken) + " seconds");
    int updateFlags = UPDATE_PERMISSIONS_ALL;
    // 检查Android版本是否升级
    if (上次记录的SDK版本 != 当前SDK版本) {
        Log.i("Platform changed; regranting permissions ...");
        updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL; // 需要全面更新权限
    }
    // 根据情况更新所有App的权限授予状态
    updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
    // 更新档案库记录的SDK版本
    ver.sdkVersion = mSdkVersion;
    // 如果是第一次启动或特定升级后,初始化默认App设置
    if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
        for (UserInfo user : 所有用户) {
            mSettings.applyDefaultPreferredAppsLPw(this, user.id); // 设置默认浏览器/拨号App等
            ... // (其他初始化)
        }
    }
    // 如果是OTA升级后首次启动,清除所有App的代码缓存
    if (mIsUpgrade && !onlyCore) {
        Log.i("Build fingerprint changed; clearing code caches");
        for (PackageSetting ps : mSettings.mPackages.values()) {
            clearAppDataLIF(ps.pkg, ..., Installer.FLAG_CLEAR_CODE_CACHE_ONLY); // 只清代码缓存
        }
    }
    // 更新档案库记录的设备指纹
    ver.fingerprint = Build.FINGERPRINT;
    // 将内存中的档案库内容(mSettings) 写回磁盘文件 (packages.xml, packages.list) 存档!
    mSettings.writeLPr();

    ​故事:​​ 所有仓库扫描完毕!

    • ​记录耗时,宣布扫描结束 (BOOT_PROGRESS_PMS_SCAN_END)。​

    • ​处理 Android 版本升级 (if (ver.sdkVersion != mSdkVersion)):​

      • 如果发现这次开机的 Android 版本 (mSdkVersion) 和上次记录在档案库里的版本 (ver.sdkVersion) 不同,说明系统升级了。
      • 系统升级可能带来权限定义的改变。厂长下令:​全面检查并更新 (updatePermissionsLPw)​ 所有已安装 App 的权限授予状态 (granted)。UPDATE_PERMISSIONS_REPLACE_ALL 标志意味着可能撤销并重新授予权限。
    • ​初始化默认 App (applyDefaultPreferredAppsLPw):​ ​ 如果是第一次开机 (mFirstBoot) 或者是 Android M (6.0) 大升级后的第一次开机 (mPromoteSystemApps),厂长需要为每个用户初始化一些默认设置,比如默认的浏览器、拨号 App、短信 App 等。

    • ​清理 OTA 后的代码缓存 (clearAppDataLIF):​ ​ 如果本次是 OTA 升级后的第一次开机 (mIsUpgrade),为了防止旧的优化代码 (code_cache) 引发兼容性问题,厂长下令:​​清除所有 App 的代码缓存目录​ ​(/data/data/<pkg>/code_cache)。

    • ​更新档案库版本信息:​ ​ 将当前的 Android SDK 版本 (mSdkVersion) 和设备指纹 (Build.FINGERPRINT) 记录到档案库 (ver.sdkVersion, ver.fingerprint)。

    • ​存档!(mSettings.writeLPr()):​ ​ 将内存中辛苦构建好的中央档案库 (mSettings 的所有信息) ​​永久保存到磁盘文件​ ​ (/data/system/packages.xml, /data/system/packages.list 等)。这样下次工厂启动时就能快速读取恢复状态了。这是极其重要的一步!

  5. ​阶段五:开张准备 (BOOT_PROGRESS_PMS_READY)​

    scss 复制代码
    java
    Copy
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis());
    // 创建安装会话管理服务 (相当于工厂的客户服务部/安装预约窗口)
    mInstallerService = new PackageInstallerService(context, this);
    ... // (其他服务初始化)
    Runtime.getRuntime().gc(); // 进行一次大扫除(垃圾回收)
    // 将 PackageManagerInternalImpl (PMS的内部管理接口) 注册为本地服务
    LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());

    ​故事:​​ 工厂建设终于完成!

    • ​宣布准备就绪 (BOOT_PROGRESS_PMS_READY)。​
    • ​成立安装预约窗口 (PackageInstallerService):​ 创建 PackageInstallerService。这个服务负责管理 App 的安装和卸载​会话​ (Session),比如用户从应用商店下载 App 后点击安装,就是由这个服务创建会话并最终交给 PMS 的物流主管 (PackageHandler) 和施工队长 (Installer) 去执行。
    • ​大扫除 (gc):​ 建设过程中产生了很多临时垃圾,进行一次全面的清理 (Java 垃圾回收)。
    • ​注册内部管理接口 (PackageManagerInternalImpl):​PackageManagerInternalImpl 注册到 LocalServices。这个接口是供运行在 ​同一进程 (system_server) 内的其他系统服务​ (如 AMS) ​高效访问 PMS 内部功能​ 的通道。比如 AMS 启动 Activity 时需要快速查询 App 信息,通过这个接口调用比通过 Binder (ServiceManager.getService("package")) 更快。

​大结局:​

经过 SystemServer 大管家的召唤 (main() 方法) 和 PMS 厂长在构造函数中五个阶段的艰苦建设 (BOOT_PROGRESS_PMS_*),PMS 这座管理 Android 世界所有 App 的"超级工厂"

相关推荐
用户2018792831677 小时前
通俗易懂的讲解:Android系统启动全流程与Launcher诞生记
android
二流小码农7 小时前
鸿蒙开发:资讯项目实战之项目框架设计
android·ios·harmonyos
用户2018792831678 小时前
WMS 的核心成员和窗口添加过程
android
用户2018792831679 小时前
通俗易懂的讲解:Android APK 解析的故事
android
渣渣_Maxz9 小时前
使用 antlr 打造 Android 动态逻辑判断能力
android·设计模式
Android研究员9 小时前
HarmonyOS实战:List拖拽位置交换的多种实现方式
android·ios·harmonyos
guiyanakaung9 小时前
一篇文章让你学会 Compose Multiplatform 推荐的桌面应用打包工具 Conveyor
android·windows·macos
恋猫de小郭9 小时前
Flutter 应该如何实现 iOS 26 的 Liquid Glass ,它为什么很难?
android·前端·flutter
葱段9 小时前
【Compose】Android Compose 监听TextField粘贴事件
android·kotlin·jetbrains