(十三)Android 修改系统启动动画

版权声明:本文为博主原创文章,未经博主允许不得转载。
本文纯个人学习笔记,由于水平有限,难免有所出错,有发现的可以交流一下。

一、原理分析

生活中使用的华为、小米、三星等手机,在开机的时候显示的各个产商的 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.效果

开机重启,显示的就是我们替换的图片。
这里写图片描述

三、问题

原理是这样没有错,但是我在模拟器运行的时候,有时候可以,有时候不行,甚至压缩包会被删除,具体原因未知。有知道的请留言。

猜你喜欢

转载自blog.csdn.net/qq_18983205/article/details/80233415