Android开机动画总共有三个过程。第一个开机动画是在Kenel启动时显示的,第二个开机动画是在init进程启动时显示的,这两个都是静态图片。第三个动画是在系统服务启动过程中显示的,他是一个动态图片,也是我们关注比较多的动画。

关于动画的播放,主要涉及frame buffer的知识,可以参考老罗的分析http://blog.csdn.net/luoshengyang/article/details/7691321/,从底层的角度,理清了Android的开机动画播放过程。

现在主要关注与开机动画相关的几个类、文件。

一、Kenel动画

Kenel logo是开机显示的第一个动画,用于显示Android内核正在启动过程中。播放的图片位于 vendor/mediatek/proprietary/bootable/bootloader/lk/dev/logo ,系统读取目录下的文件夹里面的logo图片(fwvga_kernel.bmp)显示到手机上的 。那么问题来了,系统默认读的是哪个文件夹? 如何客制化开机Kenel logo?我一修改这个文件夹不是所有的其他国家的logo都要变?

@1.1 系统默认使用哪个文件夹?

其实系统是有一套机制控制Kenel logo的,这也是客制化开机动画的基础,该目录下,有一个mk文件—rules.mk,他会决定当前系统使用哪一套开机kenel logo。

LOCAL_DIR := $(GET_LOCAL_DIR)

BOOT_LOGO_DIR := $(LOCAL_DIR)

#fix no boot_logo config

#LOCAL_CFLAGS += -DBOOT_LOGO=wvga

ifeq ($(strip $(BOOT_LOGO)),)

BOOT_LOGO = fwvga

endif

ifeq ($(strip $(MTK_LK_CAMERA_SUPPORT)), yes)

BOOT_LOGO = fhd

endif

$(info BOOT_LOGO = $(BOOT_LOGO))

$(info lk/logo/dir=$(LOCAL_DIR),builddir=$(BUILDDIR))

由上段代码可以看出来,在BOOT_LOGO没有赋值的情况下,默认使用fwvga文件夹下的Kenel logo。

@1.2 如何客制化开机Kenel logo?

看到这里,我们可以发现,如果要客制化开机Kenel logo图片,可以在rules.mk里面添加相关判断,以达到目的。以海外版本为例,我需要在发货海外的版本中,客制化kenel logo,就需要

1、在rules.mk中添加一下代码

#added by guohongcheng for kenel logo start

ifeq ($(strip $(KENEL_LOGO_PROC)), yes)

BOOT_LOGO = hd720

Endif

#added by guohongcheng for kenel logo end

这样当系统属性KENEL_LOGO_PROC是yes的时候,BOOT_LOGO会加载hd720下面的图片,

2、在ProjectConfig.mk中设置KENEL_LOGO_PROC值

而KENEL_LOGO_PROC这个属性值是在项目的ProjectConfig.mk设置的,添加一下语句

#added by guohongcheng for kenel logo start

KENEL_LOGO_PROC=yes

#added by guohongcheng for kenel logo end

