Android 13 AOSP 源码添加系统预置应用实战指南

前言
在 Android 系统开发中,将自定义应用(APK)预置到系统镜像中,是一个常见需求。比如开发一个企业定制 ROM,或者在模拟器中预置自己的测试应用。本文将详细记录我在 Android 13 AOSP 源码上,将 MyApp.apk 添加为系统预置应用的完整探索过程和实战经验。

一、问题定义
1.1 什么是系统预置应用?
系统预置应用是指直接打包到 Android 系统镜像中的应用,开机后自动安装,无需用户手动安装。常见的系统预置应用包括:
- 设置应用(Settings)
- 启动器(Launcher3)
- 相机、相册、拨号等系统组件
1.2 我们的目标
将 MyApp.apk 添加到 Android 13 AOSP 系统镜像中,使其在模拟器启动后自动显示在应用列表中。
普通应用 vs 系统预置应用的区别

二、探索过程:从观察系统应用开始
2.1 为什么先观察现有系统应用?
面对一个陌生的代码库,最佳的学习方法是观察已有的实现。Settings 和 Launcher3 都是 AOSP 自带的系统应用,它们是如何被添加进系统的?通过研究它们的配置,我们可以找到添加预置应用的"标准答案"。
2.2 寻找 Settings 和 Launcher3 的构建配置
首先,我在 packages/apps/ 目录下找到了 Settings 和 Launcher3 的源码:
packages/apps/Settings/
packages/apps/Launcher3/
packages/apps 目录结构截图

让我先查看 Settings 的配置:
bash
# 查看 Settings 目录结构
ls -la packages/apps/Settings/
结果显示:
Android.bp- 构建配置文件src/- 源码目录AndroidManifest.xml- 应用清单文件apk/- 预编译的 APK(如果有)
Settings 目录结构截图

2.3 理解 Android.bp 构建配置
Settings 的 Android.bp 使用的是 android_app 模块类型(从源码编译):
bp
android_app {
name: "Settings",
defaults: ["platform_app_defaults"],
platform_apis: true,
certificate: "platform",
system_ext_specific: true,
privileged: true,
required: [
"privapp_whitelist_com.android.settings",
"settings-platform-compat-config",
],
static_libs: ["Settings-core"],
uses_libs: ["org.apache.http.legacy"],
}
关键参数解读:
name: "Settings"- 模块名称certificate: "platform"- 使用平台级签名privileged: true- 特权应用,安装到/system/priv-app/system_ext_specific: true- 安装到 system_ext 分区
2.4 探索 Launcher3 的配置
Launcher3 同样使用 android_app 模块类型。让我查看它的构建配置:
bp
android_app {
name: "Launcher3QuickStep",
// ... 配置省略
privileged: true,
certificate: "platform",
}
Launcher3 Android.bp 配置截图

2.5 重要发现:两种不同的构建方式
在观察过程中,我发现系统应用有两种构建方式:
| 构建方式 | 模块类型 | 适用场景 |
|---|---|---|
android_app |
从源码编译 | Settings、Launcher3 等系统组件 |
android_app_import |
导入预编译 APK | 预编译的 APK 文件 |
这给了我一个重要启示:如果我有一个预编译的 APK,应该使用 android_app_import 模块类型。
三、初步尝试:简单粗暴的方法
3.1 第一步:放置 APK 并创建配置
按照初步理解,我把 MyApp.apk 放到 packages/apps/MyApp/ 目录下,并创建了 Android.bp:
bp
android_app_import {
name: "MyApp",
apk: "MyApp.apk",
presigned: true,
product_specific: true,
privileged: false
}
3.2 在产品配置中添加
然后在 build/make/target/product/sdk_phone_x86_64.mk 中添加:
mk
PRODUCT_PACKAGES += \
MyApp
3.3 编译测试
运行编译命令:
bash
source build/envsetup.sh
lunch sdk_phone_x86_64
make -j$(nproc)
编译成功 了!但是当我启动模拟器后,MyApp 并没有显示。
四、问题排查:深入分析
4.1 检查 APK 是否被正确打包
首先,我检查了 APK 是否被正确打包到系统镜像:
bash
# 在模拟器中检查
adb shell ls /product/app/MyApp/
结果:APK 文件存在于 /product/app/MyApp/MyApp.apk
4.2 检查应用是否被安装
bash
adb shell pm list packages | grep -i myapp
结果:没有输出,说明应用根本没有被安装
4.3 关键发现:product_specific 的陷阱
通过 ADB 检查分区挂载情况:
bash
adb shell cat /proc/mounts | grep product
输出:
/dev/block/dm-2 /product ext4 ro,seclabel,relatime 0 0
/product 分区确实挂载了,但为什么应用没有安装?
问题根源 :product_specific: true 会将 APK 安装到 product 分区,但 PackageManager 不会自动安装 product 分区的应用,除非额外配置。
Android 13 动态分区示意图, system/product/vendor 分区的区别

