Android 9.0 开关机动画流程分析

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的情况,如下:

Android 9.0 开关机动画流程分析_第1张图片

参考资料:https://blog.csdn.net/wangjun7121/article/details/88141376

你可能感兴趣的:(android系统)