接下来,我们再继续分析第三个开机画面是如何停止显示的。
        从前面Android系统默认Home应用程序(Launcher)的启动过程源代码分析一文可以知道,当System进程将系统中的关键服务启动起来之后,就会将应用程序启动器(Launcher)启动起来。从Android应用程序启动过程源代码分析一文又可以知道,Android应用程序的启动过程实际上就是它的根Activity组件的启动过程。对于应用程序Launcher来说,它的根Activity组件即为Launcher组件。
        一个Activity组件在启动起来之后,就会被记录起来,等到它所运行在的主线程空闲的时候,这个主线程就会向ActivityManagerService发送一个Activity组件空闲的通知。由于应用程序Launcher是系统中第一个被启动的应用程序,即它的根Activity组件是系统中第一个被启动的Activity组件,因此,当ActivityManagerService接收到它的空闲通知的时候,就可以知道系统是刚刚启动起来的。在这种情况下,ActivityManagerService就会停止显示开机动画,以便可以在屏幕中显示应用程序Lancher的界面。
       从前面Android应用程序消息处理机制(Looper、Handler)分析一文可以知道,如果一个线程想要在空闲的时候处理一些事务,那么就必须要向这个线程的消息队列注册一个空闲消息处理器。自定义的空闲消息处理器灯必须要从MessageQueue.IdleHandler类继承下来,并且重写成员函数queueIdle。当一个线程空闲的时候,即消息队列中没有新的消息需要处理的时候,那些注册了的空闲消息处理器的成员函数queueIdle就会被调用。
       应用程序的主线程是通过ActivityThread类来描述的,它实现在文件frameworks/base/core/java/android/app/ActivityThread.java中。每当有一个新的Activity组件启动起来的时候,ActivityThread类都会向它所描述的应用程序主线程的消息队列注册一个类型为Idler的空闲消息处理器。这样一个应用程序的主线程就可以在空闲的时候,向ActivityManagerService发送一个Activity组件空闲通知,相当于是通知ActivityManagerService,一个新的Activity组件已经准备就绪了。
