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 的"超级工厂"

相关推荐
xiaolizi5674896 小时前
安卓远程安卓(通过frp与adb远程)完全免费
android·远程工作
阿杰100016 小时前
ADB(Android Debug Bridge)是 Android SDK 核心调试工具,通过电脑与 Android 设备(手机、平板、嵌入式设备等)建立通信,对设备进行控制、文件传输、命令等操作。
android·adb
梨落秋霜7 小时前
Python入门篇【文件处理】
android·java·python
遥不可及zzz9 小时前
Android 接入UMP
android
Coder_Boy_11 小时前
基于SpringAI的在线考试系统设计总案-知识点管理模块详细设计
android·java·javascript
冬奇Lab12 小时前
【Kotlin系列03】控制流与函数:从if表达式到Lambda的进化之路
android·kotlin·编程语言
冬奇Lab12 小时前
稳定性性能系列之十二——Android渲染性能深度优化:SurfaceFlinger与GPU
android·性能优化·debug
冬奇Lab13 小时前
稳定性性能系列之十一——Android内存优化与OOM问题深度解决
android·性能优化
用户745890020795414 小时前
线程池
android