一、概述
在 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 := true
3.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 := true
3.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
RootTask id=1 bounds=[0,0][1080,2340] displayId=0 userId=0
configuration={1.0 ?mcc0mnc [en_US] ldltr sw393dp w393dp h851dp 440dpi nrml long hdr widecg port night finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1080, 2340) mAppBounds=Rect(0, 0 - 1080, 2340) mMaxBounds=Rect(0, 0 - 1080, 2340) mDisplayRotation=ROTATION_0 mWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_0} as.3 s.28 fontWeightAdjustment=0}
taskId=54: com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher bounds=[0,0][1080,2340] userId=0 visible=true topActivity=ComponentInfo{com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher}
RootTask id=2 bounds=[0,0][1080,2340] displayId=0 userId=0
configuration={1.0 ?mcc0mnc [en_US] ldltr sw393dp w393dp h851dp 440dpi nrml long hdr widecg port night finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1080, 2340) mAppBounds=Rect(0, 0 - 1080, 2340) mMaxBounds=Rect(0, 0 - 1080, 2340) mDisplayRotation=ROTATION_0 mWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_0} as.3 s.28 fontWeightAdjustment=0}
taskId=3: unknown bounds=[0,0][1080,2340] userId=0 visible=false
taskId=4: unknown bounds=[0,2340][1080,3510] userId=0 visible=false
可以看到launcher包名是com.android.launcher3。
那么接下来在看看包名对应的apk目录:
这里可以使用adb shell dumpsys package com.android.launcher3方式输出所有这个包名的pms相关信息
test@test:~/wmtrace$ adb shell dumpsys package com.android.launcher3 | grep path
overlay paths:
legacy overlay paths:
path: /system_ext/priv-app/TrebuchetQuickStep/TrebuchetQuickStep.apk
可以确认apk路径位于
/system_ext/priv-app/TrebuchetQuickStep/TrebuchetQuickStep.apk。

3837

被折叠的 条评论
为什么被折叠?



