http://www.mamicode.com/info-detail-399016.html

android开机动画启动流程

时间: 2014-12-31 18:34:49

标签:


从android的Surface Flinger服务启动分析知道,开机动画是在SurfaceFlinger实例通过调用startBootAnim()启动的。

下面我们就一起学习BootAnim是如何启动和结束的,我精读代码前都喜欢先描出框架图,以此图为基础再去研读会达到事半功倍的效果。好吧,直接上图。


android开机动画启动流程_第1张图片



内核起来后会启动第一个进程,即init进程。

init进程会根据init.rc配置启动surfaceflinger进程。


[cpp] view plain copy
  1. servicesurfaceflinger/system/bin/surfaceflinger
  2. classmain
  3. usersystem
  4. groupgraphicsdrmrpc
  5. onrestartrestartzygote

surfaceflinger进程便启动了,跟着就会跑进程的main()函数。


frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp

[cpp] view plain copy
  1. intmain(intargc,char**argv){
  2. ....
  3. //instantiatesurfaceflinger
  4. sp<SurfaceFlinger>flinger=newSurfaceFlinger();//创建surfaceflinger服务实例
  5. ....
  6. flinger->init();
  7. //publishsurfaceflinger
  8. sp<IServiceManager>sm(defaultServiceManager());
  9. sm->addService(String16(SurfaceFlinger::getServiceName()),flinger,false);//注册到servicemanager里
  10. //runinthisthread
  11. flinger->run();//开跑
  12. return0;
  13. }

首先new一个SurfaceFlinger实例,然后init,然后run


frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

[cpp] view plain copy
  1. voidSurfaceFlinger::init(){
  2. ALOGI("SurfaceFlinger'smainthreadreadytorun."
  3. "InitializinggraphicsH/W...");
  4. .....
  5. //startbootanimation
  6. startBootAnim();//开始播放动画
  7. }

初始化graphics之后,就调用startBootAnim()播放开机动画。


[cpp] view plain copy
  1. voidSurfaceFlinger::startBootAnim(){
  2. //startbootanimation
  3. mBootFinished=false;
  4. property_set("service.bootanim.exit","0");//这个会有bootanimation进程周期检测,=1退出动画
  5. property_set("ctl.start","bootanim");//通过ctl.start命令启动bootanim
  6. }

把service.bootanim.exit属性设为0,这个属性bootanimation进程里会周期检查,=1时就退出动画,这里=0表示要播放动画。

后面通过ctl.start的命令启动bootanim进程,动画就开始播放了。


下面来到bootanimation的实现


frameworks/base/cmds/bootanimation/bootanimation_main.cpp

[cpp] view plain copy
  1. intmain(intargc,char**argv)
  2. {
  3. sp<ProcessState>proc(ProcessState::self());
  4. ProcessState::self()->startThreadPool();
  5. //createthebootanimationobject
  6. sp<BootAnimation>boot=newBootAnimation();//创建BootAnimation实例
  7. IPCThreadState::self()->joinThreadPool();//binder线程池,与surfaceflinger通信用的。
  8. }
  9. return0;
  10. }

new一个BootAnimation实例,然后建个binder线程池,因为BootAnimation在显示动画时要与SurfaceFlinger服务进程通信,所以要启个binder线程池。


frameworks/base/cmds/bootanimation/BootAnimation.cpp

[cpp] view plain copy
  1. BootAnimation::BootAnimation():Thread(false)
  2. {
  3. mSession=newSurfaceComposerClient();//创建一个对象
  4. }

创建实例时,构造函数就会被调用,new一个SurfaceComposerClient实例,他是用来与surfaceflinger通信的


[cpp] view plain copy
  1. voidBootAnimation::onFirstRef(){
  2. status_terr=mSession->linkToComposerDeath(this);//注册surfaceflinger死亡消息的通知书
  3. ALOGE_IF(err,"linkToComposerDeathfailed(%s)",strerror(-err));
  4. if(err==NO_ERROR){
  5. run("BootAnimation",PRIORITY_DISPLAY);//开跑
  6. }
  7. }