Idler类定义在frameworks/base/core/java/android/app/ActivityThread.java中, 它的成员函数queueIdle的实现如下所示: 
  1. public final class ActivityThread {   
  2.     ......   
  3.    
  4.     private final class Idler implements MessageQueue.IdleHandler {   
  5.         public final boolean queueIdle() {   
  6.             ActivityClientRecord a = mNewActivities;   
  7.             if (a != null) {   
  8.                 mNewActivities = null;   
  9.                 IActivityManager am = ActivityManagerNative.getDefault();   
  10.                 ActivityClientRecord prev;   
  11.                 do {   
  12.                     ......   
  13.                     if (a.activity != null && !a.activity.mFinished) {   
  14.                         try {   
  15.                             am.activityIdle(a.token, a.createdConfig);   
  16.                             a.createdConfig = null;   
  17.                         } catch (RemoteException ex) {   
  18.                         }   
  19.                     }   
  20.                     prev = a;   
  21.                     a = a.nextIdle;   
  22.                     prev.nextIdle = null;   
  23.                 } while (a != null);   
  24.             }   
  25.             ensureJitEnabled();   
  26.             return false;   
  27.         }   
  28.     }   
  29.    
  30.     ......   
  31. }   
       ActivityThread类有一个类型为ActivityClientRecord的成员变量mNewActivities,用来描述所有在当前应用程序主线程中新启动起来的Activity组件。这些新启动起来的Activity组件通过ActivityClientRecord类的成员变量nextIdle连接在一起。一旦当前应用程序主线程向ActivityManagerService发送了这些新启动的Activity组件的空闲通知之后,这些新启动起来的Activity组件就不会再被保存在ActivityThread类的成员变量mNewActivities中了,即每一个新启动的Activity组件只有一次机会向ActivityManagerService发送一个空闲通知。
       向ActivityManagerService发送一个Activity组件空闲通知是通过调用ActivityManagerService代理对象的成员函数activityIdle来实现的,而ActivityManagerService代理对象可以通过调用ActivityManagerNative类的静态成员函数getDefault来获得。
       ActivityManagerService代理对象的类型为ActivityManagerProxy,它的成员函数activityIdle实现在文件frameworks/base/core/java/android/app/ActivityManagerNative.java中,如下所示:
  1. class ActivityManagerProxy implements IActivityManager   
  2. {   
  3.     ......   
  4.    
  5.     public void activityIdle(IBinder token, Configuration config) throws RemoteException   
  6.     {   
  7.         Parcel data = Parcel.obtain();   
  8.         Parcel reply = Parcel.obtain();   
  9.         data.writeInterfaceToken(IActivityManager.descriptor);   
  10.         data.writeStrongBinder(token);   
  11.         if (config != null) {   
  12.             data.writeInt(1);   
  13.             config.writeToParcel(data, 0);   
  14.         } else {   
  15.             data.writeInt(0);   
  16.         }   
  17.         mRemote.transact(ACTIVITY_IDLE_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);   
  18.         reply.readException();   
  19.         data.recycle();   
  20.         reply.recycle();   
  21.     }   
  22.    
  23.     ......   
  24. }   
      ActivityManagerProxy类的成员函数activityIdle实际上是向ActivityManagerService发送一个类型为ACTIVITY_IDLE_TRANSACTION的Binder进程间通信请求,其中,参数token用来描述与这个进程间通信请求所关联的一个Activity组件,在我们这个场景中,这个Activity组件即为应用程序Launcher的根Activity组件Launcher。
        类型为ACTIVITY_IDLE_TRANSACTION的Binder进程间通信请求是由ActivityManagerService类的成员函数activityIdle来处理的,如下所示:
  1. public final class ActivityManagerService extends ActivityManagerNative   
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   
  3.     ......   
  4.    
  5.     public final void activityIdle(IBinder token, Configuration config) {   
  6.         final long origId = Binder.clearCallingIdentity();   
  7.         mMainStack.activityIdleInternal(token, false, config);   
  8.         Binder.restoreCallingIdentity(origId);   
  9.     }   
  10.    
  11.     ......   
  12. }   
    ActivityManagerService类有一个类型为ActivityStack的成员变量mMainStack,它用来描述系统的Activity组件堆栈,它的成员函数activityIdleInternal的实现如下所示:
  1. public class ActivityStack {   
  2.     ......   
  3.    
  4.     final void activityIdleInternal(IBinder token, boolean fromTimeout,   
  5.             Configuration config) {   
  6.         ......   
  7.    
  8.         boolean enableScreen = false;   
  9.    
  10.         synchronized (mService) {   
  11.             ......   
  12.    
  13.             // Get the activity record.   
  14.             int index = indexOfTokenLocked(token);   
  15.             if (index >= 0) {   
  16.                 ActivityRecord r = (ActivityRecord)mHistory.get(index);                   
  17.                 ......   
  18.    
  19.                 if (mMainStack) {   
  20.                     if (!mService.mBooted && !fromTimeout) {   
  21.                         mService.mBooted = true;   
  22.                         enableScreen = true;   
  23.                     }   
  24.                 }   
  25.             }   
  26.    
  27.             ......   
  28.         }   
  29.    
  30.         ......   
  31.    
  32.         if (enableScreen) {   
  33.             mService.enableScreenAfterBoot();   
  34.         }   
  35.     }   
  36.    
  37.     ......   
  38. }           
        参数token用来描述刚刚启动起来的Launcher组件,通过它来调用函数indexOfTokenLocked就可以得到Launcher组件在系统Activity组件堆栈中的位置index。得到了Launcher组件在系统Activity组件堆栈中的位置index之后,就可以在ActivityStack类的成员变量mHistory中得到一个ActivityRecord对象r。这个ActivityRecord对象r同样是用来描述Launcher组件的。
        ActivityStack类的成员变量mMainStack是一个布尔变量,当它的值等于true的时候,就说明当前正在处理的ActivityStack对象是用来描述系统的Activity组件堆栈的。 ActivityStack类的另外一个成员变量mService指向了系统中的ActivityManagerService服务。ActivityManagerService服务有一个类型为布尔值的成员变量mBooted,它的初始值为false,表示系统尚未启动完成。
        从前面的调用过程可以知道,参数fromTimeout的值等于false。在这种情况下,如果ActivityManagerService服务的成员变量mBooted也等于false,那么就说明应用程序已经启动起来了,即说明系统已经启动完成了。这时候ActivityManagerService服务的成员变量mBooted以及变量enableScreen的值就会被设置为true。
        当变量enableScreen的值等于true的时候,ActivityStack类就会调用ActivityManagerService服务的成员函数enableScreenAfterBoot停止显示开机动画,以便可以将屏幕让出来显示应用程序Launcher的界面。
        ActivityManagerService类的成员函数enableScreenAfterBoot的实现如下所示:
  1. public final class ActivityManagerService extends ActivityManagerNative   
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   
  3.     ......   
  4.    
  5.     void enableScreenAfterBoot() {   
  6.         EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,   
  7.                 SystemClock.uptimeMillis());   
  8.         mWindowManager.enableScreenAfterBoot();   
  9.     }   
  10.    
  11.     ......   
  12. }   
        ActivityManagerService类的成员变量mWindowManager指向了系统中的Window管理服务WindowManagerService,ActivityManagerService服务通过调用它的成员函数enableScreenAfterBoot来停止显示开机动画。
       WindowManagerService类的成员函数enableScreenAfterBoot的实现如下所示:
  1. public class WindowManagerService extends IWindowManager.Stub   
  2.         implements Watchdog.Monitor {   
  3.     ......   
  4.    
  5.     public void enableScreenAfterBoot() {   
  6.         synchronized(mWindowMap) {   
  7.             if (mSystemBooted) {   
  8.                 return;   
  9.             }   
  10.             mSystemBooted = true;   
  11.         }   
  12.    
  13.         performEnableScreen();   
  14.     }   
  15.    
  16.     ......   
  17. }   
       WindowManagerService类的成员变量mSystemBooted用来记录系统是否已经启动完成的。如果已经启动完成的话,那么这个成员变量的值就会等于true,这时候WindowManagerService类的成员函数enableScreenAfterBoot什么也不做就返回了,否则的话,WindowManagerService类的成员函数enableScreenAfterBoot首先将这个成员变量的值设置为true,接着再调用另外一个成员函数performEnableScreen来执行停止显示开机动画的操作。

