/** * Provides a low-level mechanism for an application to receive display events * such as vertical sync. * * The display event receive is NOT thread safe. Moreover, its methods must only * be called on the Looper thread to which it is attached. * * @hide */ publicabstractclassDisplayEventReceiver{ ... /** * Called when a vertical sync pulse is received. * 在VSync脉冲到达时会被调用 * The recipient should render a frame and then call {@link #scheduleVsync} * 接受者应该rende a frame(渲染好框架?)并调用 #scheduleVsync * to schedule the next vertical sync pulse. */ @UnsupportedAppUsage publicvoidonVsync(long timestampNanos, long physicalDisplayId, int frame){ } ... /** * Schedules a single vertical sync pulse to be delivered when the next * display frame begins. * 在下一帧到来前Schedules(规划)一个 用于被接收的 VSync脉冲 */ @UnsupportedAppUsage publicvoidscheduleVsync(){ if (mReceiverPtr == 0) { Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event " + "receiver has already been disposed."); } else { nativeScheduleVsync(mReceiverPtr); } } ... }
privatefinalclassFrameDisplayEventReceiverextendsDisplayEventReceiverimplementsRunnable{ @Override publicvoidonVsync(long timestampNanos, long physicalDisplayId, int frame){ // 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. long now = 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; }
voiddoCallbacks(int callbackType, long frameTimeNanos){ CallbackRecord callbacks; 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. finallong now = System.nanoTime(); //① 这句是关键,取出callbacks callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked( now / TimeUtils.NANOS_PER_MS); if (callbacks == null) { return; } mCallbacksRunning = true; ... } try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]); for (CallbackRecord c = 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)); } //② 循环调用callback.run c.run(frameTimeNanos); } } finally { synchronized (mLock) { mCallbacksRunning = false; do { final CallbackRecord next = callbacks.next; recycleCallbackLocked(callbacks); callbacks = next; } while (callbacks != null); } Trace.traceEnd(Trace.TRACE_TAG_VIEW); } }
privatestaticfinalclassCallbackRecord{ public CallbackRecord next; publiclong dueTime; public Object action; // Runnable or FrameCallback public Object token;