linkTocomposerDeath的作用是当surfaceflinger死掉是,BootAnimation就会得到通知。


如下,收到通知后就退出动画了,因为surfaceflinger都挂掉了,播放不了了。

[cpp] view plain copy
  1. voidBootAnimation::binderDied(constwp<IBinder>&who)
  2. {
  3. //woah,surfaceflingerdied!
  4. ALOGD("SurfaceFlingerdied,exiting...");
  5. //callingrequestExit()isnotenoughherebecausetheSurfacecode
  6. //mightbeblockedonaconditionvariablethatwillneverbeupdated.
  7. kill(getpid(),SIGKILL);//收到surfaceflinger死亡的消息,好吧自己也跟着去了。
  8. requestExit();
  9. }

另一个函数run()在BootAnimation的父类Thead里,用来创建一个线程并跑起来。


父类

system/core/libutils/Threads.cpp

[cpp] view plain copy
  1. status_tThread::run(constchar*name,int32_tpriority,size_tstack)
  2. {
  3. ...
  4. if(mCanCallJava){
  5. res=createThreadEtc(_threadLoop,//创建线程
  6. this,name,priority,stack,&mThread);
  7. }else{
  8. res=androidCreateRawThreadEtc(_threadLoop,
  9. this,name,priority,stack,&mThread);
  10. }
  11. ....
  12. }

创建_threadLoop线程

[cpp] view plain copy
  1. intThread::_threadLoop(void*user)
  2. {
  3. ....
  4. do{
  5. boolresult;
  6. if(first){
  7. first=false;
  8. self->mStatus=self->readyToRun();//这个函数被bootanimation重写了
  9. result=(self->mStatus==NO_ERROR);
  10. if(result&&!self->exitPending()){
  11. ...
  12. result=self->threadLoop();//这个函数被bootanimation重写了
  13. }
  14. }else{
  15. result=self->threadLoop();
  16. }
  17. ...
  18. return0;
  19. }

readyToRun函数实现

[cpp] view plain copy
  1. status_tBootAnimation::readyToRun(){
  2. mAssets.addDefaultAssets();
  3. sp<IBinder>dtoken(SurfaceComposerClient::getBuiltInDisplay(
  4. ISurfaceComposer::eDisplayIdMain));
  5. DisplayInfodinfo;
  6. status_tstatus=SurfaceComposerClient::getDisplayInfo(dtoken,&dinfo);
  7. if(status)
  8. return-1;
  9. charvalue[PROPERTY_VALUE_MAX];
  10. property_get("persist.panel.orientation",value,"0");
  11. intorient=atoi(value)/90;
  12. if(orient==eOrientation90||orient==eOrientation270){
  13. inttemp=dinfo.h;
  14. dinfo.h=dinfo.w;
  15. dinfo.w=temp;
  16. }
  17. RectdestRect(dinfo.w,dinfo.h);
  18. mSession->setDisplayProjection(dtoken,orient,destRect,destRect);
  19. //createthenativesurface
  20. sp<SurfaceControl>control=session()->createSurface(String8("BootAnimation"),
  21. dinfo.w,dinfo.h,PIXEL_FORMAT_RGB_565);
  22. SurfaceComposerClient::openGlobalTransaction();
  23. control->setLayer(0x40000000);
  24. SurfaceComposerClient::closeGlobalTransaction();
  25. sp<Surface>s=control->getSurface();
  26. //initializeopenglandegl
  27. constEGLintattribs[]={
  28. EGL_RED_SIZE,8,
  29. EGL_GREEN_SIZE,8,
  30. EGL_BLUE_SIZE,8,
  31. EGL_DEPTH_SIZE,0,
  32. EGL_NONE
  33. };
  34. EGLintw,h,dummy;
  35. EGLintnumConfigs;
  36. EGLConfigconfig;
  37. EGLSurfacesurface;
  38. EGLContextcontext;
  39. EGLDisplaydisplay=eglGetDisplay(EGL_DEFAULT_DISPLAY);
  40. eglInitialize(display,0,0);
  41. eglChooseConfig(display,attribs,&config,1,&numConfigs);
  42. surface=eglCreateWindowSurface(display,config,s.get(),NULL);
  43. context=eglCreateContext(display,config,NULL,NULL);
  44. eglQuerySurface(display,surface,EGL_WIDTH,&w);
  45. eglQuerySurface(display,surface,EGL_HEIGHT,&h);
  46. if(eglMakeCurrent(display,surface,surface,context)==EGL_FALSE)
  47. returnNO_INIT;
  48. mDisplay=display;
  49. mContext=context;
  50. mSurface=surface;
  51. mWidth=w;
  52. mHeight=h;
  53. mFlingerSurfaceControl=control;
  54. mFlingerSurface=s;
  55. mAndroidAnimation=true;
  56. //Ifthedevicehasencryptionturnedonorisinprocess
  57. //ofbeingencryptedweshowtheencryptedbootanimation.
  58. chardecrypt[PROPERTY_VALUE_MAX];
  59. property_get("vold.decrypt",decrypt,"");
  60. boolencryptedAnimation=atoi(decrypt)!=0||!strcmp("trigger_restart_min_framework",decrypt);
  61. if((encryptedAnimation&&
  62. (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE,R_OK)==0)&&
  63. (mZip.open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE)==NO_ERROR))||
  64. ((access(USER_BOOTANIMATION_FILE,R_OK)==0)&&
  65. (mZip.open(USER_BOOTANIMATION_FILE)==NO_ERROR))||
  66. ((access(SYSTEM_BOOTANIMATION_FILE,R_OK)==0)&&
  67. (mZip.open(SYSTEM_BOOTANIMATION_FILE)==NO_ERROR))){
  68. mAndroidAnimation=false;
  69. }
  70. returnNO_ERROR;
  71. }

