一开始还是以为是Launcher起来后线程空闲回调Ams的接口开始进行关闭开机动画,但实际上看了下不仅仅是这个条件。不过还是从这里开始结合日志一起看。
在ActivityThread::handleLaunchActivity的过程中,会在resume阶段handleResumeActivity方法里面在加载完window之后将自己实现的Idlehandler添加到自己的消息队列里面,当Looper发现消息队列空闲的时候就会回调queueIdle方法
r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(
TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());
Idler实现的MessageQueue.IdleHandler接口就一个queueIdle方法,里面关键的就是会回调ams的activityIdle。
private class Idler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
ActivityClientRecord a = mNewActivities;
boolean stopProfiling = false;
if (mBoundApplication != null && mProfiler.profileFd != null
&& mProfiler.autoStopProfiler) {
stopProfiling = true;
}
if (a != null) {
mNewActivities = null;
IActivityManager am = ActivityManager.getService();
ActivityClientRecord prev;
do {
if (localLOGV) Slog.v(
TAG, "Reporting idle of " + a +
" finished=" +
(a.activity != null && a.activity.mFinished));
if (a.activity != null && !a.activity.mFinished) {
try {
am.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
prev = a;
a = a.nextIdle;
prev.nextIdle = null;
} while (a != null);
}
if (stopProfiling) {
mProfiler.stopProfiling();
}
ensureJitEnabled();
return false;
}
}
Ams
@Override
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
final long origId = Binder.clearCallingIdentity();
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
ActivityRecord r =
mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,
false /* processPausingActivities */, config);
if (stopProfiling) {
if ((mProfileProc == r.app) && mProfilerInfo != null) {
clearProfilerLocked();
}
}
}
}
Binder.restoreCallingIdentity(origId);
}
ActivityStackSuperVisor的activityIdleInternalLocked方法,会报告启动时间结束,还有就是检查是否是还在开机阶段然后结束开机流程。意思就是桌面都已经拿到焦点显示好了,开机动画可以退役了。在这里会修改Ams的mBooting全局变量为true,然后enableScreen也是true,发送Message给Ams进行处理,也就是开篇提到的。
//Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
if (isFocusedStack(r.getStack()) || fromTimeout) {
booting = checkFinishBootingLocked();
}
/**
* Called when the frontmost task is idle.
* @return the state of mService.mBooting before this was called.
*/
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;
}
void postFinishBooting(boolean finishBooting, boolean enableScreen) {
Exception e = new Exception("xian postFinishBooting");
e.printStackTrace();
mHandler.sendMessage(mHandler.obtainMessage(FINISH_BOOTING_MSG,
finishBooting ? 1 : 0, enableScreen ? 1 : 0));
}
这是对应的log打印的栈
07-03 10:20:26.632 3015 3027 W System.err: java.lang.Exception: xian postFinishBooting
07-03 10:20:26.633 3015 3027 W System.err: at com.android.server.am.ActivityManagerService.postFinishBooting(ActivityManagerService.java:7244)
07-03 10:20:26.633 3015 3027 W System.err: at com.android.server.am.ActivityStackSupervisor.checkFinishBootingLocked(ActivityStackSupervisor.java:1874)
07-03 10:20:26.633 3015 3027 W System.err: at com.android.server.am.ActivityStackSupervisor.activityIdleInternalLocked(ActivityStackSupervisor.java:1916)
07-03 10:20:26.633 3015 3027 W System.err: at com.android.server.am.ActivityManagerService.activityIdle(ActivityManagerService.java:7231)
07-03 10:20:26.633 3015 3027 W System.err: at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:309)
07-03 10:20:26.633 3015 3027 W System.err: at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2919)
07-03 10:20:26.633 3015 3027 W System.err: at android.os.Binder.execTransact(Binder.java:697)
处理Message是要干两件事,一件是finishBooting,一件是enableScreenAfterBoot。
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;
}
在finishBooting里面,