五、再次尝试:移除 product_specific
5.1 修改 Android.bp
我移除了 product_specific: true:
bp
android_app_import {
name: "MyApp",
apk: "MyApp.apk",
presigned: true,
privileged: false
}
5.2 编译测试
重新编译后,再次报错:
FAILED:
build/make/core/artifact_path_requirements.mk:30: error: Build failed.
build/make/target/product/sdk_phone_x86_64.mk produces files inside
build/make/target/product/generic_system.mks artifact path requirement.
Offending entries:
system/app/MyApp/MyApp.apk
六、深入理解:generic_system.mk 的限制
6.1 什么是 artifact path requirements?
artifact path requirements 是 AOSP 用来限制哪些文件可以被打包到哪个分区的机制。这是 Android 13 采用动态分区后的新特性。
6.2 查看 generic_system.mk 的限制
我查看了 build/make/target/product/generic_system.mk:
makefile
# Enable mainline checking
PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := true
这意味着 sdk_phone_x86_64 继承的配置严格限制了 APK 的安装路径。
6.3 解决方案:添加到白名单
查看其他产品是如何解决这个问题的:
在 build/target/product/emulator_system.mk 中,我发现了:
makefile
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST := \
system/lib/libemulator_multidisplay_jni.so \
system/lib64/libemulator_multidisplay_jni.so \
system/priv-app/MultiDisplayProvider/MultiDisplayProvider.apk \
关键发现 :可以通过 PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST 添加白名单!
6.4 最终配置方案
修改 sdk_phone_x86_64.mk:
mk
PRODUCT_PACKAGES += \
MyApp
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \
system/app/MyApp/MyApp.apk
七、新的问题:签名错误
7.1 编译后的新错误
修改配置后,编译成功。但当我通过 ADB 手动安装测试时:
bash
adb install -r /data/local/tmp/MyApp.apk
报错:
Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES:
Failed to collect certificates from ...]
7.2 检查原始 APK 签名
我检查了原始 APK:
bash
unzip -l packages/apps/MyApp/MyApp.apk | grep -i META-INF
结果:没有任何签名文件!(.RSA, .DSA, .EC, CERT.RSA 等都不存在)
7.3 理解 presigned 和 default_dev_cert
查看 AOSP 文档和其他应用配置:
presigned: true- APK 必须有有效签名,构建系统不会重新签名default_dev_cert: true- APK 没有签名或使用测试签名,构建系统会使用默认开发证书签名
7.4 最终解决方案
修改 Android.bp:
bp
android_app_import {
name: "MyApp",
apk: "MyApp.apk",
default_dev_cert: true,
privileged: false
}
【配图位置 7:default_dev_cert vs presigned 的区别说明图】
八、最终验证:成功添加系统预置应用
8.1 完整配置
packages/apps/MyApp/Android.bp:
bp
android_app_import {
name: "MyApp",
apk: "MyApp.apk",
default_dev_cert: true,
privileged: false
}
build/make/target/product/sdk_phone_x86_64.mk:
mk
PRODUCT_PACKAGES += \
MyApp
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \
system/app/MyApp/MyApp.apk
8.2 编译并验证
bash
source build/envsetup.sh
lunch sdk_phone_x86_64
make -j$(nproc)
编译成功后,重启模拟器。
8.3 验证结果
bash
# 检查 APK 位置
adb shell ls /system/app/MyApp/
# 检查应用是否已安装
adb shell pm list packages | grep -i myapp
模拟器中成功显示 MyApp 的截图

