接下来,我们再继续分析第三个开机画面是如何停止显示的。
从前面
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的实现如下所示:
-
public final class ActivityThread {
-
......
-
-
private final class Idler implements MessageQueue.IdleHandler {
-
public final boolean queueIdle() {
-
ActivityClientRecord a = mNewActivities;
-
if (a != null) {
-
mNewActivities = null;
-
IActivityManager am = ActivityManagerNative.getDefault();
-
ActivityClientRecord prev;
-
do {
-
......
-
if (a.activity != null && !a.activity.mFinished) {
-
try {
-
am.activityIdle(a.token, a.createdConfig);
-
a.createdConfig = null;
-
} catch (RemoteException ex) {
-
}
-
}
-
prev = a;
-
a = a.nextIdle;
-
prev.nextIdle = null;
-
} while (a != null);
-
}
-
ensureJitEnabled();
-
return false;
-
}
-
}
-
-
......
-
}
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中,如下所示:
-
class ActivityManagerProxy implements IActivityManager
-
{
-
......
-
-
public void activityIdle(IBinder token, Configuration config) throws RemoteException
-
{
-
Parcel data = Parcel.obtain();
-
Parcel reply = Parcel.obtain();
-
data.writeInterfaceToken(IActivityManager.descriptor);
-
data.writeStrongBinder(token);
-
if (config != null) {
-
data.writeInt(1);
-
config.writeToParcel(data, 0);
-
} else {
-
data.writeInt(0);
-
}
-
mRemote.transact(ACTIVITY_IDLE_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
-
reply.readException();
-
data.recycle();
-
reply.recycle();
-
}
-
-
......
-
}
ActivityManagerProxy类的成员函数activityIdle实际上是向ActivityManagerService发送一个类型为ACTIVITY_IDLE_TRANSACTION的Binder进程间通信请求,其中,参数token用来描述与这个进程间通信请求所关联的一个Activity组件,在我们这个场景中,这个Activity组件即为应用程序Launcher的根Activity组件Launcher。
类型为ACTIVITY_IDLE_TRANSACTION的Binder进程间通信请求是由ActivityManagerService类的成员函数activityIdle来处理的,如下所示:
-
public final class ActivityManagerService extends ActivityManagerNative
-
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
-
......
-
-
public final void activityIdle(IBinder token, Configuration config) {
-
final long origId = Binder.clearCallingIdentity();
-
mMainStack.activityIdleInternal(token, false, config);
-
Binder.restoreCallingIdentity(origId);
-
}
-
-
......
-
}
ActivityManagerService类有一个类型为ActivityStack的成员变量mMainStack,它用来描述系统的Activity组件堆栈,它的成员函数activityIdleInternal的实现如下所示:
-
public class ActivityStack {
-
......
-
-
final void activityIdleInternal(IBinder token, boolean fromTimeout,
-
Configuration config) {
-
......
-
-
boolean enableScreen = false;
-
-
synchronized (mService) {
-
......
-
-
-
int index = indexOfTokenLocked(token);
-
if (index >= 0) {
-
ActivityRecord r = (ActivityRecord)mHistory.get(index);
-
......
-
-
if (mMainStack) {
-
if (!mService.mBooted && !fromTimeout) {
-
mService.mBooted = true;
-
enableScreen = true;
-
}
-
}
-
}
-
-
......
-
}
-
-
......
-
-
if (enableScreen) {
-
mService.enableScreenAfterBoot();
-
}
-
}
-
-
......
-
}
参数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的实现如下所示:
-
public final class ActivityManagerService extends ActivityManagerNative
-
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
-
......
-
-
void enableScreenAfterBoot() {
-
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
-
SystemClock.uptimeMillis());
-
mWindowManager.enableScreenAfterBoot();
-
}
-
-
......
-
}
ActivityManagerService类的成员变量mWindowManager指向了系统中的Window管理服务WindowManagerService,ActivityManagerService服务通过调用它的成员函数enableScreenAfterBoot来停止显示开机动画。
WindowManagerService类的成员函数enableScreenAfterBoot的实现如下所示:
-
public class WindowManagerService extends IWindowManager.Stub
-
implements Watchdog.Monitor {
-
......
-
-
public void enableScreenAfterBoot() {
-
synchronized(mWindowMap) {
-
if (mSystemBooted) {
-
return;
-
}
-
mSystemBooted = true;
-
}
-
-
performEnableScreen();
-
}
-
-
......
-
}
WindowManagerService类的成员变量mSystemBooted用来记录系统是否已经启动完成的。如果已经启动完成的话,那么这个成员变量的值就会等于true,这时候WindowManagerService类的成员函数enableScreenAfterBoot什么也不做就返回了,否则的话,WindowManagerService类的成员函数enableScreenAfterBoot首先将这个成员变量的值设置为true,接着再调用另外一个成员函数performEnableScreen来执行停止显示开机动画的操作。