Android 系统 APK 分区存放剖析-你的apk应该放在哪里?
一、概述在 Android 系统中APK 的存放路径远不止 /system/app 这一个。从 Android 早期到现在随着系统架构的演进尤其是 Project Treble 之后APK 的存放路径被划分成了多个不同的分区目录。不同分区的 APK 在卸载行为、权限获取机制、签名要求等方面都有本质区别。本文基于 AOSP 15 源码设备的实际编译产物对 Android 系统中所有 APK 存放路径做一个完整的梳理和对比。二、所有分区路径总览以下是从你的 AOSP 15 编译产物中列出的所有 APK 存放分区及其实际内容以target/product/grus为例三、各分区详解3.1/data/app—— 第三方应用这是最普遍的第三方应用路径。通过 Google Play 或其他应用商店安装、或者用户手动adb install的 APK都存放在这里。可卸载用户可以随时卸载签名无特殊要求开发者自签名即可权限只能使用normal和dangerous保护级别的权限实际路径每个 app 一个子目录如/data/app/com.example.app-xxxxxxxx/编译产物中不存在因为它是运行时动态安装的编译产物不会预置3.2/system/app—— 系统内置应用这是 Android 内置的系统级应用路径与/data/app不同这里的应用不能被普通用户卸载。可卸载普通用户不可卸载需要 root 或系统级操作签名无强制要求可以是 platform 签名、shared 签名、media 签名、甚至是第三方自定义签名权限可以声明normal和dangerous级别权限但对于signature|privileged保护级别的权限默认无法获得需满足额外条件见后文编译产物举例system/app/BasicDreams/ # 屏保 system/app/BluetoothMidiService/ # 蓝牙MIDI服务 system/app/CaptivePortalLogin/ # WiFi 登录门户 system/app/CertInstaller/ # 证书安装器 system/app/KeyChain/ # 密钥链 system/app/PrintSpooler/ # 打印服务 system/app/Stk/ # SIM工具包 system/app/EasterEgg/ # Android彩蛋Build 配置示例Soong / Android.bpandroid_app { name: BasicDreams, platform_apis: true, certificate: platform, // 签名自选 // 没设 privileged: true所以进 system/app }3.3/system/priv-app—— 系统特权应用priv-app是 Android 4.4KitKat引入的概念在后续版本中不断增强。它与system/app最核心的区别在于priv-app 中的 APK 有资格申请signature|privileged保护级别的系统权限但前提是必须在对应的privapp-permissions.xml文件中显式声明。可卸载普通用户不可卸载签名同 system/app无强制要求权限门槛放置于 priv-app 只是获得了一张门票真正获得权限还需要第二步——白名单声明见第四章编译产物举例system/priv-app/CalendarProvider/ # 日历提供者 system/priv-app/ContactsProvider/ # 联系人提供者 system/priv-app/CredentialManager/ # 凭证管理 system/priv-app/DocumentsUI/ # 文件选择器 system/priv-app/DownloadProvider/ # 下载管理器 system/priv-app/ExternalStorageProvider/ # 外部存储提供者 system/priv-app/FusedLocation/ # 融合定位 system/priv-app/IntentResolver/ # Intent解析器Build 配置示例Soongandroid_app { name: CalendarProvider, platform_apis: true, certificate: platform, privileged: true, // -- 这行决定进 system/priv-app }传统 Makefile 配置Android.mkLOCAL_PRIVILEGED_MODULE : true3.4/vendor/app与/vendor/priv-app—— 硬件厂商分区Project TrebleAndroid 8.0 引入 Project Treble将**硬件相关代码HAL 实现、SoC 驱动配套 app**从 system 分区中分离出来形成 vendor 分区。目的让 system 分区可以独立升级Generic System Image, GSI不受硬件厂商定制影响存放内容与硬件/SoC 紧耦合的 APK如运营商网络相关CneApp、IWlanService、Qualcomm 配套服务等可卸载不可卸载编译产物举例vendor/app/CneApp/ # 连接引擎Qualcomm vendor/app/IWlanService/ # IWLAN服务 vendor/app/TimeService/ # 时间服务 vendor/app/CACertService/ # CA证书服务Build 配置示例Soongandroid_app { name: CneApp, proprietary: true, // vendor 分区 certificate: platform, ... }传统 Makefile 配置LOCAL_VENDOR_MODULE : true3.5/product/app与/product/priv-app—— 产品分区Android 9Android 9 引入 Product 分区用于存放OEM 厂商定制的产品级应用。这些应用不是 AOSP 原生的也不是硬件绑定的而属于 OEM 的差异化定制相机 App、时钟、短信等。目的更精细的模块化让 OEM 的定制内容也可以单独构建和升级编译产物举例product/app/Aperture/ # 相机LineageOS product/app/DeskClock/ # 时钟 product/app/Gallery2/ # 图库 product/app/LatinIME/ # 输入法 product/app/Jelly/ # 浏览器 product/app/messaging/ # 短信 product/app/Recorder/ # 录音机 product/priv-app/Contacts/ # 联系人 product/priv-app/Dialer/ # 拨号器 product/priv-app/SettingsIntelligence/ # 设置建议Build 配置示例Soongandroid_app { name: Dialer, product_specific: true, privileged: true, certificate: platform, ... }3.6/system_ext/app与/system_ext/priv-app—— 系统扩展分区Android 10/11Android 10/11 引入 SystemExt 分区。这是为了解决一个尴尬的问题很多 AOSP 核心应用如 Settings、SystemUI、Launcher3、Telecom既不能放在 product 分区因为它们是 AOSP 原生组件不是 OEM 定制又不宜留在 system 分区为了更好的模块化。定位存放扩展 AOSP 功能的组件介于 system 和 product 之间编译产物举例在 grus 上这是最丰富的 priv-app 目录system_ext/app/AccessibilityMenu/ # 无障碍菜单 system_ext/app/IFAAService/ # IFAA生物识别服务 system_ext/app/QtiTelephonyService/ # QTI电话服务 system_ext/app/WAPPushManager/ # WAP推送管理 system_ext/priv-app/Settings/ # -- 设置已从 system/priv-app 迁移 system_ext/priv-app/SystemUI/ # -- 系统UI system_ext/priv-app/TrebuchetQuickStep/ # Launcher system_ext/priv-app/ThemePicker/ # 主题选择器 system_ext/priv-app/CarrierConfig/ # 运营商配置 system_ext/priv-app/Seedvault/ # 备份 system_ext/priv-app/Updater/ # 系统更新 system_ext/priv-app/AudioFX/ # 音效 system_ext/priv-app/StorageManager/ # 存储管理Build 配置示例Settings APKandroid_app { name: Settings, platform_apis: true, certificate: platform, system_ext_specific: true, // -- 指定进 system_ext privileged: true, // -- 指定进 priv-app 子目录 required: [ privapp_whitelist_com.android.settings, settings-platform-compat-config, ], ... }关键代码位于packages/apps/Settings/Android.bp:158-159system_ext_specific: true, privileged: true,3.7/odm/app与/odm/priv-app—— ODM 分区ODMOriginal Design Manufacturer分区是为原始设计制造商准备的。ODM 通常是设计并代工手机的工厂如闻泰、华勤它们在 OEM 品牌如小米的基础上做二次定制。使用场景ODM 厂商需要加入自己的特定应用但又不想和 OEMproduct或 SoCvendor混在一起确认你的apk安装在哪在开发过程中有时候需要知道某个app具体apk放在在哪个分区那么这个时候只需要知道packageName就可以了。相关命令先确认报名这里先打开要确认app的Activity然后使用adb shell am stack list命令adb shell am stack list RootTaskid1bounds[0,0][1080,2340]displayId0userId0configuration{1.0?mcc0mnc[en_US]ldltr sw393dp w393dp h851dp 440dpi nrml long hdr widecg port night finger -keyb/v/h -nav/hwinConfig{mBoundsRect(0,0-1080,2340)mAppBoundsRect(0,0-1080,2340)mMaxBoundsRect(0,0-1080,2340)mDisplayRotationROTATION_0mWindowingModefullscreenmActivityTypehomemAlwaysOnTopundefinedmRotationROTATION_0}as.3 s.28fontWeightAdjustment0}taskId54: com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncherbounds[0,0][1080,2340]userId0visibletruetopActivityComponentInfo{com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher}RootTaskid2bounds[0,0][1080,2340]displayId0userId0configuration{1.0?mcc0mnc[en_US]ldltr sw393dp w393dp h851dp 440dpi nrml long hdr widecg port night finger -keyb/v/h -nav/hwinConfig{mBoundsRect(0,0-1080,2340)mAppBoundsRect(0,0-1080,2340)mMaxBoundsRect(0,0-1080,2340)mDisplayRotationROTATION_0mWindowingModefullscreenmActivityTypeundefinedmAlwaysOnTopundefinedmRotationROTATION_0}as.3 s.28fontWeightAdjustment0}taskId3: unknownbounds[0,0][1080,2340]userId0visiblefalsetaskId4: unknownbounds[0,2340][1080,3510]userId0visiblefalse可以看到launcher包名是com.android.launcher3。那么接下来在看看包名对应的apk目录这里可以使用adb shell dumpsys package com.android.launcher3方式输出所有这个包名的pms相关信息testtest:~/wmtrace$ adb shell dumpsys package com.android.launcher3|greppath overlay paths: legacy overlay paths: path: /system_ext/priv-app/TrebuchetQuickStep/TrebuchetQuickStep.apk可以确认apk路径位于/system_ext/priv-app/TrebuchetQuickStep/TrebuchetQuickStep.apk。