diff options
Diffstat (limited to 'android/view/FrameMetrics.java')
-rw-r--r-- | android/view/FrameMetrics.java | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/android/view/FrameMetrics.java b/android/view/FrameMetrics.java new file mode 100644 index 00000000..358a2d1e --- /dev/null +++ b/android/view/FrameMetrics.java @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Class containing timing data for various milestones in a frame + * lifecycle reported by the rendering subsystem. + * <p> + * Supported metrics can be queried via their corresponding identifier. + * </p> + */ +public final class FrameMetrics { + + /** + * Metric identifier for unknown delay. + * <p> + * Represents the number of nanoseconds elapsed waiting for the + * UI thread to become responsive and process the frame. This + * should be 0 most of the time. + * </p> + */ + public static final int UNKNOWN_DELAY_DURATION = 0; + + /** + * Metric identifier for input handling duration. + * <p> + * Represents the number of nanoseconds elapsed issuing + * input handling callbacks. + * </p> + */ + public static final int INPUT_HANDLING_DURATION = 1; + + /** + * Metric identifier for animation callback duration. + * <p> + * Represents the number of nanoseconds elapsed issuing + * animation callbacks. + * </p> + */ + public static final int ANIMATION_DURATION = 2; + + /** + * Metric identifier for layout/measure duration. + * <p> + * Represents the number of nanoseconds elapsed measuring + * and laying out the invalidated pieces of the view hierarchy. + * </p> + */ + public static final int LAYOUT_MEASURE_DURATION = 3; + /** + * Metric identifier for draw duration. + * <p> + * Represents the number of nanoseconds elapsed computing + * DisplayLists for transformations applied to the view + * hierarchy. + * </p> + */ + public static final int DRAW_DURATION = 4; + + /** + * Metric identifier for sync duration. + * <p> + * Represents the number of nanoseconds elapsed + * synchronizing the computed display lists with the render + * thread. + * </p> + */ + public static final int SYNC_DURATION = 5; + + /** + * Metric identifier for command issue duration. + * <p> + * Represents the number of nanoseconds elapsed + * issuing draw commands to the GPU. + * </p> + */ + public static final int COMMAND_ISSUE_DURATION = 6; + + /** + * Metric identifier for swap buffers duration. + * <p> + * Represents the number of nanoseconds elapsed issuing + * the frame buffer for this frame to the display + * subsystem. + * </p> + */ + public static final int SWAP_BUFFERS_DURATION = 7; + + /** + * Metric identifier for total frame duration. + * <p> + * Represents the total time in nanoseconds this frame took to render + * and be issued to the display subsystem. + * </p> + * <p> + * Equal to the sum of the values of all other time-valued metric + * identifiers. + * </p> + */ + public static final int TOTAL_DURATION = 8; + + /** + * Metric identifier for a boolean value determining whether this frame was + * the first to draw in a new Window layout. + * <p> + * {@link #getMetric(int)} will return 0 for false, 1 for true. + * </p> + * <p> + * First draw frames are expected to be slow and should usually be exempt + * from display jank calculations as they do not cause skips in animations + * and are usually hidden by window animations or other tricks. + * </p> + */ + public static final int FIRST_DRAW_FRAME = 9; + + /** + * Metric identifier for the timestamp of the intended vsync for this frame. + * <p> + * The intended start point for the frame. If this value is different from + * {@link #VSYNC_TIMESTAMP}, there was work occurring on the UI thread that + * prevented it from responding to the vsync signal in a timely fashion. + * </p> + */ + public static final int INTENDED_VSYNC_TIMESTAMP = 10; + + /** + * Metric identifier for the timestamp of the actual vsync for this frame. + * <p> + * The time value that was used in all the vsync listeners and drawing for + * the frame (Choreographer frame callbacks, animations, + * {@link View#getDrawingTime()}, etc…) + * </p> + */ + public static final int VSYNC_TIMESTAMP = 11; + + private static final int FRAME_INFO_FLAG_FIRST_DRAW = 1 << 0; + + /** + * Identifiers for metrics available for each frame. + * + * {@see #getMetric(int)} + * @hide + */ + @IntDef({ + UNKNOWN_DELAY_DURATION, + INPUT_HANDLING_DURATION, + ANIMATION_DURATION, + LAYOUT_MEASURE_DURATION, + DRAW_DURATION, + SYNC_DURATION, + COMMAND_ISSUE_DURATION, + SWAP_BUFFERS_DURATION, + TOTAL_DURATION, + FIRST_DRAW_FRAME, + INTENDED_VSYNC_TIMESTAMP, + VSYNC_TIMESTAMP, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Metric {} + + /** + * Timestamp indices for frame milestones. + * + * May change from release to release. + * + * Must be kept in sync with frameworks/base/libs/hwui/FrameInfo.h. + * + * @hide + */ + @IntDef ({ + Index.FLAGS, + Index.INTENDED_VSYNC, + Index.VSYNC, + Index.OLDEST_INPUT_EVENT, + Index.NEWEST_INPUT_EVENT, + Index.HANDLE_INPUT_START, + Index.ANIMATION_START, + Index.PERFORM_TRAVERSALS_START, + Index.DRAW_START, + Index.SYNC_QUEUED, + Index.SYNC_START, + Index.ISSUE_DRAW_COMMANDS_START, + Index.SWAP_BUFFERS, + Index.FRAME_COMPLETED, + }) + @Retention(RetentionPolicy.SOURCE) + private @interface Index { + int FLAGS = 0; + int INTENDED_VSYNC = 1; + int VSYNC = 2; + int OLDEST_INPUT_EVENT = 3; + int NEWEST_INPUT_EVENT = 4; + int HANDLE_INPUT_START = 5; + int ANIMATION_START = 6; + int PERFORM_TRAVERSALS_START = 7; + int DRAW_START = 8; + int SYNC_QUEUED = 9; + int SYNC_START = 10; + int ISSUE_DRAW_COMMANDS_START = 11; + int SWAP_BUFFERS = 12; + int FRAME_COMPLETED = 13; + + int FRAME_STATS_COUNT = 16; // must always be last + } + + /* + * Bucket endpoints for each Metric defined above. + * + * Each defined metric *must* have a corresponding entry + * in this list. + */ + private static final int[] DURATIONS = new int[] { + // UNKNOWN_DELAY + Index.INTENDED_VSYNC, Index.HANDLE_INPUT_START, + // INPUT_HANDLING + Index.HANDLE_INPUT_START, Index.ANIMATION_START, + // ANIMATION + Index.ANIMATION_START, Index.PERFORM_TRAVERSALS_START, + // LAYOUT_MEASURE + Index.PERFORM_TRAVERSALS_START, Index.DRAW_START, + // DRAW + Index.DRAW_START, Index.SYNC_QUEUED, + // SYNC + Index.SYNC_START, Index.ISSUE_DRAW_COMMANDS_START, + // COMMAND_ISSUE + Index.ISSUE_DRAW_COMMANDS_START, Index.SWAP_BUFFERS, + // SWAP_BUFFERS + Index.SWAP_BUFFERS, Index.FRAME_COMPLETED, + // TOTAL_DURATION + Index.INTENDED_VSYNC, Index.FRAME_COMPLETED, + }; + + /* package */ final long[] mTimingData; + + /** + * Constructs a FrameMetrics object as a copy. + * <p> + * Use this method to copy out metrics reported by + * {@link Window.OnFrameMetricsAvailableListener#onFrameMetricsAvailable( + * Window, FrameMetrics, int)} + * </p> + * @param other the FrameMetrics object to copy. + */ + public FrameMetrics(FrameMetrics other) { + mTimingData = new long[Index.FRAME_STATS_COUNT]; + System.arraycopy(other.mTimingData, 0, mTimingData, 0, mTimingData.length); + } + + /** + * @hide + */ + FrameMetrics() { + mTimingData = new long[Index.FRAME_STATS_COUNT]; + } + + /** + * Retrieves the value associated with Metric identifier {@code id} + * for this frame. + * <p> + * Boolean metrics are represented in [0,1], with 0 corresponding to + * false, and 1 corresponding to true. + * </p> + * @param id the metric to retrieve + * @return the value of the metric or -1 if it is not available. + */ + public long getMetric(@Metric int id) { + if (id < UNKNOWN_DELAY_DURATION || id > VSYNC_TIMESTAMP) { + return -1; + } + + if (mTimingData == null) { + return -1; + } + + if (id == FIRST_DRAW_FRAME) { + return (mTimingData[Index.FLAGS] & FRAME_INFO_FLAG_FIRST_DRAW) != 0 ? 1 : 0; + } else if (id == INTENDED_VSYNC_TIMESTAMP) { + return mTimingData[Index.INTENDED_VSYNC]; + } else if (id == VSYNC_TIMESTAMP) { + return mTimingData[Index.VSYNC]; + } + + int durationsIdx = 2 * id; + return mTimingData[DURATIONS[durationsIdx + 1]] + - mTimingData[DURATIONS[durationsIdx]]; + } +} + |