本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/967048,如需转载请自行联系原作者

Android系统的开机画面显示过程分析(12)相关推荐

  1. Android系统的开机画面显示过程分析(13)

          WindowManagerService类的成员函数performEnableScreen的实现如下所示: public class WindowManagerService extend ...

  2. Android系统的开机画面显示过程分析

    提到Android系统的UI,我们最先接触到的便是系统在启动过程中所出现的画面了.Android系统在启动的过程中,最多可以出现三个画面,每一个画面都用来描述一个不同的启动阶段.本文将详细分析这三个开 ...

  3. Android系统的开机画面显示过程分析(8)

         3. 第三个开机画面的显示过程         第三个开机画面是由应用程序bootanimation来负责显示的.应用程序bootanimation在启动脚本init.rc中被配置成了一个服 ...

  4. 安卓linux开机画面,Android系统的开机画面显示过程分析(1)

    好几个月都没有更新过博客了,从今天开始,老罗将尝试对Android系统的UI实现作一个系统的分析,也算是落实之前所作出的承诺.提到Android系统的UI,我们最先接触到的便是系统在启动过程中所出现的 ...

  5. Android系统的开机画面显示过程分析(5)

    2. 第二个开机画面的显示过程       由于第二个开机画面是在init进程启动的过程中显示的,因此,我们就从init进程的入口函数main开始分析第二个开机画面的显示过程.       init进 ...

  6. Android系统手机开机画面各个阶段代码执行流程分析(Part2)

    3. 第三个开机画面的显示过程 第三个开机画面是由应用程序bootanimation来负责显示的.应用程序bootanimation在启动脚本init.rc中被配置成了一个服务,如下所示: servi ...

  7. Android系统定制开机logo和开机动画

    定制开机logo和开机动画 开机logo 开机动画 bootanimation.zip 生成zip文件 添加新的开机动画 开机logo MTK ASOP中lk阶段的logo是开机后的第一个界面,也被称 ...

  8. Android系统手机开机画面各个阶段代码执行流程分析(Part1)

    提到Android系统的UI,我们最先接触到的便是系统在启动过程中所出现的画面了.Android系统在启动的过程中,最多可以出现三个画面,每一个画面都用来描述一个不同的启动阶段.本文将详细分析这三个开 ...

  9. android系统修改开机动画

    前提须知 开机动画是bootanimation.zip文件,包含part0和desc.txt两部分. part0文件夹:存放与屏幕分辨率相同的图片,图片命名数字递增. desc.txt文本:配置图片如 ...

  10. Android系统Surface机制的SurfaceFlinger服务的启动过程分析

    在前面一篇文章中,我们简要介绍了Android系统Surface机制中的SurfaceFlinger服务.SurfaceFlinger服务是在System进程中启动的,并且负责统一管理设备的帧缓冲区. ...

最新文章

  1. boost::fusion::make_fused用法的测试程序
  2. JVM之垃圾收集器回收种类
  3. Binary String Minimizing CodeForces - 1256D(贪心)
  4. android暂停活动,如何将Android暂停活动带到前面
  5. DemocracyOS促进双方的公民参与
  6. 王思聪名下企业被拍卖1100万债权,此前还债20亿 网友:拍下等于“接盘侠”?...
  7. 产品管理系列(一)---优秀的产品经理所具有的素质 王泽宾
  8. dell笔记本重装win10系统超详细的教程(适用所有windows系统的一套流程)
  9. c语言中switch语句流程图_C语言程序设计程序流程结构
  10. 软件考试(一)计算机技术与软件专业技术资格(水平)考试(以下简称软件水平考试)含金量最高,与职称挂钩。
  11. Meta-learning algorithms for Few-Shot Computer Vision论文解读(三)
  12. 理]疏通中国历史脉络——“魏(三国)、晋(五胡十六国)、南北朝”篇
  13. ImageDraw类详解:几何图形的绘制与文字的绘制
  14. setenv setfenv
  15. Android Manifest 权限描述大全
  16. 【MySQL】压缩包方式 - Windows下载安装及简单配置
  17. Unity UI跟随鼠标移动
  18. [SWPUCTF 2021 新生赛]easyrce
  19. 超简单的C++去重、排序
  20. Android应用程序资源的编译和打包过程分析

热门文章

  1. AutoResetEvent类的使用
  2. String.format中大括号的加入方法
  3. 暂且解决INSTALL_FAILED_SHARED_USER_INCOMPATIBLE错误
  4. vs2008的预编译命令
  5. FabFilter Total Bundle 2021 for Mac - 经典效果器合集(2022版)
  6. 解决关于升级macOS12后Alfred for mac无法运行PHP插件的问题
  7. 无法卸载 Mac 上的磁盘时该怎么办?
  8. BricsCAD 21 for Mac(CAD建模软件)多语言版
  9. 基于SpringMVC国际化资源配置方式Demo
  10. electron 爬坑记