3、配置完成过后我们只需在自己的自拟定文件夹hd720 中,( vendor/mediatek/proprietary/bootable/bootloader/lk/dev/logo 中将logo替换即可。

注意:

(1) 替换时所有图片的命名(不只是2张静态logo,其他的图片也需要拷贝到自拟定目录下进行改名)必须和默认文件夹保持一致 例如 xxxxxxxx_kernel.bmp 和 xxxxxxxx_uboot.bm

(2) 一般情况下要改61处文件名 这里给大家提供一个批量修改文件名的命令,防止人为造成的编译find -type f | grep cmcc| xargs rename ‘s/cmcc_lte_hd720/tl_lte_hd720_Italian/’参数为筛选选条件 第二个参数为需要替换的部分 第三个参数为替换成的部分

二、init 动画

@2.1 第二个开机动画的播放过程

第二个开机动画是在init进程开启时显示的图片,也就是在开启一系列系统进程的过程中显示。 init进程的入口函数main实现在文件system/core/init/init.cpp中,最终会调用console_init_action方法,代码如下:

static int console_init_action(const std::vector<:string>& args)

{

std::string console = property_get("ro.boot.console");

if (!console.empty()) {

console_name = "/dev/" + console;

}

int fd = open(console_name.c_str(), O_RDWR | O_CLOEXEC);

if (fd >= 0)

have_console = 1;

#ifdef MTK_INIT

else

ERROR("console_init: can't open %s\n", console_name.c_str());

#endif

close(fd);

fd = open("/dev/tty0", O_WRONLY | O_CLOEXEC);

if (fd >= 0) {

const char *msg;

msg = "\n"

"\n"

"\n"

"\n"

"\n"

"\n"

"\n" // console is 40 cols x 30 lines

"\n"

"\n"

"\n"

"\n"

"\n"

"\n"

"\n"

" A N D R O I D ";

write(fd, msg, strlen(msg));

close(fd);

}

显示第二个开机画面是通过调用函数load_565rle_image来实现的。在调用函数load_565rle_image的时候,指定的开机画面文件为INIT_IMAGE_FILE。INIT_IMAGE_FILE是一个宏,定义在system/core/init/init.h文件中,如下所示:

#define INIT_IMAGE_FILE "/initlogo.rle" , 即第二个开机画面的内容是由文件/initlogo.rle来指定的。如果文件/initlogo.rle不存在,或者在显示它的过程中出现异常,那么函数load_565rle_image的返回值就会等于-1,这时候函数console_init_action就以文本的方式来显示第二个开机画面,即向编号为0的控制台(/dev/tty0)输出“ANDROID”这7个字符。

@ 2.2 init 动画客制化

init logo的客制化与kenel logo的客制化相同,他对应logo文件夹下的fwvga_uboot.bmp。

三、第三个开机动画

制作开关机动画

3.1 开机动画的位置

system/media/bootanimation.zip,要修改开机动画就是修改bootanimation这个压缩文件。如果不存在该压缩包,使用原生自带的资源,其路径在system/framework/framework-res.apk/assets/images(android-logo-mask.png,android-logo-shine.png),但是比较难看,比较常见的就是“android”。所以要定制自己的开关机动画一般都是在system/media/目录下放置bootanimation.zip和shutanimation.zip.这里以开机动画为例,关机动画和开机动画其原理一样。

3.2 bootanimation.zip文件结构

bootanimation里面主要包含一个desc.txt以及N个文件夹。而文件夹里面放着的就是开机动画的图片资源。decs.txt的作用就是指导系统如何去执行开机动画。

desc.txt编写规范,例如开机动画需要用到2个文件夹,分别是folder1和folder2,开机的时候,先把folder1里面的图片都播放一遍,然后再循环播放folder2里面的文件,直到进入系统,decs.txt文档的内容如下:

320 480 12

p 1 0 folder1

p 0 0 folder2

320 480是代表屏幕的分辨率,12表示12帧每秒,简单地说12代表一秒钟播放12张图片;

p 1 0 part1:p就是play。1是播放一次,0是无限次。0代表阶段间隔帧数为0。folder1就是说,这条指令是针对folder1这个文件夹的;

p 0 0 part2:第一个0这里是代表循环播放,第二个0和上面第二条指令一样。folder2就是第二个文件夹。

总结规则如下:

第一条指令:[屏幕的分辨率] [播放频率]

第二条指令:[p] [播放次数] [间隔帧数] [文件夹]

第N条指令: 同上

3.3 压缩包

把需要用到的folder文件夹跟decs.txt打包成zip格式,必须是zip,不能是rar,且打包的时压缩方式选择“存储”模式。然后改名成为bootanimation.zip,最后将制作好的zip包push到/system/media目录下。

注意:bootanimation不能太大,一般最好不要超过3M。

@3.1 bootanimation的启动过程

第三个开机画面是由应用程序bootanimation来负责显示的。应用程序bootanimation在启动脚本system/core/rootdir/init.rc中被配置成了一个服务,如下所示:

service bootanim /system/bin/bootanimation

class core

user graphics

group graphics audio cw_access

disabled

oneshot

应用程序bootanimation的用户和用户组名称分别被设置为graphics。注意, 用来启动应用程序bootanimation的服务是disable的,即init进程在启动的时候,不会主动将应用程序bootanimation启动起来。当SurfaceFlinger服务启动的时候,它会通过修改系统属性ctl.start的值来通知init进程启动应用程序bootanimation,以便可以显示第三个开机画面,而当System进程将系统中的关键服务都启动起来之后,ActivityManagerService服务就会通知SurfaceFlinger服务来修改系统属性ctl.stop的值,以便可以通知init进程停止执行应用程序bootanimation,即停止显示第三个开机画面。接下来我们就分别分析第三个开机画面的显示过程和停止过程。

Zygote进程在启动的过程中,会将System进程启动起来,System进程在启动的过程中,会调用SurfaceFlinger类的静态成员函数instantiate来启动SurfaceFlinger服务。Sytem进程在启动SurfaceFlinger服务的过程中,首先会创建一个SurfaceFlinger实例,然后再将这个实例注册到Service Manager中去。在注册的过程,前面创建的SurfaceFlinger实例会被一个sp指针引用。从前面Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析一文可以知道,当一个对象第一次被智能指针引用的时候,这个对象的成员函数onFirstRef就会被调用。由于SurfaceFlinger重写了父类RefBase的成员函数onFirstRef,因此,在注册SurfaceFlinger服务的过程中,将会调用SurfaceFlinger类的成员函数onFirstRef。在调用的过程,就会创建一个线程来启动第三个开机画面。

SurfaceFlinger是在framework/native/services/surfaceflinger/Main_surfaceflinger.cpp 被启动的,首先会执行init方法,然后自行run方法,代码如下:

// initialize before clients can connect

flinger->init();

// publish surface flinger

sp sm(defaultServiceManager());

sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);

// publish GpuService

sp gpuservice = new GpuService();

sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);

