版权声明:本文为博主原创文章,未经博主允许不得转载。
本文纯个人学习笔记,由于水平有限,难免有所出错,有发现的可以交流一下。
一、原理分析
生活中使用的华为、小米、三星等手机,在开机的时候显示的各个产商的 logo,而不是像我们安卓模拟器那样是一个安卓机器人和 Android 文字。这是因为哥哥产商修改了各自手机的开机启动动画。
在上一篇文章 中的 一、虚拟机的启动下的1.init 源码 中提到,在开机的时候,系统会把 \frameworks\base\cmds 下的所有可执行文件启动,其中包括一个 bootanimation,很明显这就是开机启动动画。
我们在开机的时候,都是先显示开机动画,开机成功后才跳转到桌面,可以猜到,这里的开机动画是需要资源文件进行加载的,我们可以通过源码进行查找该资源文件。
bootanimation 的入口是在 \frameworks\base\cmds\bootanimation\bootanimation_main.cpp 下。
bootanimation_main.cpp 的 main:
int main()
{
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.nobootanimation", value, "0");
int noBootAnimation = atoi(value);
ALOGI_IF(noBootAnimation, "boot animation disabled");
if (!noBootAnimation) {
//创建线程池
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
// create the boot animation object
sp<BootAnimation> boot = new BootAnimation();
IPCThreadState::self()->joinThreadPool();
}
return 0;
}
在这里创建了一个线程池,并且创建了一个 BootAnimation,然后把它加入到线程池中。我们继续查看 BootAnimation。该文件位于 \frameworks\base\cmds\bootanimation\BootAnimation.cpp 。
BootAnimation.cpp 部分代码:
BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
mTimeCheckThread(NULL) {
mSession = new SurfaceComposerClient();
// If the system has already booted, the animation is not being used for a boot.
mSystemBoot = !property_get_bool(BOOT_COMPLETED_PROP_NAME, 0);
}
BootAnimation 继承 Thread,不过与 java 的 Thread 有所区别,它的启动是 readyToRun 这个方法。
readyToRun 部分代码:
static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";
status_t BootAnimation::readyToRun() {
......
if (encryptedAnimation && (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) {
mZipFileName = SYSTEM_ENCRYPTED_BOOTANIMATION_FILE;
}
else if (access(OEM_BOOTANIMATION_FILE, R_OK) == 0) {
mZipFileName = OEM_BOOTANIMATION_FILE;
}
else if (access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) {
mZipFileName = SYSTEM_BOOTANIMATION_FILE;
}
return NO_ERROR;
}
在 readyToRun 的末尾,去按顺序获取 SYSTEM_ENCRYPTED_BOOTANIMATION_FILE、OEM_BOOTANIMATION_FILE、SYSTEM_BOOTANIMATION_FILE 这三个文件,如果获取到就跳过。这就是开机动画的资源文件。
threadLoop:
bool BootAnimation::threadLoop()
{
bool r;
// We have no bootanimation file, so we use the stock android logo
// animation.
if (mZipFileName.isEmpty()) {
r = android();
} else {
r = movie();
}
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(mDisplay, mContext);
eglDestroySurface(mDisplay, mSurface);
mFlingerSurface.clear();
mFlingerSurfaceControl.clear();
eglTerminate(mDisplay);
IPCThreadState::self()->stopProcess();
return r;
}
bool BootAnimation::android()
{
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
......
}
当线程开始执行时候,调用到 threadLoop,先去判断开机资源文件是否为空,为空的话则调用 android 这个方法,android 方法会默认加载两张图片,就是 Android 文字亮色与暗色,这就是默认的开机启动的效果。不为空则调用 movie 方法,会开启动画效果。
二、替换
1.准备
新建一个文件夹,按顺序存放要播放的一组图片。
在上述文件夹同级目录下创建 desc.txt 文件。
* desc.txt :*
540 960 5
p 0 0 folder1
540 宽度
960 高度
7 帧率 一秒播放多少帧
p 标识符
0 循环次数 无限循环
folder1 对应要播放文件夹名称(上面创建的文件夹)
2.压缩
把上面的文件夹和 desc.txt 存储到 bootanimation.zip 中。
注:一定要选择存储,不能进行压缩,右边勾全去掉。
3.push
使用 root 权限,把 bootanimation.zip push 到上面三个路径中的一个即可。
有时候发现文件权限不够的时候,执行 mount -rw -o remount /system 即可。
4.效果
开机重启,显示的就是我们替换的图片。
三、问题
原理是这样没有错,但是我在模拟器运行的时候,有时候可以,有时候不行,甚至压缩包会被删除,具体原因未知。有知道的请留言。