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;
20import android.view.Window;
21
22import java.lang.annotation.Retention;
23import 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 */
32public 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    private static final int FRAME_INFO_FLAG_FIRST_DRAW = 1 << 0;
137
138    /**
139     * Identifiers for metrics available for each frame.
140     *
141     * {@see {@link #getMetric(int)}}
142     * @hide
143     */
144    @IntDef({
145            UNKNOWN_DELAY_DURATION,
146            INPUT_HANDLING_DURATION,
147            ANIMATION_DURATION,
148            LAYOUT_MEASURE_DURATION,
149            DRAW_DURATION,
150            SYNC_DURATION,
151            COMMAND_ISSUE_DURATION,
152            SWAP_BUFFERS_DURATION,
153            TOTAL_DURATION,
154            FIRST_DRAW_FRAME,
155    })
156    @Retention(RetentionPolicy.SOURCE)
157    public @interface Metric {}
158
159    /**
160     * Timestamp indices for frame milestones.
161     *
162     * May change from release to release.
163     *
164     * Must be kept in sync with frameworks/base/libs/hwui/FrameInfo.h.
165     *
166     * @hide
167     */
168    @IntDef ({
169            Index.FLAGS,
170            Index.INTENDED_VSYNC,
171            Index.VSYNC,
172            Index.OLDEST_INPUT_EVENT,
173            Index.NEWEST_INPUT_EVENT,
174            Index.HANDLE_INPUT_START,
175            Index.ANIMATION_START,
176            Index.PERFORM_TRAVERSALS_START,
177            Index.DRAW_START,
178            Index.SYNC_QUEUED,
179            Index.SYNC_START,
180            Index.ISSUE_DRAW_COMMANDS_START,
181            Index.SWAP_BUFFERS,
182            Index.FRAME_COMPLETED,
183    })
184    @Retention(RetentionPolicy.SOURCE)
185    private @interface Index {
186        int FLAGS = 0;
187        int INTENDED_VSYNC = 1;
188        int VSYNC = 2;
189        int OLDEST_INPUT_EVENT = 3;
190        int NEWEST_INPUT_EVENT = 4;
191        int HANDLE_INPUT_START = 5;
192        int ANIMATION_START = 6;
193        int PERFORM_TRAVERSALS_START = 7;
194        int DRAW_START = 8;
195        int SYNC_QUEUED = 9;
196        int SYNC_START = 10;
197        int ISSUE_DRAW_COMMANDS_START = 11;
198        int SWAP_BUFFERS = 12;
199        int FRAME_COMPLETED = 13;
200
201        int FRAME_STATS_COUNT = 14; // must always be last
202    }
203
204    /*
205     * Bucket endpoints for each Metric defined above.
206     *
207     * Each defined metric *must* have a corresponding entry
208     * in this list.
209     */
210    private static final int[] DURATIONS = new int[] {
211        // UNKNOWN_DELAY
212        Index.INTENDED_VSYNC, Index.HANDLE_INPUT_START,
213        // INPUT_HANDLING
214        Index.HANDLE_INPUT_START, Index.ANIMATION_START,
215        // ANIMATION
216        Index.ANIMATION_START, Index.PERFORM_TRAVERSALS_START,
217        // LAYOUT_MEASURE
218        Index.PERFORM_TRAVERSALS_START, Index.DRAW_START,
219        // DRAW
220        Index.DRAW_START, Index.SYNC_QUEUED,
221        // SYNC
222        Index.SYNC_START, Index.ISSUE_DRAW_COMMANDS_START,
223        // COMMAND_ISSUE
224        Index.ISSUE_DRAW_COMMANDS_START, Index.SWAP_BUFFERS,
225        // SWAP_BUFFERS
226        Index.SWAP_BUFFERS, Index.FRAME_COMPLETED,
227        // TOTAL_DURATION
228        Index.INTENDED_VSYNC, Index.FRAME_COMPLETED,
229    };
230
231    /* package */ final long[] mTimingData;
232
233    /**
234     * Constructs a FrameMetrics object as a copy.
235     * <p>
236     * Use this method to copy out metrics reported by
237     * {@link Window.OnFrameMetricsAvailableListener#onFrameMetricsAvailable(
238     * Window, FrameMetrics, int)}
239     * </p>
240     * @param other the FrameMetrics object to copy.
241     */
242    public FrameMetrics(FrameMetrics other) {
243        mTimingData = new long[Index.FRAME_STATS_COUNT];
244        System.arraycopy(other.mTimingData, 0, mTimingData, 0, mTimingData.length);
245    }
246
247    /**
248     * @hide
249     */
250    FrameMetrics() {
251        mTimingData = new long[Index.FRAME_STATS_COUNT];
252    }
253
254    /**
255     * Retrieves the value associated with Metric identifier {@code id}
256     * for this frame.
257     * <p>
258     * Boolean metrics are represented in [0,1], with 0 corresponding to
259     * false, and 1 corresponding to true.
260     * </p>
261     * @param id the metric to retrieve
262     * @return the value of the metric or -1 if it is not available.
263     */
264    public long getMetric(@Metric int id) {
265        if (id < UNKNOWN_DELAY_DURATION || id > FIRST_DRAW_FRAME) {
266            return -1;
267        }
268
269        if (mTimingData == null) {
270            return -1;
271        }
272
273        if (id == FIRST_DRAW_FRAME) {
274            return (mTimingData[Index.FLAGS] & FRAME_INFO_FLAG_FIRST_DRAW) != 0 ? 1 : 0;
275        }
276
277        int durationsIdx = 2 * id;
278        return mTimingData[DURATIONS[durationsIdx + 1]]
279                - mTimingData[DURATIONS[durationsIdx]];
280    }
281}
282
283