输出结果:
/system/app/MyApp/MyApp.apk
package:com.example.myapplication
MyApp 已成功添加为系统预置应用!
九、核心要点总结
9.1 三步成为系统预置应用
三步成为系统预置应用
Step 1: 使用 android_app_import
Step 2: 配置 PRODUCT_PACKAGES
Step 3: 处理 artifact path 限制
不是 android_app
不是 android_library
预编译 APK 专用模块
PRODUCT_PACKAGES += MyApp
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST +=
system/app/MyApp/MyApp.apk
9.2 关键配置参数说明
| 参数 | 说明 | 推荐值 |
|---|---|---|
android_app_import |
模块类型,用于导入预编译 APK | 必须 |
name |
模块名称 | 自定义 |
apk |
APK 文件路径 | 自定义 |
default_dev_cert |
使用 AOSP 默认开发证书签名 | APK 无签名时必须 |
presigned |
APK 已有有效签名 | APK 有签名时使用 |
privileged |
特权应用 | 普通应用用 false |
product_specific |
安装到 product 分区 | 不推荐,会导致不自动安装 |
9.3 Android 13 分区选择
┌─────────────────────────────────────────────────┐
│ Android 13 动态分区架构 │
├─────────────────────────────────────────────────┤
│ /system/app/ - 普通系统应用 [推荐] │
│ /system/priv-app/ - 特权系统应用 │
│ /product/app/ - 产品分区应用 [不推荐] │
│ /system_ext/app/ - system_ext 分区应用 │
└─────────────────────────────────────────────────┘
十、常见问题排查
问题 1:artifact path 限制错误
错误信息:
system/app/MyApp/MyApp.apk in artifact path requirement
解决方案:
在产品 .mk 文件中添加:
mk
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \
system/app/MyApp/MyApp.apk
问题 2:PRODUCT_COPY_FILES 错误
错误信息:
Prebuilt apk found in PRODUCT_COPY_FILES: use BUILD_PREBUILT instead
原因: 不能使用 PRODUCT_COPY_FILES 来复制 APK
解决方案: 使用 PRODUCT_PACKAGES + android_app_import 方式
问题 3:签名相关错误
错误信息:
One and only one of certificate, presigned, and default_dev_cert must be set
原因: 未指定签名方式
解决方案: 添加 default_dev_cert: true 或 presigned: true
问题 4:APK 存在但未安装
现象: ls /product/app/MyApp/ 能看到 APK,但 pm list packages 找不到
原因: 使用了 product_specific: true,导致 APK 安装到 product 分区
解决方案: 移除 product_specific: true,改用默认配置
问题 5:INSTALL_PARSE_FAILED_NO_CERTIFICATES
错误信息:
Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed to collect certificates]
原因: APK 没有签名或签名无效
解决方案: 使用 default_dev_cert: true 让构建系统重新签名
十一、学习方法论
11.1 从观察开始
在面对陌生问题时,观察已有的正确实现是最有效的方法:
- 找到类似的系统应用(Settings、Launcher3)
- 分析它们的构建配置
- 理解每个配置参数的含义
- 复用成功的模式
11.2 小步迭代
不要试图一步到位:
- 先让编译通过
- 再让 APK 正确打包
- 最后让应用正确安装
11.3 善用工具
adb shell pm list packages- 检查已安装应用adb shell ls /system/app/- 检查 APK 位置adb logcat | grep -i package- 查看包管理日志unzip -l- 检查 APK 内容
11.4 阅读错误信息
AOSP 的错误信息通常很详细,仔细阅读错误信息往往能得到解决线索。
结语
通过这次探索,我深刻理解了 Android 13 AOSP 的构建系统和动态分区机制。关键是:
- 选择正确的模块类型 :
android_app_import用于预编译 APK - 正确配置签名 :无签名 APK 使用
default_dev_cert: true - 理解分区机制 :优先使用
/system/app/,避免product_specific - 处理构建限制:通过白名单解决 artifact path 限制
希望这篇指南能帮助你在 Android 13 AOSP 上成功添加系统预置应用!
【配图位置 9:最终成功添加 MyApp 到系统预置应用的完整流程图】
参考资料
- AOSP 官方文档:https://source.android.com/
- Android.bp 构建配置:https://ci.android.com/
- Soong 构建系统:https://source.android.com/docs/setup/create/background
- 动态分区:https://source.android.com/docs/setup/create/dynamic-partitions
本文基于 Android 13.0.0_r6 AOSP 源码编写,测试环境为 sdk_phone_x86_64 模拟器。