Framework篇 - Android 开机动画分析

本文源代码基于 Android 7.0。

Framework 系列的第一篇就介绍了 Android 系统的启动架构,其中有介绍到,在 native 层,Init 进程会启动 ServiceManager (binder服务管家)、bootanimation (开机动画) 等重要服务。ServiceManager 已经在之前写过了,今天来写写 Android 的 bootanimation (开机动画)。

 

目录:

  1. 启动架构图
  2. 开机启动画面
  3. 开机动画

 

 

1. 启动架构图

avatar

Framework篇 - Android 系统介绍和架构一览

 

 

2. 开机启动画面

开机启动会显示 3 个画面:

  • 1. Linux 内核的静态启动画面。
  • 2. Init 进程启动过程中出现的静态画面。
  • 3. 系统服务启动过程中出现的动态画面 - bootanimation。

 

  • 2.1 Linux 内核的静态启动画面

Bootloader 启动 Linux 内核时的启动画面 (Linux 小企鹅的画面)。 
在默认情况下,这个画面是不会出现的 (Android 1.5及以上版本已经取消加载图片),除非在编译内核的时候,启用以下两个编译选项: 

CONFIG_FRAMEBUFFER_CONSOLE、CONFIG_LOGO 
第一个编译选项表示内核支持帧缓冲区控制台,它对应的配置菜单项为: 
Device Drivers —> Graphics support —> Console display driver support —> Framebuffer Console support。 
第二个编译选项表示内核在启动的过程中,需要显示LOGO,它对应的配置菜单项为: 
Device Drivers —> Graphics support —> Bootup logo。

内核源码: 
/kernel/goldfish/drivers/video/ 
/kernel/goldfish/drivers/video/logo/

 

  • 2.2 Init 进程启动过程中出现的静态画面

Android 系统 Init 进程启动过程中的画面。 
第二个开机画面的内容是由文件 initlogo.rle 来指定的,如果文件 initlogo.rle 文件不存在,或者在显示它的过程中出现异常,那么 Android 就以文本的方式来显示第二个开机画面,即向编号为 0 的控制台 (/dev/tty0) 输出 "ANDROID" 这7个字符。

系统源码: 

/system/core/init/ 
/system/core/init/init.c 
/system/core/init/logo.c 

 

  • 2.3 系统服务启动过程中出现的动态画面 - bootanimation

应用程序 bootanimation 显示的动画。 
bootanimation 程序会检查系统制定目录下是否存在动画文件 (.zip 文件),如果不存在,则显示的第三个开机画面是 Android 系统默认的开机动画 (明暗闪烁的 Android Logo),否则的话,第三个开机画面就是由用户自定义的开机动画。

一般定制的都是 bootanimation​​​​​

 

 

​​​​​​​3. 开机动画

内核起来后会启动第一个进程,即 Init 进程。Init 进程会根据 init.rc 配置启动 surfaceflinger 进程。开机动画是在 SurfaceFlinger 实例通过调用 startBootAnim() 启动的。

service surfaceflinger /system/bin/surfaceflinger
    class main
    user system
    group graphics drmrpc
    onrestart restart zygote

/native/services/surfaceflinger/SurfaceFlinger.cpp

/**
 * SurfaceFlinger的init函数
 *
 * 主要功能:
 *
 * 初始化EGL相关;
 * 创建HWComposer对象;
 * 初始化非虚拟显示屏;
 * 启动app和sf两个EventThread线程;
 * 启动开机动画;
 *
 * 另外,当应用和sf的vsync偏移量一致时,则只创建一个EventThread线程;否则会创建两个DispSyncSource对象,分别是用于绘制(app)和合成(SurfaceFlinger)。
 */
void SurfaceFlinger::init() {
    // ...
    // initialize our drawing state
    // 初始化绘图状态
    mDrawingState = mCurrentState;

    // set initial conditions (e.g. unblank default device)
    // 初始化显示设备
    initializeDisplays();

    // start boot animation
    // 启动开机动画【2.10】
    startBootAnim();

    ALOGV("Done initializing");
}

/**
 * 启动开机动画
 *
 * 通过控制ctl.start属性,设置成bootanim值,则触发init进程来创建开机动画进程bootanim,
 * 到此,则开始显示开机过程的动画。 
 */
void SurfaceFlinger::startBootAnim() {
    // start boot animation
    property_set("service.bootanim.exit", "0");
    property_set("ctl.start", "bootanim");
}

通过 ctl.start 的命令,init 进程就会启动 bootanim 进程,动画就开始播放了。

bootanimation 的实现 - bootanimation_main.cpp:

/base/cmds/bootanimation/bootanimation_main.cpp

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 实例,然后新建一个 Binder 线程池,因为 BootAnimation 在显示动画时要与 SurfaceFlinger 服务进程通信,所以要启个 Binder 线程池。

对于如何修改开机动画,更换素材,有兴趣的同学可以看看这篇文章:如何修改开机动画的两种方式剖析


 

 

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值