一、概述
在 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.bp):
android_app { name: "BasicDreams", platform_apis: true, certificate: "platform", // 签名自选 // 没设 privileged: true,所以进 system/app }3.3/system/priv-app—— 系统特权应用
priv-app是 Android 4.4(KitKat)引入的概念,在后续版本中不断增强。它与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 配置示例(Soong):
android_app { name: "CalendarProvider", platform_apis: true, certificate: "platform", privileged: true, // <-- 这行决定进 system/priv-app }- 传统 Makefile 配置(Android.mk):
LOCAL_PRIVILEGED_MODULE := true3.4/vendor/app与/vendor/priv-app—— 硬件厂商分区(Project Treble)
Android 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 配置示例(Soong):
android_app { name: "CneApp", proprietary: true, // vendor 分区 certificate: "platform", ... }- 传统 Makefile 配置:
LOCAL_VENDOR_MODULE := true3.5/product/app与/product/priv-app—— 产品分区(Android 9+)
Android 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 配置示例(Soong):
android_app { name: "Dialer", product_specific: true, privileged: true, certificate: "platform", ... }3.6/system_ext/app与/system_ext/priv-app—— 系统扩展分区(Android 10/11+)
Android 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 APK):
android_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-159:
system_ext_specific: true, privileged: true,3.7/odm/app与/odm/priv-app—— ODM 分区
ODM(Original Design Manufacturer)分区是为原始设计制造商准备的。ODM 通常是设计并代工手机的工厂(如闻泰、华勤),它们在 OEM 品牌(如小米)的基础上做二次定制。
- 使用场景:ODM 厂商需要加入自己的特定应用,但又不想和 OEM(product)或 SoC(vendor)混在一起
确认你的apk安装在哪
在开发过程中有时候需要知道某个app具体apk放在在哪个分区,那么这个时候只需要知道packageName就可以了。
相关命令:
先确认报名,这里先打开要确认app的Activity
然后使用
adb shell am stack list命令
adb shell am stack list RootTaskid=1bounds=[0,0][1080,2340]displayId=0userId=0configuration={1.0?mcc0mnc[en_US]ldltr sw393dp w393dp h851dp 440dpi nrml long hdr widecg port night finger -keyb/v/h -nav/hwinConfig={mBounds=Rect(0,0-1080,2340)mAppBounds=Rect(0,0-1080,2340)mMaxBounds=Rect(0,0-1080,2340)mDisplayRotation=ROTATION_0mWindowingMode=fullscreenmActivityType=homemAlwaysOnTop=undefinedmRotation=ROTATION_0}as.3 s.28fontWeightAdjustment=0}taskId=54: com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncherbounds=[0,0][1080,2340]userId=0visible=truetopActivity=ComponentInfo{com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher}RootTaskid=2bounds=[0,0][1080,2340]displayId=0userId=0configuration={1.0?mcc0mnc[en_US]ldltr sw393dp w393dp h851dp 440dpi nrml long hdr widecg port night finger -keyb/v/h -nav/hwinConfig={mBounds=Rect(0,0-1080,2340)mAppBounds=Rect(0,0-1080,2340)mMaxBounds=Rect(0,0-1080,2340)mDisplayRotation=ROTATION_0mWindowingMode=fullscreenmActivityType=undefinedmAlwaysOnTop=undefinedmRotation=ROTATION_0}as.3 s.28fontWeightAdjustment=0}taskId=3: unknownbounds=[0,0][1080,2340]userId=0visible=falsetaskId=4: unknownbounds=[0,2340][1080,3510]userId=0visible=false可以看到launcher包名是com.android.launcher3。
那么接下来在看看包名对应的apk目录:
这里可以使用adb shell dumpsys package com.android.launcher3方式输出所有这个包名的pms相关信息
test@test:~/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。