Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d5a7e40 authored by Andres Morales's avatar Andres Morales Committed by android-build-merger
Browse files

Merge "updates to FrameStatsObserver API" into nyc-dev

am: 73649053

* commit '73649053':
  updates to FrameStatsObserver API
parents ce10f209 73649053
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -40661,6 +40661,21 @@ package android.view {
    method public static android.view.FocusFinder getInstance();
  }
  public final class FrameMetrics {
    ctor public FrameMetrics(android.view.FrameMetrics);
    method public long getMetric(int);
    field public static final int ANIMATION_DURATION = 2; // 0x2
    field public static final int COMMAND_ISSUE_DURATION = 6; // 0x6
    field public static final int DRAW_DURATION = 4; // 0x4
    field public static final int FIRST_DRAW_FRAME = 9; // 0x9
    field public static final int INPUT_HANDLING_DURATION = 1; // 0x1
    field public static final int LAYOUT_MEASURE_DURATION = 3; // 0x3
    field public static final int SWAP_BUFFERS_DURATION = 7; // 0x7
    field public static final int SYNC_DURATION = 5; // 0x5
    field public static final int TOTAL_DURATION = 8; // 0x8
    field public static final int UNKNOWN_DELAY_DURATION = 0; // 0x0
  }
  public abstract class FrameStats {
    ctor public FrameStats();
    method public final long getEndTimeNano();
@@ -43164,6 +43179,7 @@ package android.view {
    ctor public Window(android.content.Context);
    method public abstract void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
    method public void addFlags(int);
    method public final void addFrameMetricsListener(android.view.Window.FrameMetricsListener, android.os.Handler);
    method public void clearFlags(int);
    method public abstract void closeAllPanels();
    method public abstract void closePanel(int);
@@ -43215,6 +43231,7 @@ package android.view {
    method public abstract boolean performContextMenuIdentifierAction(int, int);
    method public abstract boolean performPanelIdentifierAction(int, int, int);
    method public abstract boolean performPanelShortcut(int, int, android.view.KeyEvent, int);
    method public final void removeFrameMetricsListener(android.view.Window.FrameMetricsListener);
    method public boolean requestFeature(int);
    method public abstract void restoreHierarchyState(android.os.Bundle);
    method public abstract android.os.Bundle saveHierarchyState();
@@ -43340,6 +43357,10 @@ package android.view {
    method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
  }
  public static abstract interface Window.FrameMetricsListener {
    method public abstract void onMetricsAvailable(android.view.Window, android.view.FrameMetrics, int);
  }
  public static abstract interface Window.OnRestrictedCaptionAreaChangedListener {
    method public abstract void onRestrictedCaptionAreaChanged(android.graphics.Rect);
  }
+21 −0
Original line number Diff line number Diff line
@@ -43413,6 +43413,21 @@ package android.view {
    method public static android.view.FocusFinder getInstance();
  }
  public final class FrameMetrics {
    ctor public FrameMetrics(android.view.FrameMetrics);
    method public long getMetric(int);
    field public static final int ANIMATION_DURATION = 2; // 0x2
    field public static final int COMMAND_ISSUE_DURATION = 6; // 0x6
    field public static final int DRAW_DURATION = 4; // 0x4
    field public static final int FIRST_DRAW_FRAME = 9; // 0x9
    field public static final int INPUT_HANDLING_DURATION = 1; // 0x1
    field public static final int LAYOUT_MEASURE_DURATION = 3; // 0x3
    field public static final int SWAP_BUFFERS_DURATION = 7; // 0x7
    field public static final int SYNC_DURATION = 5; // 0x5
    field public static final int TOTAL_DURATION = 8; // 0x8
    field public static final int UNKNOWN_DELAY_DURATION = 0; // 0x0
  }
  public abstract class FrameStats {
    ctor public FrameStats();
    method public final long getEndTimeNano();
@@ -45916,6 +45931,7 @@ package android.view {
    ctor public Window(android.content.Context);
    method public abstract void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
    method public void addFlags(int);
    method public final void addFrameMetricsListener(android.view.Window.FrameMetricsListener, android.os.Handler);
    method public void clearFlags(int);
    method public abstract void closeAllPanels();
    method public abstract void closePanel(int);
@@ -45967,6 +45983,7 @@ package android.view {
    method public abstract boolean performContextMenuIdentifierAction(int, int);
    method public abstract boolean performPanelIdentifierAction(int, int, int);
    method public abstract boolean performPanelShortcut(int, int, android.view.KeyEvent, int);
    method public final void removeFrameMetricsListener(android.view.Window.FrameMetricsListener);
    method public boolean requestFeature(int);
    method public abstract void restoreHierarchyState(android.os.Bundle);
    method public abstract android.os.Bundle saveHierarchyState();
@@ -46093,6 +46110,10 @@ package android.view {
    method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
  }
  public static abstract interface Window.FrameMetricsListener {
    method public abstract void onMetricsAvailable(android.view.Window, android.view.FrameMetrics, int);
  }
  public static abstract interface Window.OnRestrictedCaptionAreaChangedListener {
    method public abstract void onRestrictedCaptionAreaChanged(android.graphics.Rect);
  }
+21 −0
Original line number Diff line number Diff line
@@ -40678,6 +40678,21 @@ package android.view {
    method public static android.view.FocusFinder getInstance();
  }
  public final class FrameMetrics {
    ctor public FrameMetrics(android.view.FrameMetrics);
    method public long getMetric(int);
    field public static final int ANIMATION_DURATION = 2; // 0x2
    field public static final int COMMAND_ISSUE_DURATION = 6; // 0x6
    field public static final int DRAW_DURATION = 4; // 0x4
    field public static final int FIRST_DRAW_FRAME = 9; // 0x9
    field public static final int INPUT_HANDLING_DURATION = 1; // 0x1
    field public static final int LAYOUT_MEASURE_DURATION = 3; // 0x3
    field public static final int SWAP_BUFFERS_DURATION = 7; // 0x7
    field public static final int SYNC_DURATION = 5; // 0x5
    field public static final int TOTAL_DURATION = 8; // 0x8
    field public static final int UNKNOWN_DELAY_DURATION = 0; // 0x0
  }
  public abstract class FrameStats {
    ctor public FrameStats();
    method public final long getEndTimeNano();
@@ -43181,6 +43196,7 @@ package android.view {
    ctor public Window(android.content.Context);
    method public abstract void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
    method public void addFlags(int);
    method public final void addFrameMetricsListener(android.view.Window.FrameMetricsListener, android.os.Handler);
    method public void clearFlags(int);
    method public abstract void closeAllPanels();
    method public abstract void closePanel(int);
@@ -43232,6 +43248,7 @@ package android.view {
    method public abstract boolean performContextMenuIdentifierAction(int, int);
    method public abstract boolean performPanelIdentifierAction(int, int, int);
    method public abstract boolean performPanelShortcut(int, int, android.view.KeyEvent, int);
    method public final void removeFrameMetricsListener(android.view.Window.FrameMetricsListener);
    method public boolean requestFeature(int);
    method public abstract void restoreHierarchyState(android.os.Bundle);
    method public abstract android.os.Bundle saveHierarchyState();
@@ -43357,6 +43374,10 @@ package android.view {
    method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
  }
  public static abstract interface Window.FrameMetricsListener {
    method public abstract void onMetricsAvailable(android.view.Window, android.view.FrameMetrics, int);
  }
  public static abstract interface Window.OnRestrictedCaptionAreaChangedListener {
    method public abstract void onRestrictedCaptionAreaChanged(android.graphics.Rect);
  }
+281 −0
Original line number Diff line number Diff line
/*
 * 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 android.view.Window;

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;

    private static final int FRAME_INFO_FLAG_FIRST_DRAW = 1 << 0;

    /**
     * Identifiers for metrics available for each frame.
     *
     * {@see {@link #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,
    })
    @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 = 14; // 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.FrameMetricsListener#onMetricsAvailable(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 > FIRST_DRAW_FRAME) {
            return -1;
        }

        if (mTimingData == null) {
            return -1;
        }

        if (id == FIRST_DRAW_FRAME) {
            return (mTimingData[Index.FLAGS] & FRAME_INFO_FLAG_FIRST_DRAW) != 0 ? 1 : 0;
        }

        int durationsIdx = 2 * id;
        return mTimingData[DURATIONS[durationsIdx + 1]]
                - mTimingData[DURATIONS[durationsIdx]];
    }
}
+75 −0
Original line number Diff line number Diff line
@@ -33,43 +33,23 @@ import java.lang.SuppressWarnings;
 *
 * @hide
 */
public abstract class FrameStatsObserver {
    private static final String TAG = "FrameStatsObserver";

public class FrameMetricsObserver {
    private MessageQueue mMessageQueue;
    private long[] mBuffer;

    private FrameStats mFrameStats;
    private WeakReference<Window> mWindow;

    /* package */ ThreadedRenderer mRenderer;
    /* package */ VirtualRefBasePtr mNative;
    private FrameMetrics mFrameMetrics;

    /**
     * Containing class for frame statistics reported
     * by the rendering subsystem.
     */
    public static class FrameStats {
        /**
         * Precise timing data for various milestones in a frame
         * lifecycle.
         *
         * This data is exactly the same as what is returned by
         * `adb shell dumpsys gfxinfo <PACKAGE_NAME> framestats`
         *
         * The fields reported may change from release to release.
         *
         * @see {@link http://developer.android.com/training/testing/performance.html}
         * for a description of the fields present.
         */
        public long[] mTimingData;
    }
    /* package */ Window.FrameMetricsListener mListener;
    /* package */ VirtualRefBasePtr mNative;

    /**
     * Creates a FrameStatsObserver
     * Creates a FrameMetricsObserver
     *
     * @param looper the looper to use when invoking callbacks
     */
    public FrameStatsObserver(@NonNull Looper looper) {
    FrameMetricsObserver(@NonNull Window window, @NonNull Looper looper,
            @NonNull Window.FrameMetricsListener listener) {
        if (looper == null) {
            throw new NullPointerException("looper cannot be null");
        }
@@ -79,44 +59,17 @@ public abstract class FrameStatsObserver {
            throw new IllegalStateException("invalid looper, null message queue\n");
        }

        mFrameStats = new FrameStats();
    }

    /**
     * Called on provided looper when frame stats data is available
     * for the previous frame.
     *
     * Clients of this class must do as little work as possible within
     * this callback, as the buffer is shared between the producer and consumer.
     *
     * If the consumer is still executing within this method when there is new
     * data available that data will be dropped. The producer cannot
     * wait on the consumer.
     *
     * @param data the newly available data
     */
    public abstract void onDataAvailable(FrameStats data);

    /**
     * Returns the number of reports dropped as a result of a slow
     * consumer.
     */
    public long getDroppedReportCount() {
        if (mRenderer == null) {
            return 0;
        }

        return mRenderer.getDroppedFrameReportCount();
        mFrameMetrics = new FrameMetrics();
        mWindow = new WeakReference<>(window);
        mListener = listener;
    }

    public boolean isRegistered() {
        return mRenderer != null && mNative != null;
    }

    // === called by native === //
    // Called by native on the provided Handler
    @SuppressWarnings("unused")
    private void notifyDataAvailable() {
        mFrameStats.mTimingData = mBuffer;
        onDataAvailable(mFrameStats);
    private void notifyDataAvailable(int dropCount) {
        final Window window = mWindow.get();
        if (window != null) {
            mListener.onMetricsAvailable(window, mFrameMetrics, dropCount);
        }
    }
}
Loading