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