本文档详细记录了 Android 15 (AOSP 15) 系统中,从 init 进程启动到 SurfaceFlinger 触发,再到 BootAnimation 执行与结束的完整代码流转及架构设计。
一、BootAnimation动画流程源码分析
1. init 阶段:解析与服务定义
在系统启动初期,init 进程解析 .rc 文件,定义服务的启动类别和权限。
1.1 SurfaceFlinger 配置
- 路径:
frameworks/native/services/surfaceflinger/surfaceflinger.rc - 说明:SF 属于
core和animation类,通常在系统显示驱动加载后启动。
service surfaceflinger /system/bin/surfaceflinger
class core animation
user system
group graphics drmrpc readproc
capabilities CHOWN DAC_OVERRIDE SYS_NICE
onrestart restart zygote
task_profiles ServiceCapacityLow HighPerformance
1.2 BootAnimation 配置
- 路径:
frameworks/base/cmds/bootanimation/bootanim.rc - 说明:默认标记为
disabled,必须由其他进程(SF)通过属性显式启动。
service bootanim /system/bin/bootanimation
class core
user graphics
group graphics audio
disabled # 初始状态不启动
oneshot # 运行一次后不自动重启
ioprio rt 4
task_profiles MaxPerformance
2. SurfaceFlinger 阶段:触发逻辑
AOSP 15 对 SF 初始化进行了重构,删除了旧版本的异步属性设置线程类。
2.1 入口:main_surfaceflinger.cpp
- 路径:
frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp - 操作:实例化
SurfaceFlinger并执行flinger->init()。
2.2 关键方法:initBootProperties
- 路径:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
// init()方法中执行异步
mInitBootPropsFuture.callOnce([this] {
return std::async(std::launch::async, &SurfaceFlinger::initBootProperties, this);
});
// 设置开始启动动画
void SurfaceFlinger::initBootProperties() {
property_set("service.sf.present_timestamp", mHasReliablePresentFences ? "1" : "0");
if (base::GetBoolProperty("debug.sf.boot_animation"s, true)) {
// Reset and (if needed) start BootAnimation.
property_set("service.bootanim.exit", "0");
property_set("service.bootanim.progress", "0");
property_set("ctl.start", "bootanim");
}
}
3. 执行阶段:BootAnimation 进程渲染
bootanimation 进程启动后,核心逻辑由 BootAnimation 类驱动。
3.1 核心初始化流程
- 路径:
frameworks/base/cmds/bootanimation/BootAnimation.cpp
1、 onFirstRef(): 初始化 Binder 通信。
2、 readyToRun():
- 调用 waitForSurfaceFlinger() 确保 SF 已注册。
- 创建 SurfaceComposerClient 连接。
- 创建渲染 Layer(通常名为 "BootAnimation")。
3、threadLoop(): 核心渲染循环。
- 如果 /system/media/bootanimation.zip 存在,则解析并执行 movie()。
- 否则执行默认的 android()(即渐变 Logo 动画)。
bool BootAnimation::threadLoop() {
ATRACE_CALL();
bool result;
initShaders();
// We have no bootanimation file, so we use the stock android logo
// animation.
if (mZipFileName.empty()) {
ALOGD("No animation file");
result = android(mDisplays.front());
} else {
result = movie();
}
.....
return result;
}
4. 结束阶段:从 WMS 到退出
动画的停止是由 WindowManagerService 根据系统加载状态决定的。
4.1 WMS 发出完成信号
当系统完成启动且桌面(Launcher)准备好显示首帧时:
- 路径:
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java - 调用:
SurfaceControl.bootFinished()
4.2 SF 修改退出属性
SF 收到 WMS 的 Binder 调用后,更新系统属性
- 路径:
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::bootFinished() {
if (mBootFinished == true) {
ALOGE("Extra call to bootFinished");
return;
}
mBootFinished = true;
FlagManager::getMutableInstance().markBootCompleted();
......
// stop boot animation
// formerly we would just kill the process, but we now ask it to exit so it
// can choose where to stop the animation.
property_set("service.bootanim.exit", "1");
......
}
4.3 动画进程响应
BootAnimation 在渲染循环中会调用 checkExit():
void BootAnimation::checkExit() {
ATRACE_CALL();
// Allow SurfaceFlinger to gracefully request shutdown
char value[PROPERTY_VALUE_MAX];
property_get(EXIT_PROP_NAME, value, "0");
int exitnow = atoi(value);
if (exitnow) {
requestExit();
}
}
二、bootanimation.zip制作实战
在 AOSP 15 中,系统支持通过自定义 bootanimation.zip 来替换默认的启动动画。该文件必须以 存储(Store) 模式进行压缩(即压缩率为 0),先上效果图。
1. 目录结构
一个标准的 bootanimation.zip 结构如下:
bootanimation.zip
├── desc.txt # 核心控制文件(必选)
├── part0/ # 第一阶段动画图片文件夹
│ ├── 00001.jpg
│ └── ...
├── part1/ # 第二阶段动画图片文件夹
└── ...
2. desc.txt 语法详解
desc.txt 是一个纯文本文件,定义了动画的分辨率、帧率以及各阶段的播放逻辑。
2.1 文件格式示例
1080 2400 30
p 1 0 part0
p 0 0 part1
2.2 参数含义
-
第一行 (Header):[宽度] [高度] [帧率]
- 示例中:1080x2400 分辨率,每秒播放 30 帧。
-
后续行 (Part Definition):[类型] [循环次数] [暂停帧数] [文件夹名]
-
类型:
- p (Plain):播放完该阶段后,如果系统启动未完成,则进入下一阶段。
- c (Complete):必须完整播放该阶段的所有帧,即使系统已经准备好进入桌面(AOSP 15 常用此项确保品牌 Logo 完整展示)。
-
循环次数:0 表示无限循环,直到系统发出退出信号。
-
暂停帧数:播放完当前阶段后,停留在最后一帧的帧数。
-
3. AOSP 15 高级配置技巧
3.1 动态颜色 (Dynamic Coloring)
AOSP 15 支持根据系统主题色渲染动画(通常用于 Google Pixel 风格)。这需要在 desc.txt 中加入特殊的动态颜色标记,并配合特定的图片格式,但这通常需要修改 BootAnimation.cpp 中的像素处理逻辑
3.2 多显示器支持
针对折叠屏或车机(多屏环境),AOSP 15 支持为不同显示器指定动画:
- 主屏:bootanimation.zip
- 副屏:bootanimation_secondary.zip
3.3 压缩注意事项(关键)
在打包时,严禁使用默认压缩,如果使用了压缩(Deflate),bootanim 进程在映射 Buffer 时会失败,导致黑屏或显示默认的 "ANDROID" 文字。用window要设置“zip”和设置存储格式,或在Linux 命令行中,应使用:
zip -0qr bootanimation.zip
4. 集成到 AOSP 镜像
要将自定义动画集成到系统编译中,请修改你的 Product Makefile(如 device.mk):
# 将本地的 zip 文件拷贝到系统的媒体目录下
PRODUCT_COPY_FILES += \
device/provider/project/bootanimation.zip:system/media/bootanimation.zip
如果报没有权限,可以添加一下system/media白名单权限
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \
system/media/bootanimation.zip
5. 调试实用命令
# 1. 过滤开机动画进程日志
adb logcat -s BootAnimation
# 2. 手动停止/启动动画(用于调试,需 root)
adb shell setprop ctl.stop bootanim
adb shell setprop ctl.start bootanim
# 3. 检查系统启动状态属性
adb shell getprop | grep boot
# 查看 service.bootanim.exit 的值
6. 常见问题排查 (Troubleshooting)
在 AOSP 15 开发过程中,如果自定义动画未能如期显示或出现异常,通常可以从压缩方式、配置文件逻辑、系统权限以及底层架构四个维度进行排查。
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 开机完全黑屏 | 压缩格式错误 | 必须使用 zip -0(存储模式)打包,严禁压缩 |
| 显示 "ANDROID" 闪烁文字 | 资源文件丢失或路径错误 | 检查 /system/media/bootanimation.zip 是否存在 |
| 动画异常卡顿/跳帧 | 图片过大或 CPU 负载过高 | 降低分辨率,建议使用 JPG 格式减小解码压力 |
| 动画播不完就跳到桌面 | desc.txt 逻辑配置问题 | 将关键阶段的类型从 p 改为 c (Complete) |
| 多屏设备副屏不亮 | 缺少副屏资源包 | 需提供 bootanimation_secondary.zip |