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
17package android.view;
18
19import android.annotation.IntDef;
20
21import java.lang.annotation.Retention;
22import 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 */
31public 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     */
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     */
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     */
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