summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorAhan Wu <ahanwu@google.com>2021-01-27 17:29:54 +0000
committerAhan Wu <ahanwu@google.com>2021-02-22 19:24:56 +0000
commit320858c56f14e6b7585ea4e5ff93190d7b23fa3d (patch)
tree2244260634e0a10e7d477f9818a91c51256a52d1 /core/java
parent318641ee43b42226efd57e962c410c8d27c8fefb (diff)
Send broadcast to notify the events of a CUJ session
Send broadcast to notify the CUJ events to who is interested in. Bug: 171912046 Test: atest FrameworksCoreTests:InteractionJankMonitorTest Test: atest FrameworksCoreTests:FrameTrackerTest Change-Id: I91ab025385c635d15d7be6f7f12597e8900e2e5d
Diffstat (limited to 'core/java')
-rw-r--r--core/java/com/android/internal/jank/FrameTracker.java28
-rw-r--r--core/java/com/android/internal/jank/InteractionJankMonitor.java40
2 files changed, 65 insertions, 3 deletions
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index e82cc737a395..342456a58091 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -25,6 +25,9 @@ import static android.view.SurfaceControl.JankData.JANK_SURFACEFLINGER_GPU_DEADL
import static android.view.SurfaceControl.JankData.PREDICTION_ERROR;
import static android.view.SurfaceControl.JankData.SURFACE_FLINGER_SCHEDULING;
+import static com.android.internal.jank.InteractionJankMonitor.ACTION_METRICS_LOGGED;
+import static com.android.internal.jank.InteractionJankMonitor.ACTION_SESSION_BEGIN;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.HardwareRendererObserver;
@@ -72,6 +75,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
private long mEndVsyncId = INVALID_ID;
private boolean mMetricsFinalized;
private boolean mCancelled = false;
+ private FrameTrackerListener mListener;
private static class JankInfo {
long frameVsyncId;
@@ -109,7 +113,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
@NonNull SurfaceControlWrapper surfaceControlWrapper,
@NonNull ChoreographerWrapper choreographer,
@NonNull FrameMetricsWrapper metrics, int traceThresholdMissedFrames,
- int traceThresholdFrameTimeMillis) {
+ int traceThresholdFrameTimeMillis, @Nullable FrameTrackerListener listener) {
mSession = session;
mRendererWrapper = renderer;
mMetricsWrapper = metrics;
@@ -120,6 +124,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
mObserver = new HardwareRendererObserver(this, mMetricsWrapper.getTiming(), handler);
mTraceThresholdMissedFrames = traceThresholdMissedFrames;
mTraceThresholdFrameTimeMillis = traceThresholdFrameTimeMillis;
+ mListener = listener;
// If the surface isn't valid yet, wait until it's created.
if (viewRootWrapper.getSurfaceControl().isValid()) {
@@ -165,11 +170,15 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
*/
public synchronized void begin() {
mBeginVsyncId = mChoreographer.getVsyncId() + 1;
+ mSession.setTimeStamp(System.nanoTime());
Trace.beginAsyncSection(mSession.getName(), (int) mBeginVsyncId);
mRendererWrapper.addObserver(mObserver);
if (mSurfaceControl != null) {
mSurfaceControlWrapper.addJankStatsListener(this, mSurfaceControl);
}
+ if (mListener != null) {
+ mListener.onNotifyCujEvents(mSession, ACTION_SESSION_BEGIN);
+ }
}
/**
@@ -224,7 +233,6 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
}
private boolean isInRange(long vsyncId) {
-
// It's possible that we may miss a callback for the frame with vsyncId == mEndVsyncId.
// Because of that, we collect all frames even if they happen after the end so we eventually
// have a frame after the end with both callbacks present.
@@ -371,6 +379,9 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
missedAppFramesCount + missedSfFramesCounts,
maxFrameTimeNanos,
missedSfFramesCounts);
+ if (mListener != null) {
+ mListener.onNotifyCujEvents(mSession, ACTION_METRICS_LOGGED);
+ }
}
if (DEBUG) {
Log.i(TAG, "FrameTracker: CUJ=" + mSession.getName()
@@ -495,4 +506,17 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
return mChoreographer.getVsyncId();
}
}
+
+ /**
+ * A listener that notifies cuj events.
+ */
+ public interface FrameTrackerListener {
+ /**
+ * Notify that the CUJ session was created.
+ *
+ * @param session the CUJ session
+ * @param action the specific action
+ */
+ void onNotifyCujEvents(Session session, String action);
+ }
}
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index cba6af98a980..0294ec398484 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -16,6 +16,8 @@
package com.android.internal.jank;
+import static android.content.Intent.FLAG_RECEIVER_REGISTERED_ONLY;
+
import static com.android.internal.jank.FrameTracker.ChoreographerWrapper;
import static com.android.internal.jank.FrameTracker.SurfaceControlWrapper;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL;
@@ -48,9 +50,12 @@ import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_IN
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.content.Context;
+import android.content.Intent;
import android.os.Build;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
+import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.util.Log;
import android.util.SparseArray;
@@ -59,6 +64,7 @@ import android.view.View;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.FrameTracker.FrameMetricsWrapper;
+import com.android.internal.jank.FrameTracker.FrameTrackerListener;
import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper;
import com.android.internal.jank.FrameTracker.ViewRootWrapper;
import com.android.internal.util.PerfettoTrigger;
@@ -74,6 +80,8 @@ import java.util.concurrent.TimeUnit;
*/
public class InteractionJankMonitor {
private static final String TAG = InteractionJankMonitor.class.getSimpleName();
+ private static final String ACTION_PREFIX = InteractionJankMonitor.class.getCanonicalName();
+
private static final String DEFAULT_WORKER_NAME = TAG + "-Worker";
private static final long DEFAULT_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(5L);
private static final String SETTINGS_ENABLED_KEY = "enabled";
@@ -90,6 +98,14 @@ public class InteractionJankMonitor {
private static final int DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES = 3;
private static final int DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS = 64;
+ public static final String ACTION_SESSION_BEGIN = ACTION_PREFIX + ".ACTION_SESSION_BEGIN";
+ public static final String ACTION_SESSION_END = ACTION_PREFIX + ".ACTION_SESSION_END";
+ public static final String ACTION_METRICS_LOGGED = ACTION_PREFIX + ".ACTION_METRICS_LOGGED";
+ public static final String BUNDLE_KEY_CUJ_NAME = ACTION_PREFIX + ".CUJ_NAME";
+ public static final String BUNDLE_KEY_TIMESTAMP = ACTION_PREFIX + ".TIMESTAMP";
+ @VisibleForTesting
+ public static final String PROP_NOTIFY_CUJ_EVENT = "debug.notify_cuj_events";
+
// Every value must have a corresponding entry in CUJ_STATSD_INTERACTION_TYPE.
public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE = 0;
public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE_LOCK = 1;
@@ -256,15 +272,28 @@ public class InteractionJankMonitor {
*/
@VisibleForTesting
public FrameTracker createFrameTracker(View v, Session session) {
+ final Context c = v.getContext().getApplicationContext();
synchronized (this) {
+ boolean needListener = SystemProperties.getBoolean(PROP_NOTIFY_CUJ_EVENT, false);
+ FrameTrackerListener eventsListener =
+ !needListener ? null : (s, act) -> notifyEvents(c, act, s);
+
return new FrameTracker(session, mWorker.getThreadHandler(),
new ThreadedRendererWrapper(v.getThreadedRenderer()),
new ViewRootWrapper(v.getViewRootImpl()), new SurfaceControlWrapper(),
new ChoreographerWrapper(Choreographer.getInstance()), mMetrics,
- mTraceThresholdMissedFrames, mTraceThresholdFrameTimeMillis);
+ mTraceThresholdMissedFrames, mTraceThresholdFrameTimeMillis, eventsListener);
}
}
+ private void notifyEvents(Context context, String action, Session session) {
+ Intent intent = new Intent(action);
+ intent.putExtra(BUNDLE_KEY_CUJ_NAME, getNameOfCuj(session.getCuj()));
+ intent.putExtra(BUNDLE_KEY_TIMESTAMP, session.getTimeStamp());
+ intent.addFlags(FLAG_RECEIVER_REGISTERED_ONLY);
+ context.sendBroadcast(intent);
+ }
+
/**
* Begin a trace session.
*
@@ -479,6 +508,7 @@ public class InteractionJankMonitor {
public static class Session {
@CujType
private int mCujType;
+ private long mTimeStamp;
public Session(@CujType int cujType) {
mCujType = cujType;
@@ -505,5 +535,13 @@ public class InteractionJankMonitor {
public String getName() {
return "J<" + getNameOfCuj(mCujType) + ">";
}
+
+ public void setTimeStamp(long timeStamp) {
+ mTimeStamp = timeStamp;
+ }
+
+ public long getTimeStamp() {
+ return mTimeStamp;
+ }
}
}