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