// run surface flinger in this thread

flinger->run();

在framework/native/services/surfaceflinger/SurfaceFlinger.cpp下,init()会方法的最后执行startBootAnim()

void SurfaceFlinger::init() {

ALOGI( "SurfaceFlinger's main thread ready to run. "

"Initializing graphics H/W...");

HAL_PIXEL_FORMAT_RGBA_8888);

......

// set initial conditions (e.g. unblank default device)

initializeDisplays();

// start boot animation

startBootAnim();

ALOGV("Done initializing");

}

startBootAnim()方法代码如下,它调用函数property_set来将系统属性“ctl.start”的值设置为“bootanim”,表示要将应用程序bootanimation启动起来,以便可以显示第三个开机画面。

void SurfaceFlinger::startBootAnim() {

#ifdef MTK_AOSP_ENHANCEMENT

// dynamic disable/enable boot animation

checkEnableBootAnim();

#else

// start boot animation

property_set("service.bootanim.exit", "0");

property_set("ctl.start", "bootanim");

#endif

}

当系统属性发生改变时,init进程就会接收到一个系统属性变化通知,这个通知最终是由在init进程中的函数handle_property_set_fd来处理的。 函数handle_property_set_fd实现在文件system/core/init/property_service.c中,如下所示:

static void handle_property_set_fd()

{

prop_msg msg;

int s;

int r;

struct ucred cr;

struct sockaddr_un addr;

socklen_t addr_size = sizeof(addr);

socklen_t cr_size = sizeof(cr);

char * source_ctx = NULL;

struct pollfd ufds[1];

const int timeout_ms = 2 * 1000; /* Default 2 sec timeout for caller to send property. */

int nr;

......

switch(msg.cmd) {

case PROP_MSG_SETPROP:

msg.name[PROP_NAME_MAX-1] = 0;

msg.value[PROP_VALUE_MAX-1] = 0;

if (!is_legal_property_name(msg.name, strlen(msg.name))) {

ERROR("sys_prop: illegal property name. Got: \"%s\"\n", msg.name);

close(s);

return;

}

getpeercon(s, &source_ctx);

if(memcmp(msg.name,"ctl.",4) == 0) {

// Keep the old close-socket-early behavior when handling

// ctl.* properties.

close(s);

if (check_control_mac_perms(msg.value, source_ctx, &cr)) {

#ifdef MTK_INIT

INFO("[PropSet]: pid:%u uid:%u gid:%u %s %s\n", cr.pid, cr.uid, cr.gid, msg.name, msg.value);

#endif

handle_control_message((char*) msg.name + 4, (char*) msg.value);

} else {

ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n",

msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid);

}

} else {

......

}

}

