在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;
- }
- ..
- 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,
- case BOOT_FINISHED: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- bootFinished();
- return NO_ERROR;
- }
- 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));
- }