Android 6.0 开机动画二

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函数。

  1. ......  
  2.             if (!r.onlyLocalRequest) {  
  3.                 r.nextIdle = mNewActivities;  
  4.                 mNewActivities = r;  
  5.                 if (localLOGV) Slog.v(  
  6.                     TAG, "Scheduling idle handler for " + r);  
  7.                 Looper.myQueue().addIdleHandler(new Idler());  
  8.             }  
  9. ......  

在Idler的queueIdle函数中调用了AMS的activityIdle函数,我们来看下,获取ActivityStack后调用了activityIdleInternalLocked函数。

  1. @Override  
  2. public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {  
  3.     final long origId = Binder.clearCallingIdentity();  
  4.     synchronized (this) {  
  5.         ActivityStack stack = ActivityRecord.getStackLocked(token);//得到ActivityStack  
  6.         if (stack != null) {  
  7.             ActivityRecord r =  
  8.                     mStackSupervisor.activityIdleInternalLocked(token, false, config);  
  9.             if (stopProfiling) {  
  10.                 if ((mProfileProc == r.app) && (mProfileFd != null)) {  
  11.                     try {  
  12.                         mProfileFd.close();  
  13.                     } catch (IOException e) {  
  14.                     }  
  15.                     clearProfilerLocked();  
  16.                 }  
  17.             }  
  18.         }  
  19.     }  
  20.     Binder.restoreCallingIdentity(origId);  
  21. }  

看如下函数,我们先根据token来得到其ActivityRecord,然后将ActivityRecord的idle置为true。如果是isFrontStack调用checkFinishBootingLocked函数。

  1. final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,  
  2.         Configuration config) {  
  3.     if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);  
  4.   
  5.     ArrayList<ActivityRecord> stops = null;  
  6.     ArrayList<ActivityRecord> finishes = null;  
  7.     ArrayList<UserState> startingUsers = null;  
  8.     int NS = 0;  
  9.     int NF = 0;  
  10.     boolean booting = false;  
  11.     boolean activityRemoved = false;  
  12.   
  13.     ActivityRecord r = ActivityRecord.forTokenLocked(token);  
  14.     if (r != null) {  
  15.         if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternalLocked: Callers="  
  16.                 + Debug.getCallers(4));  
  17.         mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);  
  18.         r.finishLaunchTickingLocked();  
  19.         if (fromTimeout) {  
  20.             reportActivityLaunchedLocked(fromTimeout, r, -1, -1);  
  21.         }  
  22.   
  23.         // This is a hack to semi-deal with a race condition  
  24.         // in the client where it can be constructed with a  
  25.         // newer configuration from when we asked it to launch.  
  26.         // We'll update with whatever configuration it now says  
  27.         // it used to launch.  
  28.         if (config != null) {  
  29.             r.configuration = config;  
  30.         }  
  31.   
  32.         // We are now idle.  If someone is waiting for a thumbnail from  
  33.         // us, we can now deliver.  
  34.         r.idle = true;//idle置为true  
  35.   
  36.         //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);  
  37.         if (isFrontStack(r.task.stack) || fromTimeout) {  
  38.             booting = checkFinishBootingLocked();  
  39.         }  
  40.     }  
  41. ..  

checkFinishBootingLocked函数,如果AMS正在启动会调用其postFinishBooting函数

  1. private boolean checkFinishBootingLocked() {  
  2.     final boolean booting = mService.mBooting;  
  3.     boolean enableScreen = false;  
  4.     mService.mBooting = false;  
  5.     if (!mService.mBooted) {  
  6.         mService.mBooted = true;  
  7.         enableScreen = true;  
  8.     }  
  9.     if (booting || enableScreen) {  
  10.         mService.postFinishBooting(booting, enableScreen);  
  11.     }  
  12.     return booting;  
  13. }  

AMS的postFinishBooting函数发送FINISH_BOOTING_MSG消息

  1. void postFinishBooting(boolean finishBooting, boolean enableScreen) {  
  2.     mHandler.sendMessage(mHandler.obtainMessage(FINISH_BOOTING_MSG,  
  3.             finishBooting ? 1 : 0, enableScreen ? 1 : 0));  
  4. }  

