在http://blog.csdn.net/kc58236582/article/details/52794846博客中我们已经讲了开机动画的大致流程,这里我们就Launcher启动后,Launcher的线程闲的时候在ActivityThread调用AMS的activityIdle方法。
在分析消息机制 空闲消息处理器中http://blog.csdn.net/kc58236582/article/details/52919904,我们知道在消息线程空闲时会调用IdleHandler的queueIdle方法,这里我们来看ActivityThread中的IdleHandler,是在ActivityThread的handleResumeActivity函数中有下面一段代码,调用了MessageQueue的addIdleHandler函数。
...... if (!r.onlyLocalRequest) { r.nextIdle = mNewActivities; mNewActivities = r; if (localLOGV) Slog.v( TAG, "Scheduling idle handler for " + r); Looper.myQueue().addIdleHandler(new Idler()); } ......
在Idler的queueIdle函数中调用了AMS的activityIdle函数,我们来看下,获取ActivityStack后调用了activityIdleInternalLocked函数。
@Override public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) { final long origId = Binder.clearCallingIdentity(); synchronized (this) { ActivityStack stack = ActivityRecord.getStackLocked(token);//得到ActivityStack if (stack != null) { ActivityRecord r = mStackSupervisor.activityIdleInternalLocked(token, false, config); if (stopProfiling) { if ((mProfileProc == r.app) && (mProfileFd != null)) { try { mProfileFd.close(); } catch (IOException e) { } clearProfilerLocked(); } } } } Binder.restoreCallingIdentity(origId); }
看如下函数,我们先根据token来得到其ActivityRecord,然后将ActivityRecord的idle置为true。如果是isFrontStack调用checkFinishBootingLocked函数。
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout, Configuration config) { if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token); ArrayList<ActivityRecord> stops = null; ArrayList<ActivityRecord> finishes = null; ArrayList<UserState> startingUsers = null; int NS = 0; int NF = 0; boolean booting = false; boolean activityRemoved = false; ActivityRecord r = ActivityRecord.forTokenLocked(token); if (r != null) { if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternalLocked: Callers=" + Debug.getCallers(4)); mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); r.finishLaunchTickingLocked(); if (fromTimeout) { reportActivityLaunchedLocked(fromTimeout, r, -1, -1); } // This is a hack to semi-deal with a race condition // in the client where it can be constructed with a // newer configuration from when we asked it to launch. // We'll update with whatever configuration it now says // it used to launch. if (config != null) { r.configuration = config; } // We are now idle. If someone is waiting for a thumbnail from // us, we can now deliver. r.idle = true;//idle置为true //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout); if (isFrontStack(r.task.stack) || fromTimeout) { booting = checkFinishBootingLocked(); } } ......
checkFinishBootingLocked函数,如果AMS正在启动会调用其postFinishBooting函数
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; }
AMS的postFinishBooting函数发送FINISH_BOOTING_MSG消息
void postFinishBooting(boolean finishBooting, boolean enableScreen) { mHandler.sendMessage(mHandler.obtainMessage(FINISH_BOOTING_MSG, finishBooting ? 1 : 0, enableScreen ? 1 : 0)); }
我们再来看消息处理,当finishBooting为true,就调用finishBooting函数,这个函数中会发送一些广播,以及将SystemService启动到PHASE_BOOT_COMPLETED阶段。
case FINISH_BOOTING_MSG: { if (msg.arg1 != 0) { finishBooting(); } if (msg.arg2 != 0) { enableScreenAfterBoot(); } break; }
当enableScreen为true会调用enableScreenAfterBoot函数,会在这个函数中调用WMS的enableScreenAfterBoot函数
void enableScreenAfterBoot() { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN, SystemClock.uptimeMillis()); mWindowManager.enableScreenAfterBoot(); synchronized (this) { updateEventDispatchingLocked(); } }
在WMS的enableScreenAfterBoot方法又会调用performEnableScreen方法,这个方法会调用SurfaceFlinger的Binder
public void performEnableScreen() { synchronized(mWindowMap) { if (mDisplayEnabled) { return; } if (!mSystemBooted && !mShowingBootMessages) { return; } // Don't enable the screen until all existing windows have been drawn. if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) { return; } if (!mBootAnimationStopped) { // Do this one time. try { IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); if (surfaceFlinger != null) { //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); Parcel data = Parcel.obtain(); data.writeInterfaceToken("android.ui.ISurfaceComposer"); surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED data, null, 0); data.recycle(); } } catch (RemoteException ex) { Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); } mBootAnimationStopped = true; } ......FIRST_CALL_TRANSACTION就是BOOT_FINISHED
class BnSurfaceComposer: public BnInterface<ISurfaceComposer> { public: enum { // Note: BOOT_FINISHED must remain this value, it is called from // Java by ActivityManagerService. BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,我们再来看ISurfaceComposer.cpp对BOOT_FINISHED的处理,会调用bootFinished函数。
case BOOT_FINISHED: { CHECK_INTERFACE(ISurfaceComposer, data, reply); bootFinished(); return NO_ERROR; }bootFinished会计算开机的时间,然后将service.bootanim.exit属性设为1,这样bootanim会结束,这样开机动画结束。
void SurfaceFlinger::bootFinished() { const nsecs_t now = systemTime(); const nsecs_t duration = now - mBootTime; ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); mBootFinished = true; // wait patiently for the window manager death const String16 name("window"); sp<IBinder> window(defaultServiceManager()->getService(name)); if (window != 0) { window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this)); } // stop boot animation // formerly we would just kill the process, but we now ask it to exit so it // can choose where to stop the animation. property_set("service.bootanim.exit", "1"); char boot_exit_value[32]; property_get("service.bootanim.exit", boot_exit_value, "0"); ALOGD("The service.bootanim.exit property value is %d", atoi(boot_exit_value)); }