Static Reflection
Static Reflection
发布于 2025-09-09 / 29 阅读
0

通过 bootanimation 服务预览指定开机动画

在制作了自定义开机动画后,想要在真机上预览效果时,可以通过 Android 的 bootanimation 服务来实现。该服务会在系统启动时播放 /system/media/bootanimation.zip 等路径下的动画资源。由于源码中开机动画路径已写死,我们需要借助一些技巧来临时替换并启动动画服务进行预览。

修改当前开机动画

原生的 BootAnimation 并未提供直接播放自定义动画的参数。阅读 BootAnimation.cpp 源码可以发现,系统默认的开机动画路径是硬编码在代码里的,如下所示:

// BootAnimation.cpp
static const char OEM_BOOTANIMATION_FILE[]     = "/oem/media/bootanimation.zip";
static const char PRODUCT_BOOTANIMATION_DIR[]  = "/product/media/";
static const char PRODUCT_BOOTANIMATION_FILE[] = "bootanimation.zip";
static const char SYSTEM_BOOTANIMATION_FILE[]  = "/system/media/bootanimation.zip";
static const char APEX_BOOTANIMATION_FILE[]    = "/apex/com.android.bootanimation/etc/bootanimation.zip";
static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip";
static const char PRODUCT_SHUTDOWNANIMATION_FILE[] = "/product/media/shutdownanimation.zip";
static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip";

上述代码来自 Android 14 的 BootAnimation 模块,可见系统会依次在 /oem/media//product/media//system/media/ 等路径下查找 bootanimation.zip。由于路径写死在二进制中,直接修改二进制并不现实;而各厂商定制的路径可能也略有不同,因此需要自行确定设备上的实际路径。

我们可以利用 Linux 的 挂载绑定(mount --bind) 技术,临时将设备存储(如 /sdcard)中的自定义动画包替换到系统路径。例如,假设系统默认动画路径为 /my_product/media/bootanimation/bootanimation.zip,而我们想预览的动画包放在 /sdcard/bootanimation.zip,可以执行

mount --bind /sdcard/bootanimation.zip /my_product/media/bootanimation/bootanimation.zip

这样即可暂时用自定义的 bootanimation.zip 覆盖系统默认动画(该操作需要 root 权限)

启动 BootAnimation 预览

要启动开机动画预览,需要设置 SurfaceFlinger 中的启动属性。在 StartPropertySetThread.cpp 中可以看到如下代码

// StartPropertySetThread.cpp
bool StartPropertySetThread::threadLoop() {
    // Set property service.sf.present_timestamp, consumer need check its readiness
    property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");
    // Clear BootAnimation exit flag
    property_set("service.bootanim.exit", "0");
    property_set("service.bootanim.progress", "0");
    // Start BootAnimation if not started
    property_set("ctl.start", "bootanim");
    // Exit immediately
    return false;
}

或者参考文档中的说明:执行 property_set("ctl.start", "bootanim") 会启动 bootanim 进程,而 property_set("ctl.stop", "bootanim") 则会停止它;同时 BootAnimation 进程会周期检查系统属性 service.bootanim.exit,当其值为 1 时退出动画,为 0 时播放动画

因此,执行以下命令即可启动预览(需要在设备的 adb shell 或终端内执行,该操作需要 root 权限):

setprop service.bootanim.exit 0
setprop service.bootanim.progress 0
setprop ctl.start bootanim

上述命令会清除退出标志、重置进度,并通过 ctl.start 向 init 进程发送启动 bootanim 服务的指令,从而播放我们刚才挂载的自定义开机动画

停止预览

预览完成后,可以通过以下命令停止 bootanim 服务(该操作需要 root 权限):

setprop ctl.stop bootanim
setprop service.bootanim.exit 1

这样 bootanim 进程会被停止,并将退出属性置为 1,结束动画显示

参考资料