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 * Equal to the sum of the values of all other time-valued metric 120 * identifiers. 121 * </p> 122 */ 123 public static final int TOTAL_DURATION = 8; 124 125 /** 126 * Metric identifier for a boolean value determining whether this frame was 127 * the first to draw in a new Window layout. 128 * <p> 129 * {@link #getMetric(int)} will return 0 for false, 1 for true. 130 * </p> 131 * <p> 132 * First draw frames are expected to be slow and should usually be exempt 133 * from display jank calculations as they do not cause skips in animations 134 * and are usually hidden by window animations or other tricks. 135 * </p> 136 */ 137 public static final int FIRST_DRAW_FRAME = 9; 138 139 /** 140 * Metric identifier for the timestamp of the intended vsync for this frame. 141 * <p> 142 * The intended start point for the frame. If this value is different from 143 * {@link #VSYNC_TIMESTAMP}, there was work occurring on the UI thread that 144 * prevented it from responding to the vsync signal in a timely fashion. 145 * </p> 146 */ 147 public static final int INTENDED_VSYNC_TIMESTAMP = 10; 148 149 /** 150 * Metric identifier for the timestamp of the actual vsync for this frame. 151 * <p> 152 * The time value that was used in all the vsync listeners and drawing for 153 * the frame (Choreographer frame callbacks, animations, 154 * {@link View#getDrawingTime()}, etc.) 155 * </p> 156 */ 157 public static final int VSYNC_TIMESTAMP = 11; 158 159 /** 160 * Metric identifier for GPU duration. 161 * <p> 162 * Represents the total time in nanoseconds this frame took to complete on the GPU. 163 * </p> 164 **/ 165 public static final int GPU_DURATION = 12; 166 167 /** 168 * Metric identifier for the total duration that was available to the app to produce a frame. 169 * <p> 170 * Represents the total time in nanoseconds the system allocated for the app to produce its 171 * frame. If FrameMetrics.TOTAL_DURATION < FrameMetrics.DEADLINE, the app hit its intended 172 * deadline and there was no jank visible to the user. 173 * </p> 174 **/ 175 public static final int DEADLINE = 13; 176 177 /** 178 * Identifiers for metrics available for each frame. 179 * 180 * {@see #getMetric(int)} 181 * @hide 182 */ 183 @IntDef({ 184 UNKNOWN_DELAY_DURATION, 185 INPUT_HANDLING_DURATION, 186 ANIMATION_DURATION, 187 LAYOUT_MEASURE_DURATION, 188 DRAW_DURATION, 189 SYNC_DURATION, 190 COMMAND_ISSUE_DURATION, 191 SWAP_BUFFERS_DURATION, 192 TOTAL_DURATION, 193 FIRST_DRAW_FRAME, 194 INTENDED_VSYNC_TIMESTAMP, 195 VSYNC_TIMESTAMP, 196 GPU_DURATION, 197 DEADLINE, 198 }) 199 @Retention(RetentionPolicy.SOURCE) 200 public @interface Metric {} 201 202 /** 203 * Timestamp indices for frame milestones. 204 * 205 * May change from release to release. 206 * 207 * Must be kept in sync with frameworks/base/libs/hwui/FrameInfo.h. 208 * 209 * @hide 210 */ 211 @IntDef ({ 212 Index.FLAGS, 213 Index.FRAME_TIMELINE_VSYNC_ID, 214 Index.INTENDED_VSYNC, 215 Index.VSYNC, 216 Index.INPUT_EVENT_ID, 217 Index.HANDLE_INPUT_START, 218 Index.ANIMATION_START, 219 Index.PERFORM_TRAVERSALS_START, 220 Index.DRAW_START, 221 Index.FRAME_DEADLINE, 222 Index.SYNC_QUEUED, 223 Index.SYNC_START, 224 Index.ISSUE_DRAW_COMMANDS_START, 225 Index.SWAP_BUFFERS, 226 Index.FRAME_COMPLETED, 227 Index.DEQUEUE_BUFFER_DURATION, 228 Index.QUEUE_BUFFER_DURATION, 229 Index.GPU_COMPLETED, 230 Index.SWAP_BUFFERS_COMPLETED, 231 Index.DISPLAY_PRESENT_TIME, 232 }) 233 @Retention(RetentionPolicy.SOURCE) 234 public @interface Index { 235 int FLAGS = 0; 236 int FRAME_TIMELINE_VSYNC_ID = 1; 237 int INTENDED_VSYNC = 2; 238 int VSYNC = 3; 239 int INPUT_EVENT_ID = 4; 240 int HANDLE_INPUT_START = 5; 241 int ANIMATION_START = 6; 242 int PERFORM_TRAVERSALS_START = 7; 243 int DRAW_START = 8; 244 int FRAME_DEADLINE = 9; 245 int FRAME_START_TIME = 10; 246 int FRAME_INTERVAL = 11; 247 int SYNC_QUEUED = 12; 248 int SYNC_START = 13; 249 int ISSUE_DRAW_COMMANDS_START = 14; 250 int SWAP_BUFFERS = 15; 251 int FRAME_COMPLETED = 16; 252 int DEQUEUE_BUFFER_DURATION = 17; 253 int QUEUE_BUFFER_DURATION = 18; 254 int GPU_COMPLETED = 19; 255 int SWAP_BUFFERS_COMPLETED = 20; 256 int DISPLAY_PRESENT_TIME = 21; 257 258 int FRAME_STATS_COUNT = 22; // must always be last and in sync with 259 // FrameInfoIndex::NumIndexes in libs/hwui/FrameInfo.h 260 } 261 262 /* 263 * Bucket endpoints for each Metric defined above. 264 * 265 * Each defined metric *must* have a corresponding entry 266 * in this list. 267 */ 268 private static final int[] DURATIONS = new int[] { 269 // UNKNOWN_DELAY 270 Index.INTENDED_VSYNC, Index.HANDLE_INPUT_START, 271 // INPUT_HANDLING 272 Index.HANDLE_INPUT_START, Index.ANIMATION_START, 273 // ANIMATION 274 Index.ANIMATION_START, Index.PERFORM_TRAVERSALS_START, 275 // LAYOUT_MEASURE 276 Index.PERFORM_TRAVERSALS_START, Index.DRAW_START, 277 // DRAW 278 Index.DRAW_START, Index.SYNC_QUEUED, 279 // SYNC 280 Index.SYNC_START, Index.ISSUE_DRAW_COMMANDS_START, 281 // COMMAND_ISSUE 282 Index.ISSUE_DRAW_COMMANDS_START, Index.SWAP_BUFFERS, 283 // SWAP_BUFFERS 284 Index.SWAP_BUFFERS, Index.SWAP_BUFFERS_COMPLETED, 285 // TOTAL_DURATION 286 Index.INTENDED_VSYNC, Index.FRAME_COMPLETED, 287 // RESERVED for FIRST_DRAW_FRAME 288 0, 0, 289 // RESERVED forINTENDED_VSYNC_TIMESTAMP 290 0, 0, 291 // RESERVED VSYNC_TIMESTAMP 292 0, 0, 293 // GPU_DURATION 294 Index.SWAP_BUFFERS, Index.GPU_COMPLETED, 295 // DEADLINE 296 Index.INTENDED_VSYNC, Index.FRAME_DEADLINE, 297 }; 298 299 /** 300 * @hide 301 */ 302 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 303 public final long[] mTimingData; 304 305 /** 306 * Constructs a FrameMetrics object as a copy. 307 * <p> 308 * Use this method to copy out metrics reported by 309 * {@link Window.OnFrameMetricsAvailableListener#onFrameMetricsAvailable( 310 * Window, FrameMetrics, int)} 311 * </p> 312 * @param other the FrameMetrics object to copy. 313 */ FrameMetrics(FrameMetrics other)314 public FrameMetrics(FrameMetrics other) { 315 mTimingData = new long[Index.FRAME_STATS_COUNT]; 316 System.arraycopy(other.mTimingData, 0, mTimingData, 0, mTimingData.length); 317 } 318 319 /** 320 * @hide 321 */ FrameMetrics()322 public FrameMetrics() { 323 mTimingData = new long[Index.FRAME_STATS_COUNT]; 324 } 325 326 /** 327 * Retrieves the value associated with Metric identifier {@code id} 328 * for this frame. 329 * <p> 330 * Boolean metrics are represented in [0,1], with 0 corresponding to 331 * false, and 1 corresponding to true. 332 * </p> 333 * @param id the metric to retrieve 334 * @return the value of the metric or -1 if it is not available. 335 */ getMetric(@etric int id)336 public long getMetric(@Metric int id) { 337 if (id < UNKNOWN_DELAY_DURATION || id > DEADLINE) { 338 return -1; 339 } 340 341 if (mTimingData == null) { 342 return -1; 343 } 344 345 if (id == FIRST_DRAW_FRAME) { 346 return (mTimingData[Index.FLAGS] & FLAG_WINDOW_VISIBILITY_CHANGED) != 0 ? 1 : 0; 347 } else if (id == INTENDED_VSYNC_TIMESTAMP) { 348 return mTimingData[Index.INTENDED_VSYNC]; 349 } else if (id == VSYNC_TIMESTAMP) { 350 return mTimingData[Index.VSYNC]; 351 } 352 353 int durationsIdx = 2 * id; 354 return mTimingData[DURATIONS[durationsIdx + 1]] 355 - mTimingData[DURATIONS[durationsIdx]]; 356 } 357 } 358 359