Android开机动画流程的启动主要是在Surfaseflinger里面完成的,具体代码如下:
/frameworks/native/services/surfaceflinger/StartPropertySetThread.cpp
32 bool StartPropertySetThread::threadLoop() {
33 // Set property service.sf.present_timestamp, consumer need check its readiness
34 property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");
35 // Clear BootAnimation exit flag
36 property_set("service.bootanim.exit", "0");
37 // Start BootAnimation if not started
38 property_set("ctl.start", "bootanim");
通过property_set("ctl.start", "bootanim");启动bootanim服务,启动服务的过程不做详细介绍,可以参考链接:
https://blog.csdn.net/zcyxiaxi/article/details/79159094
bootanim服务会启动开机动画的二进制执行文件,代码目录位于
/frameworks/base/cmds/bootanimation/bootanim.rc
1 service bootanim /system/bin/bootanimation
2 class core animation
3 user graphics
4 group graphics audio
5 disabled
6 oneshot
7 writepid /dev/stune/top-app/tasks
主要执行代码在/frameworks/base/cmds/bootanimation/BootAnimation.cpp文件中。
bool BootAnimation::threadLoop()
358 {
359 bool r;
360 // We have no bootanimation file, so we use the stock android logo
361 // animation.
362 if (mZipFileName.isEmpty()) {
363 r = android();
364 } else {
365 r = movie();
366 }
该方法判断mZipFileName内容是否为空,如果为空的话,就会执行android()方法走原生开机动画流程,原生开机动画是通过在界面上加载字符的方式实现的, 如果不为空的话就会走如下流程:
bool BootAnimation::movie()
817 {
818 Animation* animation = loadAnimation(mZipFileName);
..........
playAnimation(*animation);
.........
881 releaseAnimation(animation);
882
883 if (clockFontInitialized) {
884 glDeleteTextures(1, &animation->clockFont.texture.name);
885 }
886
887 return false;
888 }
先通过loadAnimation(mZipFileName)加载开机动画资源,然后playAnimation(*animation);播放开机动画,播放完以后通过releaseAnimation(animation);释放资源。
loadAnimation方法主要是传递资源路径,然后调用parseAnimationDesc方法处理动画资源,内容如下:
648 bool BootAnimation::parseAnimationDesc(Animation& animation)
649 {
650 String8 desString;
651
652 if (!readFile(animation.zip, "desc.txt", desString)) {//读取zip格式中的desc.txt内容并将值放到desString中,如果读取失败直接返回false。
653 return false;
654 }
655 char const* s = desString.string();
656
657 // Parse the description file
658 for (;;) {//for循环用来按行去读desc.txt里面的内容。
659 const char* endl = strstr(s, "\n");//搜索s字符串里面的话换行符,如果没有换行符的话直接返回NULL,搜索到换行符以后将返回换行符开始到字符串结尾的内容。
660 if (endl == NULL) break;
661 String8 line(s, endl - s);
662 const char* l = line.string();
663 int fps = 0;
664 int width = 0;
665 int height = 0;
666 int count = 0;
667 int pause = 0;
668 char path[ANIM_ENTRY_NAME_MAX];
669 char color[7] = "000000"; // default to black if unspecified
670 char clockPos1[TEXT_POS_LEN_MAX + 1] = "";
671 char clockPos2[TEXT_POS_LEN_MAX + 1] = "";
672 //将资源文件内读到的配置文件赋值到animation中。
673 char pathType;
674 if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) {
675 // ALOGD("> w=%d, h=%d, fps=%d", width, height, fps);
676 animation.width = width;
677 animation.height = height;
678 animation.fps = fps;
679 } else if (sscanf(l, " %c %d %d %s #%6s %16s %16s",
680 &pathType, &count, &pause, path, color, clockPos1, clockPos2) >= 4) {
681 //ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPos1=%s, clockPos2=%s",
682 // pathType, count, pause, path, color, clockPos1, clockPos2);
683 Animation::Part part;
684 part.playUntilComplete = pathType == 'c';
685 part.count = count;
686 part.pause = pause;
687 part.path = path;
688 part.audioData = NULL;
689 part.animation = NULL;
690 if (!parseColor(color, part.backgroundColor)) {
691 ALOGE("> invalid color '#%s'", color);
692 part.backgroundColor[0] = 0.0f;
693 part.backgroundColor[1] = 0.0f;
694 part.backgroundColor[2] = 0.0f;
695 }
696 parsePosition(clockPos1, clockPos2, &part.clockPosX, &part.clockPosY);
697 animation.parts.add(part);
698 }
699 else if (strcmp(l, "$SYSTEM") == 0) {
700 // ALOGD("> SYSTEM");
701 Animation::Part part;
702 part.playUntilComplete = false;
703 part.count = 1;
704 part.pause = 0;
705 part.audioData = NULL;
706 part.animation = loadAnimation(String8(SYSTEM_BOOTANIMATION_FILE));
707 if (part.animation != NULL)
708 animation.parts.add(part);
709 }
710 s = ++endl;//每次循环删除字符串第一行
711 }
712
713 return true;
714 }
文件desc.txt的内容格式如下面的例子所示:
600 480 24
p 1 0 part1
p 0 10 part2
第一行的三个数字分别表示开机动画在屏幕中的显示宽度、高度以及帧速(fps)。剩余的每一行都用来描述一个动画片断,
这些行必须要以字符“p”来开头,后面紧跟着两个数字以及一个文件目录路径名称。第一个数字表示一个片断的循环显示次数,
如果它的值等于0,那么就表示无限循环地显示该动画片断。第二个数字表示每一个片断在两次循环显示之间的时间间隔。这个时间间隔是以一个帧的时间为单位的。文件目录下面保存的是一系列png文件,这些png文件会被依次显示在屏幕中。
以上面这个desct.txt文件的内容为例:
它描述了一个大小为600 x 480的开机动画,动画的显示速度为24帧每秒。这个开机动画包含有两个片断 part1 和 part2。片断part1只显示一次,它对应的png图片保存在目录part1中。片断part2无限循环地显示,其中,每两次循环显示的时间间隔为10 x (1 / 24)秒,它对应的png图片保存在目录part2中。
注意:开机动画资源制作成zip包的时候,压缩方式要注意一下,必须用存储的方式进行压缩,其他方式都不行,不然会导致无法正确读取desc.txt的资源而出现开机动画crash的情况,如下:
参考资料:https://blog.csdn.net/wangjun7121/article/details/88141376