//frameworks/base/core/java/android/view/Choreographer.javapublicstaticChoreographergetInstance(){returnsThreadInstance.get();}// Thread local storage for the choreographer.privatestaticfinalThreadLocal<Choreographer>sThreadInstance=newThreadLocal<Choreographer>(){@OverrideprotectedChoreographerinitialValue(){//获取当前线程LooperLooperlooper=Looper.myLooper();if(looper==null){thrownewIllegalStateException("The current thread must have a looper!");}Choreographerchoreographer=newChoreographer(looper,VSYNC_SOURCE_APP);if(looper==Looper.getMainLooper()){mMainInstance=choreographer;}returnchoreographer;}};
publicvoidpostCallback(intcallbackType,Runnableaction,Objecttoken){postCallbackDelayed(callbackType,action,token,0);}publicvoidpostCallbackDelayed(intcallbackType,Runnableaction,Objecttoken,longdelayMillis){if(action==null){thrownewIllegalArgumentException("action must not be null");}if(callbackType<0||callbackType>CALLBACK_LAST){thrownewIllegalArgumentException("callbackType is invalid");}postCallbackDelayedInternal(callbackType,action,token,delayMillis);}
privatevoidscheduleFrameLocked(longnow){if(!mFrameScheduled){mFrameScheduled=true;if(USE_VSYNC){// Android 4.1 之后 USE_VSYNCUSE_VSYNC 默认为 trueif(DEBUG_FRAMES){Log.d(TAG,"Scheduling next frame on vsync.");}// If running on the Looper thread, then schedule the vsync immediately,// otherwise post a message to schedule the vsync from the UI thread// as soon as possible.//如果是当前线程,直接申请 vsync,否则通过 handler 通信if(isRunningOnLooperThreadLocked()){scheduleVsyncLocked();}else{Messagemsg=mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);msg.setAsynchronous(true);mHandler.sendMessageAtFrontOfQueue(msg);}}else{finallongnextFrameTime=Math.max(mLastFrameTimeNanos/TimeUtils.NANOS_PER_MS+sFrameDelay,now);if(DEBUG_FRAMES){Log.d(TAG,"Scheduling next frame in "+(nextFrameTime-now)+" ms.");}Messagemsg=mHandler.obtainMessage(MSG_DO_FRAME);msg.setAsynchronous(true);mHandler.sendMessageAtTime(msg,nextFrameTime);}}}
@UnsupportedAppUsagepublicvoidscheduleVsync(){if(mReceiverPtr==0){Log.w(TAG,"Attempted to schedule a vertical sync pulse but the display event "+"receiver has already been disposed.");}else{// 注册监听 vsync 信号,会回调 dispatchVsync() 方法nativeScheduleVsync(mReceiverPtr);}}
@UnsupportedAppUsagepublicDisplayEventReceiver(Looperlooper){this(looper,VSYNC_SOURCE_APP,CONFIG_CHANGED_EVENT_SUPPRESS);}publicDisplayEventReceiver(Looperlooper,intvsyncSource,intconfigChanged){if(looper==null){thrownewIllegalArgumentException("looper must not be null");}//获取主线程消息队列mMessageQueue=looper.getQueue();//调用Native方法mReceiverPtr=nativeInit(newWeakReference<DisplayEventReceiver>(this),mMessageQueue,vsyncSource,configChanged);mCloseGuard.open("dispose");}
//android_view_DisplayEventReceiver.cppstaticjlongnativeInit(JNIEnv*env,jclassclazz,jobjectreceiverWeak,jobjectmessageQueueObj,jintvsyncSource,jintconfigChanged){//获取MessageQueuesp<MessageQueue>messageQueue=android_os_MessageQueue_getMessageQueue(env,messageQueueObj);if(messageQueue==NULL){jniThrowRuntimeException(env,"MessageQueue is not initialized.");return0;}//创建NativeDisplayEventReceiver对象sp<NativeDisplayEventReceiver>receiver=newNativeDisplayEventReceiver(env,receiverWeak,messageQueue,vsyncSource,configChanged);status_tstatus=receiver->initialize();if(status){String8message;message.appendFormat("Failed to initialize display event receiver. status=%d",status);jniThrowRuntimeException(env,message.string());return0;}//获取DisplayEventReceiver对象的引用receiver->incStrong(gDisplayEventReceiverClassInfo.clazz);// retain a reference for the objectreturnreinterpret_cast<jlong>(receiver.get());}
//androidfw/DisplayEventDispatcher.cppintDisplayEventDispatcher::handleEvent(int,intevents,void*){if(events&(Looper::EVENT_ERROR|Looper::EVENT_HANGUP)){ALOGE("Display event receiver pipe was closed or an error occurred. ""events=0x%x",events);return0;// remove the callback}if(!(events&Looper::EVENT_INPUT)){ALOGW("Received spurious callback for unhandled poll event. ""events=0x%x",events);return1;// keep the callback}// Drain all pending events, keep the last vsync.nsecs_tvsyncTimestamp;PhysicalDisplayIdvsyncDisplayId;uint32_tvsyncCount;//清除所有的pending事件,只保留最后一次vsyncif(processPendingEvents(&vsyncTimestamp,&vsyncDisplayId,&vsyncCount)){ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%"PRId64", displayId=%"ANDROID_PHYSICAL_DISPLAY_ID_FORMAT", count=%d",this,ns2ms(vsyncTimestamp),vsyncDisplayId,vsyncCount);mWaitingForVsync=false;//分发VsyncdispatchVsync(vsyncTimestamp,vsyncDisplayId,vsyncCount);}return1;// keep the callback}
//FrameDisplayEventReceiver.java@OverridepublicvoidonVsync(longtimestampNanos,longphysicalDisplayId,intframe){// Post the vsync event to the Handler.// The idea is to prevent incoming vsync events from completely starving// the message queue. If there are no messages in the queue with timestamps// earlier than the frame time, then the vsync event will be processed immediately.// Otherwise, messages that predate the vsync event will be handled first.longnow=System.nanoTime();if(timestampNanos>now){Log.w(TAG,"Frame time is "+((timestampNanos-now)*0.000001f)+" ms in the future! Check that graphics HAL is generating vsync "+"timestamps using the correct timebase.");timestampNanos=now;}if(mHavePendingVsync){Log.w(TAG,"Already have a pending vsync event. There should only be "+"one at a time.");}else{mHavePendingVsync=true;}mTimestampNanos=timestampNanos;mFrame=frame;Messagemsg=Message.obtain(mHandler,this);msg.setAsynchronous(true);mHandler.sendMessageAtTime(msg,timestampNanos/TimeUtils.NANOS_PER_MS);}
@UnsupportedAppUsagevoiddoFrame(longframeTimeNanos,intframe){finallongstartNanos;synchronized(mLock){//false直接返回if(!mFrameScheduled){return;// no work to do}if(DEBUG_JANK&&mDebugPrintNextFrameTimeDelta){mDebugPrintNextFrameTimeDelta=false;Log.d(TAG,"Frame time delta: "+((frameTimeNanos-mLastFrameTimeNanos)*0.000001f)+" ms");}longintendedFrameTimeNanos=frameTimeNanos;startNanos=System.nanoTime();finallongjitterNanos=startNanos-frameTimeNanos;if(jitterNanos>=mFrameIntervalNanos){finallongskippedFrames=jitterNanos/mFrameIntervalNanos;//当掉帧个数超过30,则输出响应logif(skippedFrames>=SKIPPED_FRAME_WARNING_LIMIT){Log.i(TAG,"Skipped "+skippedFrames+" frames! "+"The application may be doing too much work on its main thread.");}finallonglastFrameOffset=jitterNanos%mFrameIntervalNanos;if(DEBUG_JANK){Log.d(TAG,"Missed vsync by "+(jitterNanos*0.000001f)+" ms "+"which is more than the frame interval of "+(mFrameIntervalNanos*0.000001f)+" ms! "+"Skipping "+skippedFrames+" frames and setting frame "+"time to "+(lastFrameOffset*0.000001f)+" ms in the past.");}frameTimeNanos=startNanos-lastFrameOffset;}if(frameTimeNanos<mLastFrameTimeNanos){if(DEBUG_JANK){Log.d(TAG,"Frame time appears to be going backwards. May be due to a "+"previously skipped frame. Waiting for next vsync.");}scheduleVsyncLocked();return;}if(mFPSDivisor>1){longtimeSinceVsync=frameTimeNanos-mLastFrameTimeNanos;if(timeSinceVsync<(mFrameIntervalNanos*mFPSDivisor)&&timeSinceVsync>0){scheduleVsyncLocked();return;}}mFrameInfo.setVsync(intendedFrameTimeNanos,frameTimeNanos);mFrameScheduled=false;mLastFrameTimeNanos=frameTimeNanos;}try{Trace.traceBegin(Trace.TRACE_TAG_VIEW,"Choreographer#doFrame");AnimationUtils.lockAnimationClock(frameTimeNanos/TimeUtils.NANOS_PER_MS);mFrameInfo.markInputHandlingStart();doCallbacks(Choreographer.CALLBACK_INPUT,frameTimeNanos);//标记动画开始时间mFrameInfo.markAnimationsStart();//执行回调方法doCallbacks(Choreographer.CALLBACK_ANIMATION,frameTimeNanos);doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION,frameTimeNanos);mFrameInfo.markPerformTraversalsStart();doCallbacks(Choreographer.CALLBACK_TRAVERSAL,frameTimeNanos);doCallbacks(Choreographer.CALLBACK_COMMIT,frameTimeNanos);}finally{AnimationUtils.unlockAnimationClock();Trace.traceEnd(Trace.TRACE_TAG_VIEW);}if(DEBUG_FRAMES){finallongendNanos=System.nanoTime();Log.d(TAG,"Frame "+frame+": Finished, took "+(endNanos-startNanos)*0.000001f+" ms, latency "+(startNanos-frameTimeNanos)*0.000001f+" ms.");}}
voiddoCallbacks(intcallbackType,longframeTimeNanos){CallbackRecordcallbacks;synchronized(mLock){// We use "now" to determine when callbacks become due because it's possible// for earlier processing phases in a frame to post callbacks that should run// in a following phase, such as an input event that causes an animation to start.finallongnow=System.nanoTime();//从队列查找相应类型的CallbackRecord对象callbacks=mCallbackQueues[callbackType].extractDueCallbacksLocked(now/TimeUtils.NANOS_PER_MS);if(callbacks==null){return;}mCallbacksRunning=true;// Update the frame time if necessary when committing the frame.// We only update the frame time if we are more than 2 frames late reaching// the commit phase. This ensures that the frame time which is observed by the// callbacks will always increase from one frame to the next and never repeat.// We never want the next frame's starting frame time to end up being less than// or equal to the previous frame's commit frame time. Keep in mind that the// next frame has most likely already been scheduled by now so we play it// safe by ensuring the commit time is always at least one frame behind.if(callbackType==Choreographer.CALLBACK_COMMIT){finallongjitterNanos=now-frameTimeNanos;Trace.traceCounter(Trace.TRACE_TAG_VIEW,"jitterNanos",(int)jitterNanos);//当commit类型回调执行的时间点超过2帧,则更新mLastFrameTimeNanos。if(jitterNanos>=2*mFrameIntervalNanos){finallonglastFrameOffset=jitterNanos%mFrameIntervalNanos+mFrameIntervalNanos;if(DEBUG_JANK){Log.d(TAG,"Commit callback delayed by "+(jitterNanos*0.000001f)+" ms which is more than twice the frame interval of "+(mFrameIntervalNanos*0.000001f)+" ms! "+"Setting frame time to "+(lastFrameOffset*0.000001f)+" ms in the past.");mDebugPrintNextFrameTimeDelta=true;}frameTimeNanos=now-lastFrameOffset;mLastFrameTimeNanos=frameTimeNanos;}}}try{Trace.traceBegin(Trace.TRACE_TAG_VIEW,CALLBACK_TRACE_TITLES[callbackType]);for(CallbackRecordc=callbacks;c!=null;c=c.next){if(DEBUG_FRAMES){Log.d(TAG,"RunCallback: type="+callbackType+", action="+c.action+", token="+c.token+", latencyMillis="+(SystemClock.uptimeMillis()-c.dueTime));}c.run(frameTimeNanos);}}finally{synchronized(mLock){mCallbacksRunning=false;//回收callbacks,加入对象池mCallbackPooldo{finalCallbackRecordnext=callbacks.next;recycleCallbackLocked(callbacks);callbacks=next;}while(callbacks!=null);}Trace.traceEnd(Trace.TRACE_TAG_VIEW);}}
privatestaticfinalclassCallbackRecord{publicCallbackRecordnext;publiclongdueTime;publicObjectaction;// Runnable or FrameCallbackpublicObjecttoken;@UnsupportedAppUsagepublicvoidrun(longframeTimeNanos){if(token==FRAME_CALLBACK_TOKEN){((FrameCallback)action).doFrame(frameTimeNanos);}else{((Runnable)action).run();}}}