updates to FrameStatsObserver API
- Rename to FrameMetrics to avoid collision with existing
android.view.FrameStats class
- Make FrameMetricsObserver implementation detail,
exposing FrameMetricsListener interface as public API
and wrapping in FrameStatsObserver to maintain state
- Remove dropped frame count call, in favor of passing as
parameter to callback method.
- Move away from raw timestamp access in favor of Metric IDs
which represent higher-level, more stable stages in a frame
lifecycle and match the categories exposed in the onscreen
bars.
- Support many-to-many Window<->FrameMetricsListener relationship
Change-Id: I00e741d664d4c868b1b6d0131a23f8316bd8c5c2
diff --git a/api/current.txt b/api/current.txt
index ae343cd..c1e1d7d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -40660,6 +40660,21 @@
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();
@@ -43163,6 +43178,7 @@
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);
@@ -43214,6 +43230,7 @@
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();
@@ -43339,6 +43356,10 @@
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);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index bcd39fe..5112826 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -43339,6 +43339,21 @@
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();
@@ -45842,6 +45857,7 @@
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);
@@ -45893,6 +45909,7 @@
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();
@@ -46019,6 +46036,10 @@
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);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index c1cd275..c52c56f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -40677,6 +40677,21 @@
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();
@@ -43180,6 +43195,7 @@
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);
@@ -43231,6 +43247,7 @@
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();
@@ -43356,6 +43373,10 @@
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);
}
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
new file mode 100644
index 0000000..8e66f86
--- /dev/null
+++ b/core/java/android/view/FrameMetrics.java
@@ -0,0 +1,281 @@
+/*
+ * 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]];
+ }
+}
+
diff --git a/core/java/android/view/FrameMetricsObserver.java b/core/java/android/view/FrameMetricsObserver.java
new file mode 100644
index 0000000..f38f8b7
--- /dev/null
+++ b/core/java/android/view/FrameMetricsObserver.java
@@ -0,0 +1,75 @@
+/*
+ * 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.NonNull;
+import android.util.Log;
+import android.os.Looper;
+import android.os.MessageQueue;
+
+import com.android.internal.util.VirtualRefBasePtr;
+
+import java.lang.NullPointerException;
+import java.lang.ref.WeakReference;
+import java.lang.SuppressWarnings;
+
+/**
+ * Provides streaming access to frame stats information from the rendering
+ * subsystem to apps.
+ *
+ * @hide
+ */
+public class FrameMetricsObserver {
+ private MessageQueue mMessageQueue;
+
+ private WeakReference<Window> mWindow;
+
+ private FrameMetrics mFrameMetrics;
+
+ /* package */ Window.FrameMetricsListener mListener;
+ /* package */ VirtualRefBasePtr mNative;
+
+ /**
+ * Creates a FrameMetricsObserver
+ *
+ * @param looper the looper to use when invoking callbacks
+ */
+ FrameMetricsObserver(@NonNull Window window, @NonNull Looper looper,
+ @NonNull Window.FrameMetricsListener listener) {
+ if (looper == null) {
+ throw new NullPointerException("looper cannot be null");
+ }
+
+ mMessageQueue = looper.getQueue();
+ if (mMessageQueue == null) {
+ throw new IllegalStateException("invalid looper, null message queue\n");
+ }
+
+ mFrameMetrics = new FrameMetrics();
+ mWindow = new WeakReference<>(window);
+ mListener = listener;
+ }
+
+ // Called by native on the provided Handler
+ @SuppressWarnings("unused")
+ private void notifyDataAvailable(int dropCount) {
+ final Window window = mWindow.get();
+ if (window != null) {
+ mListener.onMetricsAvailable(window, mFrameMetrics, dropCount);
+ }
+ }
+}
diff --git a/core/java/android/view/FrameStatsObserver.java b/core/java/android/view/FrameStatsObserver.java
deleted file mode 100644
index 0add607..0000000
--- a/core/java/android/view/FrameStatsObserver.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.NonNull;
-import android.util.Log;
-import android.os.Looper;
-import android.os.MessageQueue;
-
-import com.android.internal.util.VirtualRefBasePtr;
-
-import java.lang.NullPointerException;
-import java.lang.ref.WeakReference;
-import java.lang.SuppressWarnings;
-
-/**
- * Provides streaming access to frame stats information from the rendering
- * subsystem to apps.
- *
- * @hide
- */
-public abstract class FrameStatsObserver {
- private static final String TAG = "FrameStatsObserver";
-
- private MessageQueue mMessageQueue;
- private long[] mBuffer;
-
- private FrameStats mFrameStats;
-
- /* package */ ThreadedRenderer mRenderer;
- /* package */ VirtualRefBasePtr mNative;
-
- /**
- * 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;
- }
-
- /**
- * Creates a FrameStatsObserver
- *
- * @param looper the looper to use when invoking callbacks
- */
- public FrameStatsObserver(@NonNull Looper looper) {
- if (looper == null) {
- throw new NullPointerException("looper cannot be null");
- }
-
- mMessageQueue = looper.getQueue();
- if (mMessageQueue == null) {
- 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();
- }
-
- public boolean isRegistered() {
- return mRenderer != null && mNative != null;
- }
-
- // === called by native === //
- @SuppressWarnings("unused")
- private void notifyDataAvailable() {
- mFrameStats.mTimingData = mBuffer;
- onDataAvailable(mFrameStats);
- }
-}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 8b06ecf..ca41d78 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -354,8 +354,6 @@
private boolean mEnabled;
private boolean mRequested = true;
- private HashSet<FrameStatsObserver> mFrameStatsObservers;
-
ThreadedRenderer(Context context, boolean translucent) {
final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
@@ -964,29 +962,14 @@
}
}
- void addFrameStatsObserver(FrameStatsObserver fso) {
- if (mFrameStatsObservers == null) {
- mFrameStatsObservers = new HashSet<>();
- }
-
- long nativeFso = nAddFrameStatsObserver(mNativeProxy, fso);
- fso.mRenderer = this;
- fso.mNative = new VirtualRefBasePtr(nativeFso);
- mFrameStatsObservers.add(fso);
+ void addFrameMetricsObserver(FrameMetricsObserver observer) {
+ long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
+ observer.mNative = new VirtualRefBasePtr(nativeObserver);
}
- void removeFrameStatsObserver(FrameStatsObserver fso) {
- if (!mFrameStatsObservers.remove(fso)) {
- throw new IllegalArgumentException("attempt to remove FrameStatsObserver that was never added");
- }
-
- nRemoveFrameStatsObserver(mNativeProxy, fso.mNative.get());
- fso.mRenderer = null;
- fso.mNative = null;
- }
-
- long getDroppedFrameReportCount() {
- return nGetDroppedFrameReportCount(mNativeProxy);
+ void removeFrameMetricsObserver(FrameMetricsObserver observer) {
+ nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
+ observer.mNative = null;
}
static native void setupShadersDiskCache(String cacheFile);
@@ -1044,7 +1027,6 @@
private static native void nSetContentDrawBounds(long nativeProxy, int left,
int top, int right, int bottom);
- private static native long nAddFrameStatsObserver(long nativeProxy, FrameStatsObserver fso);
- private static native void nRemoveFrameStatsObserver(long nativeProxy, long nativeFso);
- private static native long nGetDroppedFrameReportCount(long nativeProxy);
+ private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer);
+ private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 127157b..c41618c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3703,9 +3703,9 @@
private ViewPropertyAnimator mAnimator = null;
/**
- * List of FrameStatsObservers pending registration when mAttachInfo is null.
+ * List of registered FrameMetricsObservers.
*/
- private ArrayList<FrameStatsObserver> mPendingFrameStatsObservers;
+ private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
/**
* Flag indicating that a drag can cross window boundaries. When
@@ -5479,19 +5479,29 @@
*
* @hide
*/
- public void addFrameStatsObserver(FrameStatsObserver fso) {
+ public void addFrameMetricsListener(Window window, Window.FrameMetricsListener listener,
+ Handler handler) {
if (mAttachInfo != null) {
if (mAttachInfo.mHardwareRenderer != null) {
- mAttachInfo.mHardwareRenderer.addFrameStatsObserver(fso);
+ if (mFrameMetricsObservers == null) {
+ mFrameMetricsObservers = new ArrayList<>();
+ }
+
+ FrameMetricsObserver fmo = new FrameMetricsObserver(window,
+ handler.getLooper(), listener);
+ mFrameMetricsObservers.add(fmo);
+ mAttachInfo.mHardwareRenderer.addFrameMetricsObserver(fmo);
} else {
Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
}
} else {
- if (mPendingFrameStatsObservers == null) {
- mPendingFrameStatsObservers = new ArrayList<>();
+ if (mFrameMetricsObservers == null) {
+ mFrameMetricsObservers = new ArrayList<>();
}
- mPendingFrameStatsObservers.add(fso);
+ FrameMetricsObserver fmo = new FrameMetricsObserver(window,
+ handler.getLooper(), listener);
+ mFrameMetricsObservers.add(fmo);
}
}
@@ -5500,32 +5510,45 @@
*
* @hide
*/
- public void removeFrameStatsObserver(FrameStatsObserver fso) {
+ public void removeFrameMetricsListener(Window.FrameMetricsListener listener) {
ThreadedRenderer renderer = getHardwareRenderer();
-
- if (mPendingFrameStatsObservers != null) {
- mPendingFrameStatsObservers.remove(fso);
+ FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
+ if (fmo == null) {
+ throw new IllegalArgumentException("attempt to remove FrameMetricsListener that was never added");
}
- if (renderer != null) {
- renderer.removeFrameStatsObserver(fso);
+ if (mFrameMetricsObservers != null) {
+ mFrameMetricsObservers.remove(fmo);
+ if (renderer != null) {
+ renderer.removeFrameMetricsObserver(fmo);
+ }
}
}
- private void registerPendingFrameStatsObservers() {
- if (mPendingFrameStatsObservers != null) {
+ private void registerPendingFrameMetricsObservers() {
+ if (mFrameMetricsObservers != null) {
ThreadedRenderer renderer = getHardwareRenderer();
if (renderer != null) {
- for (FrameStatsObserver fso : mPendingFrameStatsObservers) {
- renderer.addFrameStatsObserver(fso);
+ for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
+ renderer.addFrameMetricsObserver(fmo);
}
} else {
Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
}
- mPendingFrameStatsObservers = null;
}
}
+ private FrameMetricsObserver findFrameMetricsObserver(Window.FrameMetricsListener listener) {
+ for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
+ FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
+ if (observer.mListener == listener) {
+ return observer;
+ }
+ }
+
+ return null;
+ }
+
/**
* Call this view's OnClickListener, if it is defined. Performs all normal
* actions associated with clicking: reporting accessibility event, playing
@@ -15160,7 +15183,7 @@
mFloatingTreeObserver = null;
}
- registerPendingFrameStatsObservers();
+ registerPendingFrameMetricsObservers();
if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
mAttachInfo.mScrollContainers.add(this);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index c68a740..9f05990 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -34,6 +34,7 @@
import android.media.session.MediaController;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -604,6 +605,34 @@
void onRestrictedCaptionAreaChanged(Rect rect);
}
+ /**
+ * Callback for clients that want frame timing information for each
+ * frame rendered by the Window.
+ */
+ public interface FrameMetricsListener {
+ /**
+ * Called when information is available for the previously rendered frame.
+ *
+ * Reports can be dropped if this callback takes too
+ * long to execute, as the report producer cannot wait for the consumer to
+ * complete.
+ *
+ * It is highly recommended that clients copy the passed in FrameMetrics
+ * via {@link FrameMetrics#FrameMetrics(FrameMetrics)} within this method and defer
+ * additional computation or storage to another thread to avoid unnecessarily
+ * dropping reports.
+ *
+ * @param window The {@link Window} on which the frame was displayed.
+ * @param frameMetrics the available metrics. This object is reused on every call
+ * and thus <strong>this reference is not valid outside the scope of this method</strong>.
+ * @param dropCountSinceLastInvocation the number of reports dropped since the last time
+ * this callback was invoked.
+ */
+ void onMetricsAvailable(Window window, FrameMetrics frameMetrics,
+ int dropCountSinceLastInvocation);
+ }
+
+
public Window(Context context) {
mContext = context;
mFeatures = mLocalFeatures = getDefaultFeatures(context);
@@ -798,33 +827,28 @@
* Set an observer to collect frame stats for each frame rendererd in this window.
*
* Must be in hardware rendering mode.
- * @hide
*/
- public final void addFrameStatsObserver(@NonNull FrameStatsObserver fso) {
+ public final void addFrameMetricsListener(@NonNull FrameMetricsListener listener,
+ Handler handler) {
final View decorView = getDecorView();
if (decorView == null) {
throw new IllegalStateException("can't observe a Window without an attached view");
}
- if (fso == null) {
- throw new NullPointerException("FrameStatsObserver cannot be null");
+ if (listener == null) {
+ throw new NullPointerException("listener cannot be null");
}
- if (fso.isRegistered()) {
- throw new IllegalStateException("FrameStatsObserver already registered on a Window.");
- }
-
- decorView.addFrameStatsObserver(fso);
+ decorView.addFrameMetricsListener(this, listener, handler);
}
/**
* Remove observer and stop listening to frame stats for this window.
- * @hide
*/
- public final void removeFrameStatsObserver(FrameStatsObserver fso) {
+ public final void removeFrameMetricsListener(FrameMetricsListener listener) {
final View decorView = getDecorView();
if (decorView != null) {
- getDecorView().removeFrameStatsObserver(fso);
+ getDecorView().removeFrameMetricsListener(listener);
}
}
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index acd0501..dd0e456 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -41,6 +41,7 @@
#include <Animator.h>
#include <AnimationContext.h>
#include <FrameInfo.h>
+#include <FrameMetricsObserver.h>
#include <IContextFactory.h>
#include <JankTracker.h>
#include <RenderNode.h>
@@ -56,10 +57,11 @@
using namespace android::uirenderer::renderthread;
struct {
- jfieldID buffer;
+ jfieldID frameMetrics;
+ jfieldID timingDataBuffer;
jfieldID messageQueue;
- jmethodID notifyData;
-} gFrameStatsObserverClassInfo;
+ jmethodID callback;
+} gFrameMetricsObserverClassInfo;
static JNIEnv* getenv(JavaVM* vm) {
JNIEnv* env;
@@ -239,31 +241,46 @@
mBuffer = buffer;
}
+ void setDropCount(int dropCount) {
+ mDropCount = dropCount;
+ }
+
virtual void handleMessage(const Message& message);
private:
JavaVM* mVm;
sp<ObserverProxy> mObserver;
- BufferPool::Buffer* mBuffer;
+ BufferPool::Buffer* mBuffer = nullptr;
+ int mDropCount = 0;
};
-class ObserverProxy : public FrameStatsObserver {
+static jlongArray get_metrics_buffer(JNIEnv* env, jobject observer) {
+ jobject frameMetrics = env->GetObjectField(
+ observer, gFrameMetricsObserverClassInfo.frameMetrics);
+ LOG_ALWAYS_FATAL_IF(frameMetrics == nullptr, "unable to retrieve data sink object");
+ jobject buffer = env->GetObjectField(
+ frameMetrics, gFrameMetricsObserverClassInfo.timingDataBuffer);
+ LOG_ALWAYS_FATAL_IF(buffer == nullptr, "unable to retrieve data sink buffer");
+ return reinterpret_cast<jlongArray>(buffer);
+}
+
+class ObserverProxy : public FrameMetricsObserver {
public:
- ObserverProxy(JavaVM *vm, jobject fso) : mVm(vm) {
+ ObserverProxy(JavaVM *vm, jobject observer) : mVm(vm) {
JNIEnv* env = getenv(mVm);
- jlongArray longArrayLocal = env->NewLongArray(kBufferSize);
- LOG_ALWAYS_FATAL_IF(longArrayLocal == nullptr,
- "OOM: can't allocate frame stats buffer");
- env->SetObjectField(fso, gFrameStatsObserverClassInfo.buffer, longArrayLocal);
-
- mFsoWeak = env->NewWeakGlobalRef(fso);
- LOG_ALWAYS_FATAL_IF(mFsoWeak == nullptr,
+ mObserverWeak = env->NewWeakGlobalRef(observer);
+ LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr,
"unable to create frame stats observer reference");
- jobject messageQueueLocal =
- env->GetObjectField(fso, gFrameStatsObserverClassInfo.messageQueue);
+ jlongArray buffer = get_metrics_buffer(env, observer);
+ jsize bufferSize = env->GetArrayLength(reinterpret_cast<jarray>(buffer));
+ LOG_ALWAYS_FATAL_IF(bufferSize != kBufferSize,
+ "Mismatched Java/Native FrameMetrics data format.");
+
+ jobject messageQueueLocal = env->GetObjectField(
+ observer, gFrameMetricsObserverClassInfo.messageQueue);
mMessageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueLocal);
LOG_ALWAYS_FATAL_IF(mMessageQueue == nullptr, "message queue not available");
@@ -274,17 +291,18 @@
~ObserverProxy() {
JNIEnv* env = getenv(mVm);
- env->DeleteWeakGlobalRef(mFsoWeak);
+ env->DeleteWeakGlobalRef(mObserverWeak);
}
- jweak getJavaObjectRef() {
- return mFsoWeak;
+ jweak getObserverReference() {
+ return mObserverWeak;
}
- virtual void notify(BufferPool::Buffer* buffer) {
+ virtual void notify(BufferPool::Buffer* buffer, int dropCount) {
buffer->incRef();
mMessageHandler->setBuffer(buffer);
mMessageHandler->setObserver(this);
+ mMessageHandler->setDropCount(dropCount);
mMessageQueue->getLooper()->sendMessage(mMessageHandler, mMessage);
}
@@ -292,26 +310,27 @@
static const int kBufferSize = static_cast<int>(FrameInfoIndex::NumIndexes);
JavaVM* mVm;
- jweak mFsoWeak;
+ jweak mObserverWeak;
+ jobject mJavaBufferGlobal;
sp<MessageQueue> mMessageQueue;
sp<NotifyHandler> mMessageHandler;
Message mMessage;
+
};
void NotifyHandler::handleMessage(const Message& message) {
JNIEnv* env = getenv(mVm);
- jobject target = env->NewLocalRef(mObserver->getJavaObjectRef());
+ jobject target = env->NewLocalRef(mObserver->getObserverReference());
if (target != nullptr) {
- jobject javaBuffer = env->GetObjectField(target, gFrameStatsObserverClassInfo.buffer);
- if (javaBuffer != nullptr) {
- env->SetLongArrayRegion(reinterpret_cast<jlongArray>(javaBuffer),
- 0, mBuffer->getSize(), mBuffer->getBuffer());
- env->CallVoidMethod(target, gFrameStatsObserverClassInfo.notifyData);
- env->DeleteLocalRef(target);
- }
+ jlongArray javaBuffer = get_metrics_buffer(env, target);
+ env->SetLongArrayRegion(javaBuffer,
+ 0, mBuffer->getSize(), mBuffer->getBuffer());
+ env->CallVoidMethod(target, gFrameMetricsObserverClassInfo.callback,
+ mDropCount);
+ env->DeleteLocalRef(target);
}
mBuffer->release();
@@ -579,10 +598,10 @@
}
// ----------------------------------------------------------------------------
-// FrameStatsObserver
+// FrameMetricsObserver
// ----------------------------------------------------------------------------
-static jlong android_view_ThreadedRenderer_addFrameStatsObserver(JNIEnv* env,
+static jlong android_view_ThreadedRenderer_addFrameMetricsObserver(JNIEnv* env,
jclass clazz, jlong proxyPtr, jobject fso) {
JavaVM* vm = nullptr;
if (env->GetJavaVM(&vm) != JNI_OK) {
@@ -593,25 +612,18 @@
renderthread::RenderProxy* renderProxy =
reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
- FrameStatsObserver* observer = new ObserverProxy(vm, fso);
- renderProxy->addFrameStatsObserver(observer);
+ FrameMetricsObserver* observer = new ObserverProxy(vm, fso);
+ renderProxy->addFrameMetricsObserver(observer);
return reinterpret_cast<jlong>(observer);
}
-static void android_view_ThreadedRenderer_removeFrameStatsObserver(JNIEnv* env, jclass clazz,
+static void android_view_ThreadedRenderer_removeFrameMetricsObserver(JNIEnv* env, jclass clazz,
jlong proxyPtr, jlong observerPtr) {
- FrameStatsObserver* observer = reinterpret_cast<FrameStatsObserver*>(observerPtr);
+ FrameMetricsObserver* observer = reinterpret_cast<FrameMetricsObserver*>(observerPtr);
renderthread::RenderProxy* renderProxy =
reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
- renderProxy->removeFrameStatsObserver(observer);
-}
-
-static jint android_view_ThreadedRenderer_getDroppedFrameReportCount(JNIEnv* env, jclass clazz,
- jlong proxyPtr) {
- renderthread::RenderProxy* renderProxy =
- reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
- return renderProxy->getDroppedFrameReportCount();
+ renderProxy->removeFrameMetricsObserver(observer);
}
// ----------------------------------------------------------------------------
@@ -684,25 +696,26 @@
{ "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
{ "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
{ "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
- { "nAddFrameStatsObserver",
- "(JLandroid/view/FrameStatsObserver;)J",
- (void*)android_view_ThreadedRenderer_addFrameStatsObserver },
- { "nRemoveFrameStatsObserver",
+ { "nAddFrameMetricsObserver",
+ "(JLandroid/view/FrameMetricsObserver;)J",
+ (void*)android_view_ThreadedRenderer_addFrameMetricsObserver },
+ { "nRemoveFrameMetricsObserver",
"(JJ)V",
- (void*)android_view_ThreadedRenderer_removeFrameStatsObserver },
- { "nGetDroppedFrameReportCount",
- "(J)J",
- (void*)android_view_ThreadedRenderer_getDroppedFrameReportCount },
+ (void*)android_view_ThreadedRenderer_removeFrameMetricsObserver },
};
int register_android_view_ThreadedRenderer(JNIEnv* env) {
- jclass clazz = FindClassOrDie(env, "android/view/FrameStatsObserver");
- gFrameStatsObserverClassInfo.messageQueue =
- GetFieldIDOrDie(env, clazz, "mMessageQueue", "Landroid/os/MessageQueue;");
- gFrameStatsObserverClassInfo.buffer =
- GetFieldIDOrDie(env, clazz, "mBuffer", "[J");
- gFrameStatsObserverClassInfo.notifyData =
- GetMethodIDOrDie(env, clazz, "notifyDataAvailable", "()V");
+ jclass observerClass = FindClassOrDie(env, "android/view/FrameMetricsObserver");
+ gFrameMetricsObserverClassInfo.frameMetrics = GetFieldIDOrDie(
+ env, observerClass, "mFrameMetrics", "Landroid/view/FrameMetrics;");
+ gFrameMetricsObserverClassInfo.messageQueue = GetFieldIDOrDie(
+ env, observerClass, "mMessageQueue", "Landroid/os/MessageQueue;");
+ gFrameMetricsObserverClassInfo.callback = GetMethodIDOrDie(
+ env, observerClass, "notifyDataAvailable", "(I)V");
+
+ jclass metricsClass = FindClassOrDie(env, "android/view/FrameMetrics");
+ gFrameMetricsObserverClassInfo.timingDataBuffer = GetFieldIDOrDie(
+ env, metricsClass, "mTimingData", "[J");
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/libs/hwui/FrameStatsObserver.h b/libs/hwui/FrameMetricsObserver.h
similarity index 86%
rename from libs/hwui/FrameStatsObserver.h
rename to libs/hwui/FrameMetricsObserver.h
index 7abc9f1..2b42a80 100644
--- a/libs/hwui/FrameStatsObserver.h
+++ b/libs/hwui/FrameMetricsObserver.h
@@ -23,9 +23,9 @@
namespace android {
namespace uirenderer {
-class FrameStatsObserver : public VirtualLightRefBase {
+class FrameMetricsObserver : public VirtualLightRefBase {
public:
- virtual void notify(BufferPool::Buffer* buffer);
+ virtual void notify(BufferPool::Buffer* buffer, int dropCount);
};
}; // namespace uirenderer
diff --git a/libs/hwui/FrameStatsReporter.h b/libs/hwui/FrameMetricsReporter.h
similarity index 83%
rename from libs/hwui/FrameStatsReporter.h
rename to libs/hwui/FrameMetricsReporter.h
index b8a9432..0831d24 100644
--- a/libs/hwui/FrameStatsReporter.h
+++ b/libs/hwui/FrameMetricsReporter.h
@@ -21,7 +21,7 @@
#include "BufferPool.h"
#include "FrameInfo.h"
-#include "FrameStatsObserver.h"
+#include "FrameMetricsObserver.h"
#include <string.h>
#include <vector>
@@ -29,18 +29,18 @@
namespace android {
namespace uirenderer {
-class FrameStatsReporter {
+class FrameMetricsReporter {
public:
- FrameStatsReporter() {
+ FrameMetricsReporter() {
mBufferPool = new BufferPool(kBufferSize, kBufferCount);
LOG_ALWAYS_FATAL_IF(mBufferPool.get() == nullptr, "OOM: unable to allocate buffer pool");
}
- void addObserver(FrameStatsObserver* observer) {
+ void addObserver(FrameMetricsObserver* observer) {
mObservers.push_back(observer);
}
- bool removeObserver(FrameStatsObserver* observer) {
+ bool removeObserver(FrameMetricsObserver* observer) {
for (size_t i = 0; i < mObservers.size(); i++) {
if (mObservers[i].get() == observer) {
mObservers.erase(mObservers.begin() + i);
@@ -54,7 +54,7 @@
return mObservers.size() > 0;
}
- void reportFrameStats(const int64_t* stats) {
+ void reportFrameMetrics(const int64_t* stats) {
BufferPool::Buffer* statsBuffer = mBufferPool->acquire();
if (statsBuffer != nullptr) {
@@ -63,11 +63,12 @@
// notify on requested threads
for (size_t i = 0; i < mObservers.size(); i++) {
- mObservers[i]->notify(statsBuffer);
+ mObservers[i]->notify(statsBuffer, mDroppedReports);
}
// drop our reference
statsBuffer->release();
+ mDroppedReports = 0;
} else {
mDroppedReports++;
}
@@ -79,7 +80,7 @@
static const size_t kBufferCount = 3;
static const size_t kBufferSize = static_cast<size_t>(FrameInfoIndex::NumIndexes);
- std::vector< sp<FrameStatsObserver> > mObservers;
+ std::vector< sp<FrameMetricsObserver> > mObservers;
sp<BufferPool> mBufferPool;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index ea702c0..4f528b1 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -507,8 +507,8 @@
mJankTracker.addFrame(*mCurrentFrameInfo);
mRenderThread.jankTracker().addFrame(*mCurrentFrameInfo);
- if (CC_UNLIKELY(mFrameStatsReporter.get() != nullptr)) {
- mFrameStatsReporter->reportFrameStats(mCurrentFrameInfo->data());
+ if (CC_UNLIKELY(mFrameMetricsReporter.get() != nullptr)) {
+ mFrameMetricsReporter->reportFrameMetrics(mCurrentFrameInfo->data());
}
GpuMemoryTracker::onFrameCompleted();
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 168166e..1f81970 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -20,7 +20,7 @@
#include "DamageAccumulator.h"
#include "FrameInfo.h"
#include "FrameInfoVisualizer.h"
-#include "FrameStatsReporter.h"
+#include "FrameMetricsReporter.h"
#include "IContextFactory.h"
#include "LayerUpdateQueue.h"
#include "RenderNode.h"
@@ -142,26 +142,26 @@
return mRenderThread.renderState();
}
- void addFrameStatsObserver(FrameStatsObserver* observer) {
- if (mFrameStatsReporter.get() == nullptr) {
- mFrameStatsReporter.reset(new FrameStatsReporter());
+ void addFrameMetricsObserver(FrameMetricsObserver* observer) {
+ if (mFrameMetricsReporter.get() == nullptr) {
+ mFrameMetricsReporter.reset(new FrameMetricsReporter());
}
- mFrameStatsReporter->addObserver(observer);
+ mFrameMetricsReporter->addObserver(observer);
}
- void removeFrameStatsObserver(FrameStatsObserver* observer) {
- if (mFrameStatsReporter.get() != nullptr) {
- mFrameStatsReporter->removeObserver(observer);
- if (!mFrameStatsReporter->hasObservers()) {
- mFrameStatsReporter.reset(nullptr);
+ void removeFrameMetricsObserver(FrameMetricsObserver* observer) {
+ if (mFrameMetricsReporter.get() != nullptr) {
+ mFrameMetricsReporter->removeObserver(observer);
+ if (!mFrameMetricsReporter->hasObservers()) {
+ mFrameMetricsReporter.reset(nullptr);
}
}
}
long getDroppedFrameReportCount() {
- if (mFrameStatsReporter.get() != nullptr) {
- return mFrameStatsReporter->getDroppedReports();
+ if (mFrameMetricsReporter.get() != nullptr) {
+ return mFrameMetricsReporter->getDroppedReports();
}
return 0;
@@ -215,7 +215,7 @@
std::string mName;
JankTracker mJankTracker;
FrameInfoVisualizer mProfiler;
- std::unique_ptr<FrameStatsReporter> mFrameStatsReporter;
+ std::unique_ptr<FrameMetricsReporter> mFrameMetricsReporter;
std::set<RenderNode*> mPrefetechedLayers;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 7c6cd7e..04223a7 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -568,17 +568,17 @@
post(task);
}
-CREATE_BRIDGE2(addFrameStatsObserver, CanvasContext* context,
- FrameStatsObserver* frameStatsObserver) {
- args->context->addFrameStatsObserver(args->frameStatsObserver);
+CREATE_BRIDGE2(addFrameMetricsObserver, CanvasContext* context,
+ FrameMetricsObserver* frameStatsObserver) {
+ args->context->addFrameMetricsObserver(args->frameStatsObserver);
if (args->frameStatsObserver != nullptr) {
args->frameStatsObserver->decStrong(args->context);
}
return nullptr;
}
-void RenderProxy::addFrameStatsObserver(FrameStatsObserver* observer) {
- SETUP_TASK(addFrameStatsObserver);
+void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observer) {
+ SETUP_TASK(addFrameMetricsObserver);
args->context = mContext;
args->frameStatsObserver = observer;
if (observer != nullptr) {
@@ -587,17 +587,17 @@
post(task);
}
-CREATE_BRIDGE2(removeFrameStatsObserver, CanvasContext* context,
- FrameStatsObserver* frameStatsObserver) {
- args->context->removeFrameStatsObserver(args->frameStatsObserver);
+CREATE_BRIDGE2(removeFrameMetricsObserver, CanvasContext* context,
+ FrameMetricsObserver* frameStatsObserver) {
+ args->context->removeFrameMetricsObserver(args->frameStatsObserver);
if (args->frameStatsObserver != nullptr) {
args->frameStatsObserver->decStrong(args->context);
}
return nullptr;
}
-void RenderProxy::removeFrameStatsObserver(FrameStatsObserver* observer) {
- SETUP_TASK(removeFrameStatsObserver);
+void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observer) {
+ SETUP_TASK(removeFrameMetricsObserver);
args->context = mContext;
args->frameStatsObserver = observer;
if (observer != nullptr) {
@@ -606,16 +606,6 @@
post(task);
}
-CREATE_BRIDGE1(getDroppedFrameReportCount, CanvasContext* context) {
- return (void*) args->context->getDroppedFrameReportCount();
-}
-
-long RenderProxy::getDroppedFrameReportCount() {
- SETUP_TASK(getDroppedFrameReportCount);
- args->context = mContext;
- return (long) postAndWait(task);
-}
-
void RenderProxy::post(RenderTask* task) {
mRenderThread.queue(task);
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 178724a..8d65a82 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -29,7 +29,7 @@
#include <utils/StrongPointer.h>
#include "../Caches.h"
-#include "../FrameStatsObserver.h"
+#include "../FrameMetricsObserver.h"
#include "../IContextFactory.h"
#include "CanvasContext.h"
#include "DrawFrameTask.h"
@@ -113,8 +113,8 @@
ANDROID_API void drawRenderNode(RenderNode* node);
ANDROID_API void setContentDrawBounds(int left, int top, int right, int bottom);
- ANDROID_API void addFrameStatsObserver(FrameStatsObserver* observer);
- ANDROID_API void removeFrameStatsObserver(FrameStatsObserver* observer);
+ ANDROID_API void addFrameMetricsObserver(FrameMetricsObserver* observer);
+ ANDROID_API void removeFrameMetricsObserver(FrameMetricsObserver* observer);
ANDROID_API long getDroppedFrameReportCount();
private: