失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Android开机动画流程(一)——启动阶段

Android开机动画流程(一)——启动阶段

时间:2019-07-18 18:57:44

相关推荐

Android开机动画流程(一)——启动阶段

(1)前述

Android系统在启动的过程中,最多可以出现四个画面,每一个画面都用来描述一个不同的启动阶段。

Linux uboot显示(静态)Linux 内核的启动画面(静态)init 进程的启动画面(静态)BootAnimation启动动画(动态)

无论是哪一个画面,它们都是在一个称为帧缓冲区(frame buffer,简称fb)的硬件设备上进行渲染的。接下来,我们就单独分析BootAnimation是如何开始显示的。

(2)BootAnimation启动阶段

(A)bootanimation启动概述

开机动画是由应用程序bootanimation来负责显示的,先看一下其rc文件。

//frameworks/base/cmds/bootanimation/bootanim.rcservice bootanim /system/bin/bootanimationclass core animationuser graphicsgroup graphics audiodisabled //系统启动时,不会自动启动bootanimationoneshot //只启动一次ioprio rt 0task_profiles MaxPerformance

应用程序bootanimation的用户和用户组名称分别被设置为graphics。注意, 用来启动应用程序bootanimation的服务是disable的,即init进程在启动的时候,不会主动将应用程序bootanimation启动起来。

SurfaceFlinger 服务启动的过程中会修改系统属性"ctl.start"的值以通知init进程启动bootanim来显示开机动画。当系统关键服务启动完毕后会由AMS通知SurfaceFlinger修改系统属性"ctl.stop"来通知init进程停止执行bootanim关闭动画。

(B)SurfaceFlinger如何启动bootAnimation

首先来看一下surfaceflinger.rc文件

//frameworks/native/services/surfaceflinger/surfaceflinger.rcservice surfaceflinger /system/bin/surfaceflingerclass core animationuser systemgroup graphics drmrpc readproccapabilities SYS_NICEonrestart restart zygotetask_profiles HighPerformancesocket pdx/system/vr/display/clientstream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0socket pdx/system/vr/display/vsyncstream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0

SurfaceFlinger服务的入口在下面的main_surfaceflinger.cpp中,我们查看它的main函数。

//frameworks/native/services/surfaceflinger/main_surfaceflinger.cppint main(int, char**) {// When SF is launched in its own process, limit the number of// binder threads to 4.ProcessState::self()->setThreadPoolMaxThreadCount(4);// start the thread poolsp<ProcessState> ps(ProcessState::self());ps->startThreadPool();// instantiate surfaceflingersp<SurfaceFlinger> flinger = new SurfaceFlinger();// initialize before clients can connectflinger->init(); //我们主要看这里// run in this threadflinger->run();return 0;}

主要工作就是新建一个SurfaceFlinger对象,然后调用其中的init函数,最后调用run函数。

//frameworks/native/services/surfaceflinger/SurfaceFlinger.cppsp<StartPropertySetThread> mStartPropertySetThread;void SurfaceFlinger::init() {ALOGI( "SurfaceFlinger's main thread ready to run. ""Initializing graphics H/W...");Mutex::Autolock _l(mStateLock);//...if (mStartPropertySetThread->Start() != NO_ERROR) {ALOGE("Run StartPropertySetThread failed!");}ALOGV("Done initializing");}

//frameworks/native/services/surfaceflinger/StartPropertySetThread.cppstatus_t StartPropertySetThread::Start() {return run("SurfaceFlinger::StartPropertySetThread", PRIORITY_NORMAL);}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 immediatelyreturn false;}

这里将系统属性"service.bootanim.exit"设置为"0",并将"ctl.start"设置为"bootanim"。

当系统属性发生改变时,init进程就会接收到一个系统属性变化通知,这个通知最终是由在init进程中的函数handle_property_set_fd来处理的,具体中间流程是如何运行的,可以参考另外一篇文章Android系统设置属性详解。

(C)bootAnimation启动

从前面的内容可以知道,名称等于"bootanim"的服务所对应的应用程序为/system/bin/bootanimation,应用程序入口函数的实现在frameworks/base/cmds/bootanimation/Bootanimation_main.cpp中。