我们再来看消息处理,当finishBooting为true,就调用finishBooting函数,这个函数中会发送一些广播,以及将SystemService启动到PHASE_BOOT_COMPLETED阶段。

  1. case FINISH_BOOTING_MSG: {  
  2.     if (msg.arg1 != 0) {  
  3.         finishBooting();  
  4.     }  
  5.     if (msg.arg2 != 0) {  
  6.         enableScreenAfterBoot();  
  7.     }  
  8.     break;  
  9. }  

当enableScreen为true会调用enableScreenAfterBoot函数,会在这个函数中调用WMS的enableScreenAfterBoot函数

  1. void enableScreenAfterBoot() {  
  2.     EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,  
  3.             SystemClock.uptimeMillis());  
  4.     mWindowManager.enableScreenAfterBoot();  
  5.   
  6.     synchronized (this) {  
  7.         updateEventDispatchingLocked();  
  8.     }  
  9. }  

在WMS的enableScreenAfterBoot方法又会调用performEnableScreen方法,这个方法会调用SurfaceFlinger的Binder

  1. public void performEnableScreen() {  
  2.     synchronized(mWindowMap) {  
  3.         if (mDisplayEnabled) {  
  4.             return;  
  5.         }  
  6.         if (!mSystemBooted && !mShowingBootMessages) {  
  7.             return;  
  8.         }  
  9.   
  10.         // Don't enable the screen until all existing windows have been drawn.  
  11.         if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) {  
  12.             return;  
  13.         }  
  14.   
  15.         if (!mBootAnimationStopped) {  
  16.             // Do this one time.  
  17.             try {  
  18.                 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");  
  19.                 if (surfaceFlinger != null) {  
  20.                     //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");  
  21.                     Parcel data = Parcel.obtain();  
  22.                     data.writeInterfaceToken("android.ui.ISurfaceComposer");  
  23.                     surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED  
  24.                             data, null, 0);  
  25.                     data.recycle();  
  26.                 }  
  27.             } catch (RemoteException ex) {  
  28.                 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");  
  29.             }  
  30.             mBootAnimationStopped = true;  
  31.         }  
  32. ..  
FIRST_CALL_TRANSACTION就是BOOT_FINISHED
  1. class BnSurfaceComposer: public BnInterface<ISurfaceComposer> {  
  2. public:  
  3.     enum {  
  4.         // Note: BOOT_FINISHED must remain this value, it is called from  
  5.         // Java by ActivityManagerService.  
  6.         BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,  
我们再来看ISurfaceComposer.cpp对BOOT_FINISHED的处理,会调用bootFinished函数。
  1. case BOOT_FINISHED: {  
  2.     CHECK_INTERFACE(ISurfaceComposer, data, reply);  
  3.     bootFinished();  
  4.     return NO_ERROR;  
  5. }  
bootFinished会计算开机的时间,然后将service.bootanim.exit属性设为1,这样bootanim会结束,这样开机动画结束。
  1. void SurfaceFlinger::bootFinished()  
  2. {  
  3.     const nsecs_t now = systemTime();  
  4.     const nsecs_t duration = now - mBootTime;  
  5.     ALOGI("Boot is finished (%ld ms)"long(ns2ms(duration)) );  
  6.     mBootFinished = true;  
  7.   
  8.     // wait patiently for the window manager death  
  9.     const String16 name("window");  
  10.     sp<IBinder> window(defaultServiceManager()->getService(name));  
  11.     if (window != 0) {  
  12.         window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));  
  13.     }  
  14.   
  15.     // stop boot animation  
  16.     // formerly we would just kill the process, but we now ask it to exit so it  
  17.     // can choose where to stop the animation.  
  18.     property_set("service.bootanim.exit""1");  
  19.     char boot_exit_value[32];  
  20.     property_get("service.bootanim.exit", boot_exit_value, "0");  
  21.     ALOGD("The service.bootanim.exit property value is %d", atoi(boot_exit_value));  
  22. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值