android+动画打包命令,Android 开机动画客制化相关推荐

  1. 完成谷歌Android设置向导,Android RRO机制的运用-----google开机向导客制化

    上周五的时候领导分了一个任务,客户让在google开机向导里面增加一页,首先就想到了android的Overlay,然后网上搜了下,发下有很多人写了这方面的技术.而且写的都还不错,所以本篇只当记录作用 ...

  2. android开机动画视频教程,【Android开机动画制作教程】开机动画文件组成及其详解释疑!...

    [开机动画位置] 安卓原版系统开机动画位置: system/media/bootanimation.zip或者data/local/bootanimation.zip 这两处的区别在于动画放在syst ...

  3. Android修改kernel logo和开机动画(android)

    一.uboot 开机logo 1.安装图片工具 # sudo apt-get install netpbm2.生成logo脚本 //make-uboot-logo.sh #!/bin/sh #1.ub ...

  4. MTK Android 13平台开关机动画铃声客制化

    MTK Android 13平台开关机动画铃声客制化 Android T和S的差异很大 主要是MtkShutdownThread.java和ShutdownThread.java差异 未完,待更新,填 ...

  5. Android 系统序列号从哪里来,以及客制化序列号

    Android 系统序列号从哪里来,以及客制化序列号 系统获取序列号过程 客制化序列号 系统获取序列号过程 Android系统的SN号,实际是从"cmdline"里面的" ...

  6. Android 手机按键客制化详解

    在Android 中会有以下5个按键(Back.Home.Menu.Power.Volume)与用户进行交互,Framework 层中实现按键功能,因此,从手机系统定制的角度,可以满足客户的客制化要求 ...

  7. Android 信号格客制化问题处理

    [Android Q] 信号强度客制化代码位置: NR(5G) CellSignalStrengthNr.java updateLevel() LTE MtkSignalStrength.java u ...

  8. Android实现客制化系统apk在线签名

    目录 一.基线代码签名key 二.如何生成自定义的签名pk8 .x509.pem 签名文件 三.如何使用签名key对apk进行重新签名 四.大厂商为了安全,使用自定义签名方式,而不采用原生的签名方式 ...

  9. Android 11.0 充电指示灯红绿显示简单客制化

    客制化充电指示灯的文章在网上也有不少了,项目的需求是在百分百情况下量绿灯,其它情况下都是红灯,这里简单记录下在Android11,kernel-4.19版本下的修改内容,也给有相关需求的各位提供下思路 ...

最新文章

  1. c语言xml序列化,C# XML和实体类之间相互转换(序列化和反序列化)
  2. Android数据存储(三)——SQLite
  3. 关于写代码的几个看法
  4. 关于synchronize与lock的区别
  5. 计算机网络 | 网络层 :IP协议详解
  6. ArrayList和Vector的异同
  7. /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.17' not found 解决办法
  8. c form画直线_新手教程跟我一起画儿童裤子裁剪图
  9. 好的设计善于利用PSD模板,轻松搞定促销海报!
  10. Linux C编程Makefile编写初步-转
  11. [转]:vue-cli3.0配置详解
  12. 【数据库】sql2008卸载和默认实例的删除
  13. 博士申请 | 澳门大学张一博教授课题组招收计算机视觉方向全奖博士生
  14. 如何让win7像win10一样漂亮-win7美化
  15. AspNetPager 存储过程
  16. 好未来表格识别大赛 | 获奖名单新鲜出炉!
  17. U3D记腾讯面试经历
  18. 第十五周博客作业西北师范大学|李晓婷
  19. HTML5 table表格合并单元格和合并边框
  20. USB转串口驱动分析(一)

热门文章

  1. 虚拟服务器面板,主流的虚拟主机控制面板有哪些(一)
  2. 基于Python下Tkinter实现学生选课管理系统
  3. 带你一起学习C语言语法
  4. anaconda navigator启动时一直卡在 loading applications 页面(已解决)
  5. mht 转换 html java,使用java将网页保存为mht格式(2)
  6. android sdk 需要下载安装哪些
  7. 程序员基础能力系列(1)——vim快捷键总结
  8. opencv的java api_OpenCV Java开发教程
  9. 2018年c++达内从入门到精通全套教程
  10. ppt怎么转pdf?经验分享