//frameworks/base/cmds/bootanimation/bootanimation_main.cppint main(){bool noBootAnimation = bootAnimationDisabled();ALOGI_IF(noBootAnimation, "boot animation disabled");if (!noBootAnimation) {//启动一个Binder线程池sp<ProcessState> proc(ProcessState::self());ProcessState::self()->startThreadPool();// create the boot animation object (may take up to 200ms for 2MB zip)sp<BootAnimation> boot = new BootAnimation(audioplay::createAnimationCallbacks());waitForSurfaceFlinger();boot->run("BootAnimation", PRIORITY_DISPLAY);ALOGV("Boot animation set up. Joining pool.");IPCThreadState::self()->joinThreadPool();}return 0;}bool bootAnimationDisabled() {char value[PROPERTY_VALUE_MAX];property_get("debug.sf.nobootanimation", value, "0");if (atoi(value) > 0) {return true;}property_get("ro.boot.quiescent", value, "0");return atoi(value) > 0;}

首先检查系统属性“debug.sf.nobootnimaition”的值是否不等于0。如果不等于的话,那么接下来就会启动一个Binder线程池,并且创建一个BootAnimation对象。这个Binder线程用于同SurfaceFlinger服务通信。

接着我们看看BootAnimation类的声明:

//frameworks/base/cmds/bootanimation/BootAnimation.hclass BootAnimation : public Thread, public IBinder::DeathRecipient {public: BootAnimation(); virtual~BootAnimation(); ....... private: virtual bool threadLoop(); virtual status_t readyToRun(); virtual void onFirstRef(); virtual void binderDied(const wp<IBinder>& who); status_t initTexture(Texture* texture, AssetManager& asset, const char* name); status_t initTexture(const Animation::Frame& frame); bool android(); bool movie(); Animation* loadAnimation(const String8&);bool playAnimation(const Animation&);void releaseAnimation(Animation*) const;bool parseAnimationDesc(Animation&);bool preloadZip(Animation &animation);void findBootAnimationFile();bool findBootAnimationFileInternal(const std::vector<std::string>& files);bool preloadAnimation();void checkExit();};

BootAnimation类继承了Thread类和IBinder::DeathRecipient类,其中几个重要的函数说明如下:

onFirstRef()—— 属于其父类RefBase,该函数在强引用sp新增引用计数時调用,就是当有sp包装的类初始化的时候调用;binderDied() ——当对象死掉或者其他情况导致该Binder结束时,就会回调binderDied()方法;readyToRun() ——Thread执行前的初始化工作;threadLoop() ——每个线程类都要实现的,在这里定义thread的执行内容。这个函数如果返回true,且没有调用requestExit(),则该函数会再次执行;如果返回false,则threadloop中的内容仅仅执行一次,线程就会退出。

其他函数简述如下:

android()——显示系统默认的开机画面;movie()——显示用户自定义的开机动画;loadAnimation(const String8&)——加载动画;playAnimation(const Animation&)——播放动画;checkExit()——检查是否退出动画;

BootAnimation类间接地继承了RefBase类,并且重写了RefBase类的成员函数onFirstRef,当一个BootAnimation对象第一次被智能指针引用时,这个BootAnimation对象的成员函数onFirstRef就会被调用。

mSession = new SurfaceComposerClient();void BootAnimation::onFirstRef() {status_t err = mSession->linkToComposerDeath(this);ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));}

mSession是BootAnimation类的一个成员变量,它的类型为SurfaceComposerClient,是用来和SurfaceFlinger执行Binder进程间通信的,它是在BootAnimation类的构造函数中创建的。

由于BootAnimation类引用了SurfaceFlinger服务,当SurfaceFlinger服务意外死亡时,BootAnimation类就需要得到通知,这是通过调用成员变量mSession的成员函数linkToComposerDeath来注册SurfaceFlinger服务的死亡接收通知来实现的。

BootAnimation类继承了Thread类,当BootAnimation类的成员函数onFirstRef调用了父类Thread的成员函数run之后,系统就会创建一个线程,这个线程在第一次运行之前,会调用BootAnimation类的成员函数readyToRun来执行一些初始化工作,后面再调用BootAnimation类的成员函数threadLoop来显示开机画面。

如果觉得《Android开机动画流程(一)——启动阶段》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。