前言

在上篇文章【Android从上电到加载launcher,都发生了啥】中,简单介绍了Android系统从上电到加载launcher的流程,但比较粗略,特别是init之后,开机动画如何启动,又如何结束的,丝毫没有涉及,这篇文章就来好好说说。

概述

先放上一张流程图,需要说明的是,下图中init所做的事不止下图所展示的,这里只是画出跟开机动画相关的流程。

系统上电后,通过内置的rom_code将uboot映像从flash中加载到内存中运行,之后跳转到uboot执行,做一些硬件外设参数的初始化工作,然后从flash中加载kernel到内存中运行并跳转到kernel执行。

init进程是kernel的第一个进程,也是Android系统的第一个进程。而跟开机动画有关的,主要是init中做的两件事,一件事是启动surfaceflinger进程,开机动画的启动就是在这里触发;另外一件事是启动zygote进程,zygote进程起来后就fork出了system_server,system_server主要是启动系统服务,如AMS,WMS,PMS等。等待一些关键服务ready后,就开始加载launcher,launcher加载好就触发结束开机动画的操作,从而进入到launcher界面。

如上图片可查看原图:

https://note.youdao.com/ynoteshare1/index.html?id=09bc4482a051436bde4127b73ea346b0&type=note

bootanimation的开启

开机动画是在surfaceflinger中触发,而surfaceflinger进程是在init.rc中启动的,如下:

service surfaceflinger /system/bin/surfaceflinger

这里需要说明的是,在高版本的Android上,如AndroidP,surfaceflinger进程并不是直接在init.rc文件中启动的,而是通过Android.bp文件去包含启动surfaceflinger.rc文件,然后在该文件中再去启动surfaceflinger:

AOSP/frameworks/native/services/surfaceflinger/Android.bp...init_rc: ["surfaceflinger.rc"],AOSP/frameworks/native/services/surfaceflinger/surfaceflinger.rc

surfaceflinger启动了,就会跑到它的main函数:

AOSP/frameworks/native/services/surfaceflinger/main_surfaceflinger.cppint main(int, char**) {...// instantiate surfaceflingersp flinger = new SurfaceFlinger();flinger->init();flinger->run();}

这里创建一个SurfaceFlinger实例,然后执行了init(),看看它的实现:

AOSP/frameworks/native/services/surfaceflinger/surfaceflinger.cppvoid SurfaceFlinger::init() {mStartPropertySetThread = new StartPropertySetThread();mStartPropertySetThread->Start();

surfaceflinger完成初始化后,会直接实例化一个StartPropertySetThread,然后启动,我们来看下:

bool StartPropertySetThread::threadLoop() {// Set property service.sf.present_timestamp, consumer need check its readinessproperty_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");// Clear BootAnimation exit flagproperty_set("service.bootanim.exit", "0");// Start BootAnimation if not startedproperty_set("ctl.start", "bootanim");// Exit immediately#ifdef MTK_BOOT_PROFSurfaceFlinger::bootProf(1);#endifreturn false;

这里设置属性【service.bootanim.exit】并采用【ctl.start】的方式启动开机动画:

service bootanim /system/bin/bootanimation

在这之后,开机动画就会启动,由bootanimation进程实现具体动画播放。

bootanimation的实现流程

先看下bootanimation进程的入口:

AOSP/frameworks/base/cmds/bootanimation_main.cppint main(){setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);bool noBootAnimation = bootAnimationDisabled();ALOGI_IF(noBootAnimation, "boot animation disabled");if (!noBootAnimation) {sp proc(ProcessState::self());ProcessState::self()->startThreadPool();waitForSurfaceFlinger();// create the boot animation objectsp boot = new BootAnimation(new AudioAnimationCallbacks());ALOGV("Boot animation set up. Joining pool.");IPCThreadState::self()->joinThreadPool();}ALOGV("Boot animation exit");return 0;

new了一个BootAnimation实例,然后创建了一个binder线程池,用于显示动画时,与surfaceflinger进程通信用。接下来看看BootAnimation的实现:

AOSP/frameworks/base/cmds/bootanimation.cppBootAnimation::BootAnimation(sp callbacks): Thread(false), mClockEnabled(true), mTimeIsAccurate(false),mTimeFormat12Hour(false), mTimeCheckThread(NULL), mCallbacks(callbacks) {mSession = new SurfaceComposerClient();

这里创建了SurfaceComposerClient,用于与surfaceflinger通讯。接下来就到了onFirstRef:

void BootAnimation::onFirstRef() {status_t err = mSession->linkToComposerDeath(this);ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));if (err == NO_ERROR) {run("BootAnimation", PRIORITY_DISPLAY);

这里先注册surfaceflinger的死亡消息通知书【linkToComposerDeath】,只要surfaceflinger挂掉了,bootanimation进程就会收到通知,从而执行如下代码:

void BootAnimation::binderDied(const wp&)// woah, surfaceflinger died!ALOGD("SurfaceFlinger died, exiting...");// calling requestExit() is not enough here because the Surface code// might be blocked on a condition variable that will never be updated.kill( getpid(), SIGKILL );requestExit();

直接退出,等待surfaceflinger的下一次重启,如果还有来生的话。

onFirstRef在创建了死亡通知书后,还做了一件事,那就是run bootanimation,个中细节不在这里列出,bootanimation重写了readyToRun和threadLoop,我们直接看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);eglReleaseThread();IPCThreadState::self()->stopProcess();return r;

这里会根据有无定制的开机动画包,如果没有,则默认播放Android的那个经典动画,如果有,则进入movie播放开机动画:

bool BootAnimation::movie()playAnimation(*animation);bool BootAnimation::playAnimation(const Animation& animation)//代码太长,就不贴出了,主要就是做动画播放的相关代码checkExit();

开机动画开始播放了,那何时才结束播放呢?答案在checkExit方法中:

static const char EXIT_PROP_NAME[] = "service.bootanim.exit";void BootAnimation::checkExit() {// Allow surface flinger to gracefully request shutdownchar value[PROPERTY_VALUE_MAX];property_get(EXIT_PROP_NAME, value, "0");int exitnow = atoi(value);if (exitnow) {requestExit();mCallbacks->shutdown();

这里会一直检测【service.bootanim.exit】的值,当属性值为1的时候,则开机动画会requestExit,从而结束开机动画。那是谁给【service.bootanim.exit】的属性值设置为1呢?

bootanimation的结束

init启动zygote进程之后,由zygote孵化出了system_server,然后system_server启动了各种各种的系统所需的服务,其中就有AMS,AMS启动并ready后,会执行startHomeActivityLocked:

public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {startHomeActivityLocked(currentUserId, "systemReady");boolean startHomeActivityLocked(int userId, String reason) {Intent intent = getHomeIntent();ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);final String myReason = reason + ":" + userId + ":" + resolvedUserId;mActivityStartController.startHomeActivity(intent, aInfo, myReason);

launcher在这里开始加载启动,在launcher的主线程处于空闲时,就会向ActivityManagerService发送一个activityIdle的消息:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.javapublic final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {ActivityRecord r =mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,false /* processPausingActivities */, config);

这里通过activityIdleInternalLocked获取到ActivityRecord实例,我们看看具体实现:

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.javafinal ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,boolean processPausingActivities, Configuration config) {....//Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);if (isFocusedStack(r.getStack()) || fromTimeout) {booting = checkFinishBootingLocked();

这里会检测开机是否结束:

private boolean checkFinishBootingLocked() {final boolean booting = mService.mBooting;boolean enableScreen = false;mService.mBooting = false;if (!mService.mBooted) {mService.mBooted = true;enableScreen = true;if (booting || enableScreen) {mService.postFinishBooting(booting, enableScreen);return booting;

这里会直接进入到postFinishBooting方法中执行:

//AMSvoid postFinishBooting(boolean finishBooting, boolean enableScreen) {mHandler.sendMessage(mHandler.obtainMessage(FINISH_BOOTING_MSG,finishBooting ? 1 : 0, enableScreen ? 1 : 0));

这里直接发一条消息【FINISH_BOOTING_MSG】,我们看看具体handler的处理:

case FINISH_BOOTING_MSG: {if (msg.arg1 != 0) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "FinishBooting");finishBooting();Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);if (msg.arg2 != 0) {enableScreenAfterBoot();break;

最终执行到了enableScreenAfterBoot方法:

void enableScreenAfterBoot() {mWindowManager.enableScreenAfterBoot();

这里调用了WMS的方法【enableScreenAfterBoot】,我们跳入看看:

public void enableScreenAfterBoot() {performEnableScreen();private void performEnableScreen() {if (!mBootAnimationStopped) {Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);// stop boot animation// formerly we would just kill the process, but we now ask it to exit so it// can choose where to stop the animation.SystemProperties.set("service.bootanim.exit", "1");mBootAnimationStopped = true;

到了这里,最终通过设置【service.bootanim.exit】的值,stop掉了开机动画,接着来的就是发出了开机广播。

结语

本篇文章简单介绍了开机动画从开始到结束的流程,涉及到的surfaceflinger进程,这个是开机动画能够显示的基础,如果它挂掉,开机动画也活不了。还有AMS等服务,在launcher加载完后,就设置属性【service.bootanim.exit】,结束开机动画,从而进入到launcher的界面。

互动

如果文章存在错误描述,可直接评论留言,一起探讨!

举报/反馈

android的启动动画,Android系统开机动画的一生相关推荐

  1. 修改android系统开机动画

    本文转载自:http://blog.csdn.net/u012301841/article/details/51598115 修改android系统开机动画 转载于:https://www.cnblo ...

  2. 安卓系统开机动画制作

    安卓原生的开机动画默认是"Android"的字样,并且会闪动,仔细阅读源码,其实可以发现它并不是一个zip格式的压缩包,而且也找不到bootanimation.zip这个文件,因为 ...

  3. android开机动画多长时间_Android系统开机动画的一生

    前言 在上篇文章[Android从上电到加载launcher,都发生了啥]中,简单介绍了Android系统从上电到加载launcher的流程,但比较粗略,特别是init之后,开机动画如何启动,又如何结 ...

  4. android开机动画修改,Android系统 开机动画修改 + 自动替换脚本

    1.准备 多帧图片PNG-24格式 adb 环境 2.bootanimation 开机包制作 1 在 Widows 环境中建立文件夹:bootanimation 2 在bootanimation文件夹 ...

  5. Android制作并替换系统开机动画bootanimation.zip(需root)

    一.Android默认开机动画是显示"android"字样的图片,想要替换掉"android",需要用到bootanimation.zip. 二.原生Andro ...

  6. Android系统 开机动画修改 + 自动替换脚本

    1.准备 多帧图片PNG-24格式 adb 环境 2.bootanimation 开机包制作 1 在 Widows 环境中建立文件夹:bootanimation 2 在bootanimation文件夹 ...

  7. android默认开机动画,修改安卓开机动画(除了部分系统 如MIUI等)

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 这技术已经很久了,但还是忍不住搬运了一下. 出处是百度的,很久很久以前玩手机在百度上学的 我这里说的开机动画是指开机的第二屏 开机动画可以在下载的rom里 ...

  8. android更换开机动画,修改安卓开机动画(除了部分系统 如MIUI等)

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 这技术已经很久了,但还是忍不住搬运了一下. 出处是百度的,很久很久以前玩手机在百度上学的 我这里说的开机动画是指开机的第二屏 开机动画可以在下载的rom里 ...

  9. android直到开机动画播放完,开机动画播放完进入launcher黑屏2s

    当修改了开机动画的播放次数后,例如由无限循环播放改为只播放一次,开机动画播放完进入launcher黑屏几秒. 增加一句getWindow().setBackgroundDrawableResource ...

最新文章

  1. 【Java小工匠聊密码学】-密码学--综述
  2. electron 打包把node代理服务打包进去_用 Node.js 官方镜像打包一个 express 服务
  3. jQuery find() 方法的使用总结
  4. Sino Global Capital CEO:Robinhood暂停GME股票交易凸显了DeFi的重要性
  5. 使用Word 2007写blog
  6. 安装配置管理 之 安装和配置 JPackage Java
  7. Python:每日一题008
  8. 转义字符html识别吗,HTML转义字符对照表
  9. python零基础教学plc_编程零基础应当如何开始学习 Python?
  10. python图像的手绘效果代码_python实现手绘效果图
  11. PPT文件太大了怎么压缩
  12. Android流式布局控件
  13. 谷歌浏览器无法使用谷歌翻译解决办法
  14. 手把手教你集成华为Image Kit图像裁剪功能
  15. SVN强制编写注释才能提交,提交中不允许删除文件操作。
  16. 【C语言】(百合花)水仙花数的算法思考习题4-6 水仙花数
  17. EXCEL单元格内多个姓名如何统计个数
  18. 动漫免费在线观看,实时更新,资源全
  19. eclipse启动很慢调优
  20. 微信支付结算费率怎么降低至0.2~0.35操作方法

热门文章

  1. 微信公众平台测试帐号申请网址
  2. filecoin benchmarks v25 GeForce GTX 1080 Ti
  3. Empress .... 概念
  4. [转]马化腾:如何从“较好”到“最好”
  5. 常微分方程(2):一阶线性微分方程
  6. #Reading Paper# 【序列推荐综述】IJCAI‘19:Sequential Recommender Systems: Challenges, Progress and Prospects
  7. 申请转正自评php开发,PHP开发工程师岗位自我评价怎么写
  8. 网上舆情分析报告写作框架及六大技巧
  9. gm 1 n 模型matlab,灰色预测模型GM1,n模型的matlab源...
  10. 二、谷歌阻止苹果,谁来阻止谷歌