threadloop实现 [cpp] view plain copy
  1. boolBootAnimation::threadLoop()
  2. {
  3. boolr;
  4. if(mAndroidAnimation){
  5. r=android();//显示android默认动画
  6. }else{
  7. r=movie();//显示自定义的动画
  8. }
  9. //Noneedtoforceexitanymore
  10. property_set(EXIT_PROP_NAME,"0");
  11. eglMakeCurrent(mDisplay,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);
  12. eglDestroyContext(mDisplay,mContext);
  13. eglDestroySurface(mDisplay,mSurface);
  14. mFlingerSurface.clear();
  15. mFlingerSurfaceControl.clear();
  16. eglTerminate(mDisplay);
  17. IPCThreadState::self()->stopProcess();
  18. returnr;
  19. }

movie()的实现 [cpp] view plain copy
  1. boolBootAnimation::movie()
  2. {
  3. //读取bootanimation.zip文件并解释
  4. //clearscreen
  5. //下面是循环显示
  6. for(inti=0;i<pcount;i++){
  7. constAnimation::Part&part(animation.parts[i]);
  8. constsize_tfcount=part.frames.size();
  9. glBindTexture(GL_TEXTURE_2D,0);
  10. for(intr=0;!part.count||r<part.count;r++){
  11. //Exitanynonplayuntilcompletepartsimmediately
  12. if(exitPending()&&!part.playUntilComplete)
  13. break;
  14. for(intj=0;j<fcount&&(!exitPending()||part.playUntilComplete);j++){
  15. constAnimation::Frame&frame(part.frames[j]);
  16. nsecs_tlastFrame=systemTime();
  17. if(r>0){
  18. glBindTexture(GL_TEXTURE_2D,frame.tid);
  19. }else{
  20. if(part.count!=1){
  21. glGenTextures(1,&frame.tid);
  22. glBindTexture(GL_TEXTURE_2D,frame.tid);
  23. glTexParameterx(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  24. glTexParameterx(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  25. }
  26. initTexture(
  27. frame.map->getDataPtr(),
  28. frame.map->getDataLength());
  29. }
  30. if(!clearReg.isEmpty()){
  31. Region::const_iteratorhead(clearReg.begin());
  32. Region::const_iteratortail(clearReg.end());
  33. glEnable(GL_SCISSOR_TEST);
  34. while(head!=tail){
  35. constRect&r(*head++);
  36. glScissor(r.left,mHeight-r.bottom,
  37. r.width(),r.height());
  38. glClear(GL_COLOR_BUFFER_BIT);
  39. }
  40. glDisable(GL_SCISSOR_TEST);
  41. }
  42. glDrawTexiOES(xc,yc,0,animation.width,animation.height);
  43. eglSwapBuffers(mDisplay,mSurface);
  44. nsecs_tnow=systemTime();
  45. nsecs_tdelay=frameDuration-(now-lastFrame);
  46. //ALOGD("%lld,%lld",ns2ms(now-lastFrame),ns2ms(delay));
  47. lastFrame=now;
  48. if(delay>0){
  49. structtimespecspec;
  50. spec.tv_sec=(now+delay)/1000000000;
  51. spec.tv_nsec=(now+delay)%1000000000;
  52. interr;
  53. do{
  54. err=clock_nanosleep(CLOCK_MONOTONIC,TIMER_ABSTIME,&spec,NULL);
  55. }while(err<0&&errno==EINTR);
  56. }
  57. checkExit();//检测是否退出动画
  58. }
  59. usleep(part.pause*ns2us(frameDuration));
  60. //Forinfiniteparts,we'venowplayedthematleastonce,soperhapsexit
  61. if(exitPending()&&!part.count)
  62. break;
  63. }
  64. //freethetexturesforthispart
  65. if(part.count!=1){
  66. for(intj=0;j<fcount;j++){
  67. constAnimation::Frame&frame(part.frames[j]);
  68. glDeleteTextures(1,&frame.tid);
  69. }
  70. }
  71. }
  72. returnfalse;
  73. }

那么到movie为止,动画是在播放了,而且还在循环检测是否退出,即checkExit()


checkExit()的实现

[cpp] view plain copy
  1. voidBootAnimation::checkExit(){
  2. //Allowsurfaceflingertogracefullyrequestshutdown
  3. charvalue[PROPERTY_VALUE_MAX];
  4. property_get(EXIT_PROP_NAME,value,"0");//属性为1,说明要退出了
  5. intexitnow=atoi(value);
  6. if(exitnow){
  7. requestExit();
  8. }
  9. }

[cpp] view plain copy
  1. property_get(EXIT_PROP_NAME,value,"0");检测这个属性,=1就退出动画
[cpp] view plain copy
  1. #defineEXIT_PROP_NAME"service.bootanim.exit"
这个属性就是上面讲到的,等到launcher跑起来后就会置1

那动画是什么时候退出的?

当launcher应用程序主线程跑起来后,如果主线程处于空闲,就会向ActivityManagerService发送一个activityIdle的消息。

应用程序主线程是ActivityThread.java来描述的,activityIdle是这个类来实现的

[cpp] view plain copy
  1. privateclassIdlerimplementsMessageQueue.IdleHandler{
  2. ...
  3. IActivityManageram=ActivityManagerNative.getDefault();
  4. ...
  5. try{
  6. am.activityIdle(a.token,a.createdConfig,stopProfiling);
  7. a.createdConfig=null;
  8. }catch(RemoteExceptionex){
  9. //Ignore
  10. }
  11. ....
  12. }

上面的ActivityManagerNavtive.getDefault()得到am

来到frameworks/base/core/java/android/app/ActivityManagerNative.java

[cpp] view plain copy
  1. staticpublicIActivityManagergetDefault(){
  2. returngDefault.get();//getDefault的实现
  3. }

[cpp] view plain copy
  1. privatestaticfinalSingleton<IActivityManager>gDefault=newSingleton<IActivityManager>(){
  2. protectedIActivityManagercreate(){
  3. IBinderb=ServiceManager.getService("activity");
  4. if(false){
  5. Log.v("ActivityManager","defaultservicebinder="+b);
  6. }
  7. IActivityManageram=asInterface(b);
  8. if(false){
  9. Log.v("ActivityManager","defaultservice="+am);
  10. }
  11. returnam;
  12. }
  13. };

gDefault实际上是IActivityManager,往下看

[cpp] view plain copy
  1. classActivityManagerProxyimplementsIActivityManager
  2. {


ActivityManagerProxy实现了IActivityManager

那么am.activityIdle()就是ActivityManagerProxy里的函数,如下

[cpp] view plain copy
  1. publicvoidactivityIdle(IBindertoken,Configurationconfig,booleanstopProfiling)
  2. throwsRemoteException
  3. {
  4. ...
  5. mRemote.transact(ACTIVITY_IDLE_TRANSACTION,data,reply,IBinder.FLAG_ONEWAY);//发送ACTIVITY_IDLE_TRANSACTION
  6. ....
  7. }

发送了ACTIVITY_IDLE_TRANSACTION的进程间通信,这个消息被 ActivityManagerNative接收处理了。

[cpp] view plain copy
  1. caseACTIVITY_IDLE_TRANSACTION:{//收到消息
  2. data.enforceInterface(IActivityManager.descriptor);
  3. IBindertoken=data.readStrongBinder();
  4. Configurationconfig=null;
  5. if(data.readInt()!=0){
  6. config=Configuration.CREATOR.createFromParcel(data);
  7. }
  8. booleanstopProfiling=data.readInt()!=0;
  9. if(token!=null){
  10. activityIdle(token,config,stopProfiling);//这个函数在ActivityManagerService被重写
  11. }
  12. reply.writeNoException();
  13. returntrue;
  14. }

收到消息后就调用了activityIdle函数,这个函数被ActivityManagerService重写了,如下

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

[cpp] view plain copy
  1. @Override
  2. publicfinalvoidactivityIdle(IBindertoken,Configurationconfig,booleanstopProfiling){
  3. finallongorigId=Binder.clearCallingIdentity();
  4. synchronized(this){
  5. ActivityStackstack=ActivityRecord.getStackLocked(token);
  6. if(stack!=null){
  7. ActivityRecordr=
  8. mStackSupervisor.activityIdleInternalLocked(token,false,config);
  9. if(stopProfiling){
  10. if((mProfileProc==r.app)&&(mProfileFd!=null)){
  11. try{
  12. mProfileFd.close();
  13. }catch(IOExceptione){
  14. }
  15. clearProfilerLocked();
  16. }
  17. }
  18. }
  19. }
  20. Binder.restoreCallingIdentity(origId);
  21. }

调用activityIdleInternalLocked函数,在下面实现

frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java

[cpp] view plain copy
  1. finalActivityRecordactivityIdleInternalLocked(finalIBindertoken,booleanfromTimeout,
  2. Configurationconfig){
  3. ....
  4. if(enableScreen){
  5. mService.enableScreenAfterBoot();//调ActivityManagerService类的enableScreenAfterBoot()函数
  6. }
  7. ....
  8. if(activityRemoved){
  9. resumeTopActivitiesLocked();
  10. }
  11. returnr;
  12. }


来到frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

[cpp] view plain copy
  1. voidenableScreenAfterBoot(){
  2. EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
  3. SystemClock.uptimeMillis());
  4. mWindowManager.enableScreenAfterBoot();//调WindowManagerService类里的enableScreenAfterBoot()函数
  5. synchronized(this){
  6. updateEventDispatchingLocked();
  7. }
  8. }

来到frameworks/base/services/java/com/android/server/wm/WindowManagerService.java


[cpp] view plain copy
  1. publicvoidenableScreenAfterBoot(){
  2. ....
  3. performEnableScreen();
  4. }

performEnableScreen()实现


[cpp] view plain copy
  1. publicvoidperformEnableScreen(){
  2. ..
  3. surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,//BOOT_FINISHED
  4. data,null,0);
  5. ....
  6. }

发送了FIRST_CALL_TRANSACTION的请求



因为从下面知道FIRST_CALL_TRANSACTION = BOOT_FINISHED

所以BnSurfaceComposer收到消息

frameworks/native/include/gui/ISurfaceComposer.h

[cpp] view plain copy
  1. classBnSurfaceComposer:publicBnInterface<ISurfaceComposer>{
  2. public:
  3. enum{
  4. //Note:BOOT_FINISHEDmustremainthisvalue,itiscalledfrom
  5. //JavabyActivityManagerService.
  6. BOOT_FINISHED=IBinder::FIRST_CALL_TRANSACTION,
  7. ...
  8. };
  9. virtualstatus_tonTransact(uint32_tcode,constParcel&data,
  10. Parcel*reply,uint32_tflags=0);
  11. };


[cpp] view plain copy
  1. </pre></p><p><spanstyle="color:#333333;">frameworks/native/libs/gui/ISurfaceComposer.cpp</span></p><p><spanstyle="color:#333333;"></span><prename="code"class="cpp">status_tBnSurfaceComposer::onTransact(
  2. uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)
  3. {
  4. switch(code){
  5. ....
  6. caseBOOT_FINISHED:{
  7. CHECK_INTERFACE(ISurfaceComposer,data,reply);
  8. bootFinished();//调用bootFinished()
  9. returnNO_ERROR;
  10. }
  11. ....
  12. }
  13. //shouldbeunreachable
  14. returnNO_ERROR;
  15. }

bootFinished()函数BpSurfaceComposer里实现,但发现没有,他又发了一个BOOT_FINISHED,死循环了,其实没有。bootFinished()被 SurfaceFlinger类重写了

[cpp] view plain copy
  1. classBpSurfaceComposer:publicBpInterface<ISurfaceComposer>
  2. {
  3. virtualvoidbootFinished()
  4. {
  5. Parceldata,reply;
  6. data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
  7. remote()->transact(BnSurfaceComposer::BOOT_FINISHED,data,&reply);
  8. }

重写

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

[cpp] view plain copy
  1. voidSurfaceFlinger::bootFinished()
  2. {
  3. ...
  4. property_set("service.bootanim.exit","1");
  5. }

把service.bootanim.exit写成1,然后bootanimation进程的checkExit()检测到就退出进程,停止播放。

更多相关文章

  1. android中的逐帧动画
  2. Android通过共享用户ID来实现多Activity进程共享
  3. Android 中 动画效果实现
  4. Android 转场动画
  5. Android使用View类动画
  6. Android 自定义PopupWindow动画效果
  7. Android之进程查看,关闭(可操作所有进程)
  8. 个性进度条--------菊花加载----Android 播放动画

随机推荐

  1. 使用GMail SMTP服务器从PHP页面发送电子
  2. 如何找到数组的大小
  3. 为什么在php.ini中设置了date.timezone =
  4. 登录后无法看到我的网站
  5. Asterisk ami删除某些扩展名
  6. 将纪元时间转换为日期PHP
  7. PHP - Content-type未指定假设应用程序/x
  8. 一道php自增运算符题
  9. ThinkPHP的create方法的一系列操作
  10. PHP不区分大小写数组搜索函数[duplicate]