1 /*
2  * Copyright (C) 2016 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 android.annotation.IntDef;
20 
21 import java.lang.annotation.Retention;
22 import java.lang.annotation.RetentionPolicy;
23 
24 /**
25  * Class containing timing data for various milestones in a frame
26  * lifecycle reported by the rendering subsystem.
27  * <p>
28  * Supported metrics can be queried via their corresponding identifier.
29  * </p>
30  */
31 public final class FrameMetrics {
32 
33     /**
34      * Metric identifier for unknown delay.
35      * <p>
36      * Represents the number of nanoseconds elapsed waiting for the
37      * UI thread to become responsive and process the frame. This
38      * should be 0 most of the time.
39      * </p>
40      */
41     public static final int UNKNOWN_DELAY_DURATION = 0;
42 
43     /**
44      * Metric identifier for input handling duration.
45      * <p>
46      * Represents the number of nanoseconds elapsed issuing
47      * input handling callbacks.
48      * </p>
49      */
50     public static final int INPUT_HANDLING_DURATION = 1;
51 
52     /**
53      * Metric identifier for animation callback duration.
54      * <p>
55      * Represents the number of nanoseconds elapsed issuing
56      * animation callbacks.
57      * </p>
58      */
59     public static final int ANIMATION_DURATION = 2;
60 
61     /**
62      * Metric identifier for layout/measure duration.
63      * <p>
64      * Represents the number of nanoseconds elapsed measuring
65      * and laying out the invalidated pieces of the view hierarchy.
66      * </p>
67      */
68     public static final int LAYOUT_MEASURE_DURATION = 3;
69     /**
70      * Metric identifier for draw duration.
71      * <p>
72      * Represents the number of nanoseconds elapsed computing
73      * DisplayLists for transformations applied to the view
74      * hierarchy.
75      * </p>
76      */
77     public static final int DRAW_DURATION = 4;
78 
79     /**
80      * Metric identifier for sync duration.
81      * <p>
82      * Represents the number of nanoseconds elapsed
83      * synchronizing the computed display lists with the render
84      * thread.
85      * </p>
86      */
87     public static final int SYNC_DURATION = 5;
88 
89     /**
90      * Metric identifier for command issue duration.
91      * <p>
92      * Represents the number of nanoseconds elapsed
93      * issuing draw commands to the GPU.
94      * </p>
95      */
96     public static final int COMMAND_ISSUE_DURATION = 6;
97 
98     /**
99      * Metric identifier for swap buffers duration.
100      * <p>
101      * Represents the number of nanoseconds elapsed issuing
102      * the frame buffer for this frame to the display
103      * subsystem.
104      * </p>
105      */
106     public static final int SWAP_BUFFERS_DURATION = 7;
107 
108     /**
109      * Metric identifier for total frame duration.
110      * <p>
111      * Represents the total time in nanoseconds this frame took to render
112      * and be issued to the display subsystem.
113      * </p>
114      * <p>
115      * Equal to the sum of the values of all other time-valued metric
116      * identifiers.
117      * </p>
118      */
119     public static final int TOTAL_DURATION = 8;
120 
121     /**
122      * Metric identifier for a boolean value determining whether this frame was
123      * the first to draw in a new Window layout.
124      * <p>
125      * {@link #getMetric(int)} will return 0 for false, 1 for true.
126      * </p>
127      * <p>
128      * First draw frames are expected to be slow and should usually be exempt
129      * from display jank calculations as they do not cause skips in animations
130      * and are usually hidden by window animations or other tricks.
131      * </p>
132      */
133     public static final int FIRST_DRAW_FRAME = 9;
134 
135     /**
136      * Metric identifier for the timestamp of the intended vsync for this frame.
137      * <p>
138      * The intended start point for the frame. If this value is different from
139      * {@link #VSYNC_TIMESTAMP}, there was work occurring on the UI thread that
140      * prevented it from responding to the vsync signal in a timely fashion.
141      * </p>
142      */
143     public static final int INTENDED_VSYNC_TIMESTAMP = 10;
144 
145     /**
146      * Metric identifier for the timestamp of the actual vsync for this frame.
147      * <p>
148      * The time value that was used in all the vsync listeners and drawing for
149      * the frame (Choreographer frame callbacks, animations,
150      * {@link View#getDrawingTime()}, etc…)
151      * </p>
152      */
153     public static final int VSYNC_TIMESTAMP = 11;
154 
155     private static final int FRAME_INFO_FLAG_FIRST_DRAW = 1 << 0;
156 
157     /**
158      * Identifiers for metrics available for each frame.
159      *
160      * {@see #getMetric(int)}
161      * @hide
162      */
163     @IntDef({
164             UNKNOWN_DELAY_DURATION,
165             INPUT_HANDLING_DURATION,
166             ANIMATION_DURATION,
167             LAYOUT_MEASURE_DURATION,
168             DRAW_DURATION,
169             SYNC_DURATION,
170             COMMAND_ISSUE_DURATION,
171             SWAP_BUFFERS_DURATION,
172             TOTAL_DURATION,
173             FIRST_DRAW_FRAME,
174             INTENDED_VSYNC_TIMESTAMP,
175             VSYNC_TIMESTAMP,
176     })
177     @Retention(RetentionPolicy.SOURCE)
178     public @interface Metric {}
179 
180     /**
181      * Timestamp indices for frame milestones.
182      *
183      * May change from release to release.
184      *
185      * Must be kept in sync with frameworks/base/libs/hwui/FrameInfo.h.
186      *
187      * @hide
188      */
189     @IntDef ({
190             Index.FLAGS,
191             Index.INTENDED_VSYNC,
192             Index.VSYNC,
193             Index.OLDEST_INPUT_EVENT,
194             Index.NEWEST_INPUT_EVENT,
195             Index.HANDLE_INPUT_START,
196             Index.ANIMATION_START,
197             Index.PERFORM_TRAVERSALS_START,
198             Index.DRAW_START,
199             Index.SYNC_QUEUED,
200             Index.SYNC_START,
201             Index.ISSUE_DRAW_COMMANDS_START,
202             Index.SWAP_BUFFERS,
203             Index.FRAME_COMPLETED,
204     })
205     @Retention(RetentionPolicy.SOURCE)
206     private @interface Index {
207         int FLAGS = 0;
208         int INTENDED_VSYNC = 1;
209         int VSYNC = 2;
210         int OLDEST_INPUT_EVENT = 3;
211         int NEWEST_INPUT_EVENT = 4;
212         int HANDLE_INPUT_START = 5;
213         int ANIMATION_START = 6;
214         int PERFORM_TRAVERSALS_START = 7;
215         int DRAW_START = 8;
216         int SYNC_QUEUED = 9;
217         int SYNC_START = 10;
218         int ISSUE_DRAW_COMMANDS_START = 11;
219         int SWAP_BUFFERS = 12;
220         int FRAME_COMPLETED = 13;
221 
222         int FRAME_STATS_COUNT = 16; // must always be last
223     }
224 
225     /*
226      * Bucket endpoints for each Metric defined above.
227      *
228      * Each defined metric *must* have a corresponding entry
229      * in this list.
230      */
231     private static final int[] DURATIONS = new int[] {
232         // UNKNOWN_DELAY
233         Index.INTENDED_VSYNC, Index.HANDLE_INPUT_START,
234         // INPUT_HANDLING
235         Index.HANDLE_INPUT_START, Index.ANIMATION_START,
236         // ANIMATION
237         Index.ANIMATION_START, Index.PERFORM_TRAVERSALS_START,
238         // LAYOUT_MEASURE
239         Index.PERFORM_TRAVERSALS_START, Index.DRAW_START,
240         // DRAW
241         Index.DRAW_START, Index.SYNC_QUEUED,
242         // SYNC
243         Index.SYNC_START, Index.ISSUE_DRAW_COMMANDS_START,
244         // COMMAND_ISSUE
245         Index.ISSUE_DRAW_COMMANDS_START, Index.SWAP_BUFFERS,
246         // SWAP_BUFFERS
247         Index.SWAP_BUFFERS, Index.FRAME_COMPLETED,
248         // TOTAL_DURATION
249         Index.INTENDED_VSYNC, Index.FRAME_COMPLETED,
250     };
251 
252     /* package */ final long[] mTimingData;
253 
254     /**
255      * Constructs a FrameMetrics object as a copy.
256      * <p>
257      * Use this method to copy out metrics reported by
258      * {@link Window.OnFrameMetricsAvailableListener#onFrameMetricsAvailable(
259      * Window, FrameMetrics, int)}
260      * </p>
261      * @param other the FrameMetrics object to copy.
262      */
FrameMetrics(FrameMetrics other)263     public FrameMetrics(FrameMetrics other) {
264         mTimingData = new long[Index.FRAME_STATS_COUNT];
265         System.arraycopy(other.mTimingData, 0, mTimingData, 0, mTimingData.length);
266     }
267 
268     /**
269      * @hide
270      */
FrameMetrics()271     FrameMetrics() {
272         mTimingData = new long[Index.FRAME_STATS_COUNT];
273     }
274 
275     /**
276      * Retrieves the value associated with Metric identifier {@code id}
277      * for this frame.
278      * <p>
279      * Boolean metrics are represented in [0,1], with 0 corresponding to
280      * false, and 1 corresponding to true.
281      * </p>
282      * @param id the metric to retrieve
283      * @return the value of the metric or -1 if it is not available.
284      */
getMetric(@etric int id)285     public long getMetric(@Metric int id) {
286         if (id < UNKNOWN_DELAY_DURATION || id > VSYNC_TIMESTAMP) {
287             return -1;
288         }
289 
290         if (mTimingData == null) {
291             return -1;
292         }
293 
294         if (id == FIRST_DRAW_FRAME) {
295             return (mTimingData[Index.FLAGS] & FRAME_INFO_FLAG_FIRST_DRAW) != 0 ? 1 : 0;
296         } else if (id == INTENDED_VSYNC_TIMESTAMP) {
297             return mTimingData[Index.INTENDED_VSYNC];
298         } else if (id == VSYNC_TIMESTAMP) {
299             return mTimingData[Index.VSYNC];
300         }
301 
302         int durationsIdx = 2 * id;
303         return mTimingData[DURATIONS[durationsIdx + 1]]
304                 - mTimingData[DURATIONS[durationsIdx]];
305     }
306 }
307 
308