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