OSDN Git Service

Merge "docs: Add documentation for equals() method" into qt-dev am: 732a127636
[android-x86/frameworks-base.git] / core / java / android / view / Choreographer.java
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package android.view;
18
19 import static android.view.DisplayEventReceiver.CONFIG_CHANGED_EVENT_SUPPRESS;
20 import static android.view.DisplayEventReceiver.VSYNC_SOURCE_APP;
21 import static android.view.DisplayEventReceiver.VSYNC_SOURCE_SURFACE_FLINGER;
22
23 import android.annotation.TestApi;
24 import android.annotation.UnsupportedAppUsage;
25 import android.graphics.FrameInfo;
26 import android.hardware.display.DisplayManagerGlobal;
27 import android.os.Build;
28 import android.os.Handler;
29 import android.os.Looper;
30 import android.os.Message;
31 import android.os.SystemClock;
32 import android.os.SystemProperties;
33 import android.os.Trace;
34 import android.util.Log;
35 import android.util.TimeUtils;
36 import android.view.animation.AnimationUtils;
37
38 import java.io.PrintWriter;
39
40 /**
41  * Coordinates the timing of animations, input and drawing.
42  * <p>
43  * The choreographer receives timing pulses (such as vertical synchronization)
44  * from the display subsystem then schedules work to occur as part of rendering
45  * the next display frame.
46  * </p><p>
47  * Applications typically interact with the choreographer indirectly using
48  * higher level abstractions in the animation framework or the view hierarchy.
49  * Here are some examples of things you can do using the higher-level APIs.
50  * </p>
51  * <ul>
52  * <li>To post an animation to be processed on a regular time basis synchronized with
53  * display frame rendering, use {@link android.animation.ValueAnimator#start}.</li>
54  * <li>To post a {@link Runnable} to be invoked once at the beginning of the next display
55  * frame, use {@link View#postOnAnimation}.</li>
56  * <li>To post a {@link Runnable} to be invoked once at the beginning of the next display
57  * frame after a delay, use {@link View#postOnAnimationDelayed}.</li>
58  * <li>To post a call to {@link View#invalidate()} to occur once at the beginning of the
59  * next display frame, use {@link View#postInvalidateOnAnimation()} or
60  * {@link View#postInvalidateOnAnimation(int, int, int, int)}.</li>
61  * <li>To ensure that the contents of a {@link View} scroll smoothly and are drawn in
62  * sync with display frame rendering, do nothing.  This already happens automatically.
63  * {@link View#onDraw} will be called at the appropriate time.</li>
64  * </ul>
65  * <p>
66  * However, there are a few cases where you might want to use the functions of the
67  * choreographer directly in your application.  Here are some examples.
68  * </p>
69  * <ul>
70  * <li>If your application does its rendering in a different thread, possibly using GL,
71  * or does not use the animation framework or view hierarchy at all
72  * and you want to ensure that it is appropriately synchronized with the display, then use
73  * {@link Choreographer#postFrameCallback}.</li>
74  * <li>... and that's about it.</li>
75  * </ul>
76  * <p>
77  * Each {@link Looper} thread has its own choreographer.  Other threads can
78  * post callbacks to run on the choreographer but they will run on the {@link Looper}
79  * to which the choreographer belongs.
80  * </p>
81  */
82 public final class Choreographer {
83     private static final String TAG = "Choreographer";
84
85     // Prints debug messages about jank which was detected (low volume).
86     private static final boolean DEBUG_JANK = false;
87
88     // Prints debug messages about every frame and callback registered (high volume).
89     private static final boolean DEBUG_FRAMES = false;
90
91     // The default amount of time in ms between animation frames.
92     // When vsync is not enabled, we want to have some idea of how long we should
93     // wait before posting the next animation message.  It is important that the
94     // default value be less than the true inter-frame delay on all devices to avoid
95     // situations where we might skip frames by waiting too long (we must compensate
96     // for jitter and hardware variations).  Regardless of this value, the animation
97     // and display loop is ultimately rate-limited by how fast new graphics buffers can
98     // be dequeued.
99     private static final long DEFAULT_FRAME_DELAY = 10;
100
101     // The number of milliseconds between animation frames.
102     private static volatile long sFrameDelay = DEFAULT_FRAME_DELAY;
103
104     // Thread local storage for the choreographer.
105     private static final ThreadLocal<Choreographer> sThreadInstance =
106             new ThreadLocal<Choreographer>() {
107         @Override
108         protected Choreographer initialValue() {
109             Looper looper = Looper.myLooper();
110             if (looper == null) {
111                 throw new IllegalStateException("The current thread must have a looper!");
112             }
113             Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);
114             if (looper == Looper.getMainLooper()) {
115                 mMainInstance = choreographer;
116             }
117             return choreographer;
118         }
119     };
120
121     private static volatile Choreographer mMainInstance;
122
123     // Thread local storage for the SF choreographer.
124     private static final ThreadLocal<Choreographer> sSfThreadInstance =
125             new ThreadLocal<Choreographer>() {
126                 @Override
127                 protected Choreographer initialValue() {
128                     Looper looper = Looper.myLooper();
129                     if (looper == null) {
130                         throw new IllegalStateException("The current thread must have a looper!");
131                     }
132                     return new Choreographer(looper, VSYNC_SOURCE_SURFACE_FLINGER);
133                 }
134             };
135
136     // Enable/disable vsync for animations and drawing.
137     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769497)
138     private static final boolean USE_VSYNC = SystemProperties.getBoolean(
139             "debug.choreographer.vsync", true);
140
141     // Enable/disable using the frame time instead of returning now.
142     private static final boolean USE_FRAME_TIME = SystemProperties.getBoolean(
143             "debug.choreographer.frametime", true);
144
145     // Set a limit to warn about skipped frames.
146     // Skipped frames imply jank.
147     private static final int SKIPPED_FRAME_WARNING_LIMIT = SystemProperties.getInt(
148             "debug.choreographer.skipwarning", 30);
149
150     private static final int MSG_DO_FRAME = 0;
151     private static final int MSG_DO_SCHEDULE_VSYNC = 1;
152     private static final int MSG_DO_SCHEDULE_CALLBACK = 2;
153
154     // All frame callbacks posted by applications have this token.
155     private static final Object FRAME_CALLBACK_TOKEN = new Object() {
156         public String toString() { return "FRAME_CALLBACK_TOKEN"; }
157     };
158
159     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
160     private final Object mLock = new Object();
161
162     private final Looper mLooper;
163     private final FrameHandler mHandler;
164
165     // The display event receiver can only be accessed by the looper thread to which
166     // it is attached.  We take care to ensure that we post message to the looper
167     // if appropriate when interacting with the display event receiver.
168     @UnsupportedAppUsage
169     private final FrameDisplayEventReceiver mDisplayEventReceiver;
170
171     private CallbackRecord mCallbackPool;
172
173     @UnsupportedAppUsage
174     private final CallbackQueue[] mCallbackQueues;
175
176     private boolean mFrameScheduled;
177     private boolean mCallbacksRunning;
178     @UnsupportedAppUsage
179     private long mLastFrameTimeNanos;
180     @UnsupportedAppUsage
181     private long mFrameIntervalNanos;
182     private boolean mDebugPrintNextFrameTimeDelta;
183     private int mFPSDivisor = 1;
184
185     /**
186      * Contains information about the current frame for jank-tracking,
187      * mainly timings of key events along with a bit of metadata about
188      * view tree state
189      *
190      * TODO: Is there a better home for this? Currently Choreographer
191      * is the only one with CALLBACK_ANIMATION start time, hence why this
192      * resides here.
193      *
194      * @hide
195      */
196     FrameInfo mFrameInfo = new FrameInfo();
197
198     /**
199      * Must be kept in sync with CALLBACK_* ints below, used to index into this array.
200      * @hide
201      */
202     private static final String[] CALLBACK_TRACE_TITLES = {
203             "input", "animation", "insets_animation", "traversal", "commit"
204     };
205
206     /**
207      * Callback type: Input callback.  Runs first.
208      * @hide
209      */
210     public static final int CALLBACK_INPUT = 0;
211
212     /**
213      * Callback type: Animation callback.  Runs before {@link #CALLBACK_INSETS_ANIMATION}.
214      * @hide
215      */
216     @TestApi
217     public static final int CALLBACK_ANIMATION = 1;
218
219     /**
220      * Callback type: Animation callback to handle inset updates. This is separate from
221      * {@link #CALLBACK_ANIMATION} as we need to "gather" all inset animation updates via
222      * {@link WindowInsetsAnimationController#changeInsets} for multiple ongoing animations but then
223      * update the whole view system with a single callback to {@link View#dispatchWindowInsetsAnimationProgress}
224      * that contains all the combined updated insets.
225      * <p>
226      * Both input and animation may change insets, so we need to run this after these callbacks, but
227      * before traversals.
228      * <p>
229      * Runs before traversals.
230      * @hide
231      */
232     public static final int CALLBACK_INSETS_ANIMATION = 2;
233
234     /**
235      * Callback type: Traversal callback.  Handles layout and draw.  Runs
236      * after all other asynchronous messages have been handled.
237      * @hide
238      */
239     public static final int CALLBACK_TRAVERSAL = 3;
240
241     /**
242      * Callback type: Commit callback.  Handles post-draw operations for the frame.
243      * Runs after traversal completes.  The {@link #getFrameTime() frame time} reported
244      * during this callback may be updated to reflect delays that occurred while
245      * traversals were in progress in case heavy layout operations caused some frames
246      * to be skipped.  The frame time reported during this callback provides a better
247      * estimate of the start time of the frame in which animations (and other updates
248      * to the view hierarchy state) actually took effect.
249      * @hide
250      */
251     public static final int CALLBACK_COMMIT = 4;
252
253     private static final int CALLBACK_LAST = CALLBACK_COMMIT;
254
255     private Choreographer(Looper looper, int vsyncSource) {
256         mLooper = looper;
257         mHandler = new FrameHandler(looper);
258         mDisplayEventReceiver = USE_VSYNC
259                 ? new FrameDisplayEventReceiver(looper, vsyncSource)
260                 : null;
261         mLastFrameTimeNanos = Long.MIN_VALUE;
262
263         mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
264
265         mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
266         for (int i = 0; i <= CALLBACK_LAST; i++) {
267             mCallbackQueues[i] = new CallbackQueue();
268         }
269         // b/68769804: For low FPS experiments.
270         setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));
271     }
272
273     private static float getRefreshRate() {
274         DisplayInfo di = DisplayManagerGlobal.getInstance().getDisplayInfo(
275                 Display.DEFAULT_DISPLAY);
276         return di.getMode().getRefreshRate();
277     }
278
279     /**
280      * Gets the choreographer for the calling thread.  Must be called from
281      * a thread that already has a {@link android.os.Looper} associated with it.
282      *
283      * @return The choreographer for this thread.
284      * @throws IllegalStateException if the thread does not have a looper.
285      */
286     public static Choreographer getInstance() {
287         return sThreadInstance.get();
288     }
289
290     /**
291      * @hide
292      */
293     @UnsupportedAppUsage
294     public static Choreographer getSfInstance() {
295         return sSfThreadInstance.get();
296     }
297
298     /**
299      * @return The Choreographer of the main thread, if it exists, or {@code null} otherwise.
300      * @hide
301      */
302     public static Choreographer getMainThreadInstance() {
303         return mMainInstance;
304     }
305
306     /** Destroys the calling thread's choreographer
307      * @hide
308      */
309     public static void releaseInstance() {
310         Choreographer old = sThreadInstance.get();
311         sThreadInstance.remove();
312         old.dispose();
313     }
314
315     private void dispose() {
316         mDisplayEventReceiver.dispose();
317     }
318
319     /**
320      * The amount of time, in milliseconds, between each frame of the animation.
321      * <p>
322      * This is a requested time that the animation will attempt to honor, but the actual delay
323      * between frames may be different, depending on system load and capabilities. This is a static
324      * function because the same delay will be applied to all animations, since they are all
325      * run off of a single timing loop.
326      * </p><p>
327      * The frame delay may be ignored when the animation system uses an external timing
328      * source, such as the display refresh rate (vsync), to govern animations.
329      * </p>
330      *
331      * @return the requested time between frames, in milliseconds
332      * @hide
333      */
334     @TestApi
335     public static long getFrameDelay() {
336         return sFrameDelay;
337     }
338
339     /**
340      * The amount of time, in milliseconds, between each frame of the animation.
341      * <p>
342      * This is a requested time that the animation will attempt to honor, but the actual delay
343      * between frames may be different, depending on system load and capabilities. This is a static
344      * function because the same delay will be applied to all animations, since they are all
345      * run off of a single timing loop.
346      * </p><p>
347      * The frame delay may be ignored when the animation system uses an external timing
348      * source, such as the display refresh rate (vsync), to govern animations.
349      * </p>
350      *
351      * @param frameDelay the requested time between frames, in milliseconds
352      * @hide
353      */
354     @TestApi
355     public static void setFrameDelay(long frameDelay) {
356         sFrameDelay = frameDelay;
357     }
358
359     /**
360      * Subtracts typical frame delay time from a delay interval in milliseconds.
361      * <p>
362      * This method can be used to compensate for animation delay times that have baked
363      * in assumptions about the frame delay.  For example, it's quite common for code to
364      * assume a 60Hz frame time and bake in a 16ms delay.  When we call
365      * {@link #postAnimationCallbackDelayed} we want to know how long to wait before
366      * posting the animation callback but let the animation timer take care of the remaining
367      * frame delay time.
368      * </p><p>
369      * This method is somewhat conservative about how much of the frame delay it
370      * subtracts.  It uses the same value returned by {@link #getFrameDelay} which by
371      * default is 10ms even though many parts of the system assume 16ms.  Consequently,
372      * we might still wait 6ms before posting an animation callback that we want to run
373      * on the next frame, but this is much better than waiting a whole 16ms and likely
374      * missing the deadline.
375      * </p>
376      *
377      * @param delayMillis The original delay time including an assumed frame delay.
378      * @return The adjusted delay time with the assumed frame delay subtracted out.
379      * @hide
380      */
381     public static long subtractFrameDelay(long delayMillis) {
382         final long frameDelay = sFrameDelay;
383         return delayMillis <= frameDelay ? 0 : delayMillis - frameDelay;
384     }
385
386     /**
387      * @return The refresh rate as the nanoseconds between frames
388      * @hide
389      */
390     public long getFrameIntervalNanos() {
391         return mFrameIntervalNanos;
392     }
393
394     void dump(String prefix, PrintWriter writer) {
395         String innerPrefix = prefix + "  ";
396         writer.print(prefix); writer.println("Choreographer:");
397         writer.print(innerPrefix); writer.print("mFrameScheduled=");
398                 writer.println(mFrameScheduled);
399         writer.print(innerPrefix); writer.print("mLastFrameTime=");
400                 writer.println(TimeUtils.formatUptime(mLastFrameTimeNanos / 1000000));
401     }
402
403     /**
404      * Posts a callback to run on the next frame.
405      * <p>
406      * The callback runs once then is automatically removed.
407      * </p>
408      *
409      * @param callbackType The callback type.
410      * @param action The callback action to run during the next frame.
411      * @param token The callback token, or null if none.
412      *
413      * @see #removeCallbacks
414      * @hide
415      */
416     @TestApi
417     public void postCallback(int callbackType, Runnable action, Object token) {
418         postCallbackDelayed(callbackType, action, token, 0);
419     }
420
421     /**
422      * Posts a callback to run on the next frame after the specified delay.
423      * <p>
424      * The callback runs once then is automatically removed.
425      * </p>
426      *
427      * @param callbackType The callback type.
428      * @param action The callback action to run during the next frame after the specified delay.
429      * @param token The callback token, or null if none.
430      * @param delayMillis The delay time in milliseconds.
431      *
432      * @see #removeCallback
433      * @hide
434      */
435     @TestApi
436     public void postCallbackDelayed(int callbackType,
437             Runnable action, Object token, long delayMillis) {
438         if (action == null) {
439             throw new IllegalArgumentException("action must not be null");
440         }
441         if (callbackType < 0 || callbackType > CALLBACK_LAST) {
442             throw new IllegalArgumentException("callbackType is invalid");
443         }
444
445         postCallbackDelayedInternal(callbackType, action, token, delayMillis);
446     }
447
448     private void postCallbackDelayedInternal(int callbackType,
449             Object action, Object token, long delayMillis) {
450         if (DEBUG_FRAMES) {
451             Log.d(TAG, "PostCallback: type=" + callbackType
452                     + ", action=" + action + ", token=" + token
453                     + ", delayMillis=" + delayMillis);
454         }
455
456         synchronized (mLock) {
457             final long now = SystemClock.uptimeMillis();
458             final long dueTime = now + delayMillis;
459             mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
460
461             if (dueTime <= now) {
462                 scheduleFrameLocked(now);
463             } else {
464                 Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
465                 msg.arg1 = callbackType;
466                 msg.setAsynchronous(true);
467                 mHandler.sendMessageAtTime(msg, dueTime);
468             }
469         }
470     }
471
472     /**
473      * Removes callbacks that have the specified action and token.
474      *
475      * @param callbackType The callback type.
476      * @param action The action property of the callbacks to remove, or null to remove
477      * callbacks with any action.
478      * @param token The token property of the callbacks to remove, or null to remove
479      * callbacks with any token.
480      *
481      * @see #postCallback
482      * @see #postCallbackDelayed
483      * @hide
484      */
485     @TestApi
486     public void removeCallbacks(int callbackType, Runnable action, Object token) {
487         if (callbackType < 0 || callbackType > CALLBACK_LAST) {
488             throw new IllegalArgumentException("callbackType is invalid");
489         }
490
491         removeCallbacksInternal(callbackType, action, token);
492     }
493
494     private void removeCallbacksInternal(int callbackType, Object action, Object token) {
495         if (DEBUG_FRAMES) {
496             Log.d(TAG, "RemoveCallbacks: type=" + callbackType
497                     + ", action=" + action + ", token=" + token);
498         }
499
500         synchronized (mLock) {
501             mCallbackQueues[callbackType].removeCallbacksLocked(action, token);
502             if (action != null && token == null) {
503                 mHandler.removeMessages(MSG_DO_SCHEDULE_CALLBACK, action);
504             }
505         }
506     }
507
508     /**
509      * Posts a frame callback to run on the next frame.
510      * <p>
511      * The callback runs once then is automatically removed.
512      * </p>
513      *
514      * @param callback The frame callback to run during the next frame.
515      *
516      * @see #postFrameCallbackDelayed
517      * @see #removeFrameCallback
518      */
519     public void postFrameCallback(FrameCallback callback) {
520         postFrameCallbackDelayed(callback, 0);
521     }
522
523     /**
524      * Posts a frame callback to run on the next frame after the specified delay.
525      * <p>
526      * The callback runs once then is automatically removed.
527      * </p>
528      *
529      * @param callback The frame callback to run during the next frame.
530      * @param delayMillis The delay time in milliseconds.
531      *
532      * @see #postFrameCallback
533      * @see #removeFrameCallback
534      */
535     public void postFrameCallbackDelayed(FrameCallback callback, long delayMillis) {
536         if (callback == null) {
537             throw new IllegalArgumentException("callback must not be null");
538         }
539
540         postCallbackDelayedInternal(CALLBACK_ANIMATION,
541                 callback, FRAME_CALLBACK_TOKEN, delayMillis);
542     }
543
544     /**
545      * Removes a previously posted frame callback.
546      *
547      * @param callback The frame callback to remove.
548      *
549      * @see #postFrameCallback
550      * @see #postFrameCallbackDelayed
551      */
552     public void removeFrameCallback(FrameCallback callback) {
553         if (callback == null) {
554             throw new IllegalArgumentException("callback must not be null");
555         }
556
557         removeCallbacksInternal(CALLBACK_ANIMATION, callback, FRAME_CALLBACK_TOKEN);
558     }
559
560     /**
561      * Gets the time when the current frame started.
562      * <p>
563      * This method provides the time in milliseconds when the frame started being rendered.
564      * The frame time provides a stable time base for synchronizing animations
565      * and drawing.  It should be used instead of {@link SystemClock#uptimeMillis()}
566      * or {@link System#nanoTime()} for animations and drawing in the UI.  Using the frame
567      * time helps to reduce inter-frame jitter because the frame time is fixed at the time
568      * the frame was scheduled to start, regardless of when the animations or drawing
569      * callback actually runs.  All callbacks that run as part of rendering a frame will
570      * observe the same frame time so using the frame time also helps to synchronize effects
571      * that are performed by different callbacks.
572      * </p><p>
573      * Please note that the framework already takes care to process animations and
574      * drawing using the frame time as a stable time base.  Most applications should
575      * not need to use the frame time information directly.
576      * </p><p>
577      * This method should only be called from within a callback.
578      * </p>
579      *
580      * @return The frame start time, in the {@link SystemClock#uptimeMillis()} time base.
581      *
582      * @throws IllegalStateException if no frame is in progress.
583      * @hide
584      */
585     @UnsupportedAppUsage
586     public long getFrameTime() {
587         return getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;
588     }
589
590     /**
591      * Same as {@link #getFrameTime()} but with nanosecond precision.
592      *
593      * @return The frame start time, in the {@link System#nanoTime()} time base.
594      *
595      * @throws IllegalStateException if no frame is in progress.
596      * @hide
597      */
598     @UnsupportedAppUsage
599     public long getFrameTimeNanos() {
600         synchronized (mLock) {
601             if (!mCallbacksRunning) {
602                 throw new IllegalStateException("This method must only be called as "
603                         + "part of a callback while a frame is in progress.");
604             }
605             return USE_FRAME_TIME ? mLastFrameTimeNanos : System.nanoTime();
606         }
607     }
608
609     /**
610      * Like {@link #getLastFrameTimeNanos}, but always returns the last frame time, not matter
611      * whether callbacks are currently running.
612      * @return The frame start time of the last frame, in the {@link System#nanoTime()} time base.
613      * @hide
614      */
615     public long getLastFrameTimeNanos() {
616         synchronized (mLock) {
617             return USE_FRAME_TIME ? mLastFrameTimeNanos : System.nanoTime();
618         }
619     }
620
621     private void scheduleFrameLocked(long now) {
622         if (!mFrameScheduled) {
623             mFrameScheduled = true;
624             if (USE_VSYNC) {
625                 if (DEBUG_FRAMES) {
626                     Log.d(TAG, "Scheduling next frame on vsync.");
627                 }
628
629                 // If running on the Looper thread, then schedule the vsync immediately,
630                 // otherwise post a message to schedule the vsync from the UI thread
631                 // as soon as possible.
632                 if (isRunningOnLooperThreadLocked()) {
633                     scheduleVsyncLocked();
634                 } else {
635                     Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
636                     msg.setAsynchronous(true);
637                     mHandler.sendMessageAtFrontOfQueue(msg);
638                 }
639             } else {
640                 final long nextFrameTime = Math.max(
641                         mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
642                 if (DEBUG_FRAMES) {
643                     Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
644                 }
645                 Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
646                 msg.setAsynchronous(true);
647                 mHandler.sendMessageAtTime(msg, nextFrameTime);
648             }
649         }
650     }
651
652     void setFPSDivisor(int divisor) {
653         if (divisor <= 0) divisor = 1;
654         mFPSDivisor = divisor;
655         ThreadedRenderer.setFPSDivisor(divisor);
656     }
657
658     @UnsupportedAppUsage
659     void doFrame(long frameTimeNanos, int frame) {
660         final long startNanos;
661         synchronized (mLock) {
662             if (!mFrameScheduled) {
663                 return; // no work to do
664             }
665
666             if (DEBUG_JANK && mDebugPrintNextFrameTimeDelta) {
667                 mDebugPrintNextFrameTimeDelta = false;
668                 Log.d(TAG, "Frame time delta: "
669                         + ((frameTimeNanos - mLastFrameTimeNanos) * 0.000001f) + " ms");
670             }
671
672             long intendedFrameTimeNanos = frameTimeNanos;
673             startNanos = System.nanoTime();
674             final long jitterNanos = startNanos - frameTimeNanos;
675             if (jitterNanos >= mFrameIntervalNanos) {
676                 final long skippedFrames = jitterNanos / mFrameIntervalNanos;
677                 if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
678                     Log.i(TAG, "Skipped " + skippedFrames + " frames!  "
679                             + "The application may be doing too much work on its main thread.");
680                 }
681                 final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
682                 if (DEBUG_JANK) {
683                     Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms "
684                             + "which is more than the frame interval of "
685                             + (mFrameIntervalNanos * 0.000001f) + " ms!  "
686                             + "Skipping " + skippedFrames + " frames and setting frame "
687                             + "time to " + (lastFrameOffset * 0.000001f) + " ms in the past.");
688                 }
689                 frameTimeNanos = startNanos - lastFrameOffset;
690             }
691
692             if (frameTimeNanos < mLastFrameTimeNanos) {
693                 if (DEBUG_JANK) {
694                     Log.d(TAG, "Frame time appears to be going backwards.  May be due to a "
695                             + "previously skipped frame.  Waiting for next vsync.");
696                 }
697                 scheduleVsyncLocked();
698                 return;
699             }
700
701             if (mFPSDivisor > 1) {
702                 long timeSinceVsync = frameTimeNanos - mLastFrameTimeNanos;
703                 if (timeSinceVsync < (mFrameIntervalNanos * mFPSDivisor) && timeSinceVsync > 0) {
704                     scheduleVsyncLocked();
705                     return;
706                 }
707             }
708
709             mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
710             mFrameScheduled = false;
711             mLastFrameTimeNanos = frameTimeNanos;
712         }
713
714         try {
715             Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");
716             AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
717
718             mFrameInfo.markInputHandlingStart();
719             doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
720
721             mFrameInfo.markAnimationsStart();
722             doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
723             doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos);
724
725             mFrameInfo.markPerformTraversalsStart();
726             doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
727
728             doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
729         } finally {
730             AnimationUtils.unlockAnimationClock();
731             Trace.traceEnd(Trace.TRACE_TAG_VIEW);
732         }
733
734         if (DEBUG_FRAMES) {
735             final long endNanos = System.nanoTime();
736             Log.d(TAG, "Frame " + frame + ": Finished, took "
737                     + (endNanos - startNanos) * 0.000001f + " ms, latency "
738                     + (startNanos - frameTimeNanos) * 0.000001f + " ms.");
739         }
740     }
741
742     void doCallbacks(int callbackType, long frameTimeNanos) {
743         CallbackRecord callbacks;
744         synchronized (mLock) {
745             // We use "now" to determine when callbacks become due because it's possible
746             // for earlier processing phases in a frame to post callbacks that should run
747             // in a following phase, such as an input event that causes an animation to start.
748             final long now = System.nanoTime();
749             callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(
750                     now / TimeUtils.NANOS_PER_MS);
751             if (callbacks == null) {
752                 return;
753             }
754             mCallbacksRunning = true;
755
756             // Update the frame time if necessary when committing the frame.
757             // We only update the frame time if we are more than 2 frames late reaching
758             // the commit phase.  This ensures that the frame time which is observed by the
759             // callbacks will always increase from one frame to the next and never repeat.
760             // We never want the next frame's starting frame time to end up being less than
761             // or equal to the previous frame's commit frame time.  Keep in mind that the
762             // next frame has most likely already been scheduled by now so we play it
763             // safe by ensuring the commit time is always at least one frame behind.
764             if (callbackType == Choreographer.CALLBACK_COMMIT) {
765                 final long jitterNanos = now - frameTimeNanos;
766                 Trace.traceCounter(Trace.TRACE_TAG_VIEW, "jitterNanos", (int) jitterNanos);
767                 if (jitterNanos >= 2 * mFrameIntervalNanos) {
768                     final long lastFrameOffset = jitterNanos % mFrameIntervalNanos
769                             + mFrameIntervalNanos;
770                     if (DEBUG_JANK) {
771                         Log.d(TAG, "Commit callback delayed by " + (jitterNanos * 0.000001f)
772                                 + " ms which is more than twice the frame interval of "
773                                 + (mFrameIntervalNanos * 0.000001f) + " ms!  "
774                                 + "Setting frame time to " + (lastFrameOffset * 0.000001f)
775                                 + " ms in the past.");
776                         mDebugPrintNextFrameTimeDelta = true;
777                     }
778                     frameTimeNanos = now - lastFrameOffset;
779                     mLastFrameTimeNanos = frameTimeNanos;
780                 }
781             }
782         }
783         try {
784             Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]);
785             for (CallbackRecord c = callbacks; c != null; c = c.next) {
786                 if (DEBUG_FRAMES) {
787                     Log.d(TAG, "RunCallback: type=" + callbackType
788                             + ", action=" + c.action + ", token=" + c.token
789                             + ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime));
790                 }
791                 c.run(frameTimeNanos);
792             }
793         } finally {
794             synchronized (mLock) {
795                 mCallbacksRunning = false;
796                 do {
797                     final CallbackRecord next = callbacks.next;
798                     recycleCallbackLocked(callbacks);
799                     callbacks = next;
800                 } while (callbacks != null);
801             }
802             Trace.traceEnd(Trace.TRACE_TAG_VIEW);
803         }
804     }
805
806     void doScheduleVsync() {
807         synchronized (mLock) {
808             if (mFrameScheduled) {
809                 scheduleVsyncLocked();
810             }
811         }
812     }
813
814     void doScheduleCallback(int callbackType) {
815         synchronized (mLock) {
816             if (!mFrameScheduled) {
817                 final long now = SystemClock.uptimeMillis();
818                 if (mCallbackQueues[callbackType].hasDueCallbacksLocked(now)) {
819                     scheduleFrameLocked(now);
820                 }
821             }
822         }
823     }
824
825     @UnsupportedAppUsage
826     private void scheduleVsyncLocked() {
827         mDisplayEventReceiver.scheduleVsync();
828     }
829
830     private boolean isRunningOnLooperThreadLocked() {
831         return Looper.myLooper() == mLooper;
832     }
833
834     private CallbackRecord obtainCallbackLocked(long dueTime, Object action, Object token) {
835         CallbackRecord callback = mCallbackPool;
836         if (callback == null) {
837             callback = new CallbackRecord();
838         } else {
839             mCallbackPool = callback.next;
840             callback.next = null;
841         }
842         callback.dueTime = dueTime;
843         callback.action = action;
844         callback.token = token;
845         return callback;
846     }
847
848     private void recycleCallbackLocked(CallbackRecord callback) {
849         callback.action = null;
850         callback.token = null;
851         callback.next = mCallbackPool;
852         mCallbackPool = callback;
853     }
854
855     /**
856      * Implement this interface to receive a callback when a new display frame is
857      * being rendered.  The callback is invoked on the {@link Looper} thread to
858      * which the {@link Choreographer} is attached.
859      */
860     public interface FrameCallback {
861         /**
862          * Called when a new display frame is being rendered.
863          * <p>
864          * This method provides the time in nanoseconds when the frame started being rendered.
865          * The frame time provides a stable time base for synchronizing animations
866          * and drawing.  It should be used instead of {@link SystemClock#uptimeMillis()}
867          * or {@link System#nanoTime()} for animations and drawing in the UI.  Using the frame
868          * time helps to reduce inter-frame jitter because the frame time is fixed at the time
869          * the frame was scheduled to start, regardless of when the animations or drawing
870          * callback actually runs.  All callbacks that run as part of rendering a frame will
871          * observe the same frame time so using the frame time also helps to synchronize effects
872          * that are performed by different callbacks.
873          * </p><p>
874          * Please note that the framework already takes care to process animations and
875          * drawing using the frame time as a stable time base.  Most applications should
876          * not need to use the frame time information directly.
877          * </p>
878          *
879          * @param frameTimeNanos The time in nanoseconds when the frame started being rendered,
880          * in the {@link System#nanoTime()} timebase.  Divide this value by {@code 1000000}
881          * to convert it to the {@link SystemClock#uptimeMillis()} time base.
882          */
883         public void doFrame(long frameTimeNanos);
884     }
885
886     private final class FrameHandler extends Handler {
887         public FrameHandler(Looper looper) {
888             super(looper);
889         }
890
891         @Override
892         public void handleMessage(Message msg) {
893             switch (msg.what) {
894                 case MSG_DO_FRAME:
895                     doFrame(System.nanoTime(), 0);
896                     break;
897                 case MSG_DO_SCHEDULE_VSYNC:
898                     doScheduleVsync();
899                     break;
900                 case MSG_DO_SCHEDULE_CALLBACK:
901                     doScheduleCallback(msg.arg1);
902                     break;
903             }
904         }
905     }
906
907     private final class FrameDisplayEventReceiver extends DisplayEventReceiver
908             implements Runnable {
909         private boolean mHavePendingVsync;
910         private long mTimestampNanos;
911         private int mFrame;
912
913         public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
914             super(looper, vsyncSource, CONFIG_CHANGED_EVENT_SUPPRESS);
915         }
916
917         // TODO(b/116025192): physicalDisplayId is ignored because SF only emits VSYNC events for
918         // the internal display and DisplayEventReceiver#scheduleVsync only allows requesting VSYNC
919         // for the internal display implicitly.
920         @Override
921         public void onVsync(long timestampNanos, long physicalDisplayId, int frame) {
922             // Post the vsync event to the Handler.
923             // The idea is to prevent incoming vsync events from completely starving
924             // the message queue.  If there are no messages in the queue with timestamps
925             // earlier than the frame time, then the vsync event will be processed immediately.
926             // Otherwise, messages that predate the vsync event will be handled first.
927             long now = System.nanoTime();
928             if (timestampNanos > now) {
929                 Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)
930                         + " ms in the future!  Check that graphics HAL is generating vsync "
931                         + "timestamps using the correct timebase.");
932                 timestampNanos = now;
933             }
934
935             if (mHavePendingVsync) {
936                 Log.w(TAG, "Already have a pending vsync event.  There should only be "
937                         + "one at a time.");
938             } else {
939                 mHavePendingVsync = true;
940             }
941
942             mTimestampNanos = timestampNanos;
943             mFrame = frame;
944             Message msg = Message.obtain(mHandler, this);
945             msg.setAsynchronous(true);
946             mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
947         }
948
949         @Override
950         public void run() {
951             mHavePendingVsync = false;
952             doFrame(mTimestampNanos, mFrame);
953         }
954     }
955
956     private static final class CallbackRecord {
957         public CallbackRecord next;
958         public long dueTime;
959         public Object action; // Runnable or FrameCallback
960         public Object token;
961
962         @UnsupportedAppUsage
963         public void run(long frameTimeNanos) {
964             if (token == FRAME_CALLBACK_TOKEN) {
965                 ((FrameCallback)action).doFrame(frameTimeNanos);
966             } else {
967                 ((Runnable)action).run();
968             }
969         }
970     }
971
972     private final class CallbackQueue {
973         private CallbackRecord mHead;
974
975         public boolean hasDueCallbacksLocked(long now) {
976             return mHead != null && mHead.dueTime <= now;
977         }
978
979         public CallbackRecord extractDueCallbacksLocked(long now) {
980             CallbackRecord callbacks = mHead;
981             if (callbacks == null || callbacks.dueTime > now) {
982                 return null;
983             }
984
985             CallbackRecord last = callbacks;
986             CallbackRecord next = last.next;
987             while (next != null) {
988                 if (next.dueTime > now) {
989                     last.next = null;
990                     break;
991                 }
992                 last = next;
993                 next = next.next;
994             }
995             mHead = next;
996             return callbacks;
997         }
998
999         @UnsupportedAppUsage
1000         public void addCallbackLocked(long dueTime, Object action, Object token) {
1001             CallbackRecord callback = obtainCallbackLocked(dueTime, action, token);
1002             CallbackRecord entry = mHead;
1003             if (entry == null) {
1004                 mHead = callback;
1005                 return;
1006             }
1007             if (dueTime < entry.dueTime) {
1008                 callback.next = entry;
1009                 mHead = callback;
1010                 return;
1011             }
1012             while (entry.next != null) {
1013                 if (dueTime < entry.next.dueTime) {
1014                     callback.next = entry.next;
1015                     break;
1016                 }
1017                 entry = entry.next;
1018             }
1019             entry.next = callback;
1020         }
1021
1022         public void removeCallbacksLocked(Object action, Object token) {
1023             CallbackRecord predecessor = null;
1024             for (CallbackRecord callback = mHead; callback != null;) {
1025                 final CallbackRecord next = callback.next;
1026                 if ((action == null || callback.action == action)
1027                         && (token == null || callback.token == token)) {
1028                     if (predecessor != null) {
1029                         predecessor.next = next;
1030                     } else {
1031                         mHead = next;
1032                     }
1033                     recycleCallbackLocked(callback);
1034                 } else {
1035                     predecessor = callback;
1036                 }
1037                 callback = next;
1038             }
1039         }
1040     }
1041 }