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