Merge "Log window trace data per frame in continuous mode"
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6c3e1f4..00105be 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -188,6 +188,7 @@
import android.util.TimeUtils;
import android.util.TypedValue;
import android.util.proto.ProtoOutputStream;
+import android.view.Choreographer;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
@@ -843,7 +844,7 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
synchronized (mGlobalLock) {
SurfaceControl.closeTransaction();
- traceStateLocked(where);
+ mWindowTracing.logState(where);
}
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
@@ -967,7 +968,8 @@
mWindowPlacerLocked = new WindowSurfacePlacer(this);
mTaskSnapshotController = new TaskSnapshotController(this);
- mWindowTracing = WindowTracing.createDefaultAndStartLooper(context);
+ mWindowTracing = WindowTracing.createDefaultAndStartLooper(this,
+ Choreographer.getInstance());
LocalServices.addService(WindowManagerPolicy.class, mPolicy);
@@ -5765,17 +5767,6 @@
proto.write(LAST_ORIENTATION, defaultDisplayContent.getLastOrientation());
}
- void traceStateLocked(String where) {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "traceStateLocked");
- try {
- mWindowTracing.traceStateLocked(where, this);
- } catch (Exception e) {
- Log.wtf(TAG, "Exception while tracing state", e);
- } finally {
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- }
- }
-
private void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
ArrayList<WindowState> windows) {
pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java
index 8b1ffa8..abc474d 100644
--- a/services/core/java/com/android/server/wm/WindowTracing.java
+++ b/services/core/java/com/android/server/wm/WindowTracing.java
@@ -24,12 +24,14 @@
import static com.android.server.wm.WindowManagerTraceProto.WINDOW_MANAGER_SERVICE;
import android.annotation.Nullable;
-import android.content.Context;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.Trace;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
+import android.view.Choreographer;
+
+import com.android.internal.annotations.VisibleForTesting;
import java.io.File;
import java.io.IOException;
@@ -48,6 +50,10 @@
private static final int WINDOW_TRACE_BUFFER_SIZE = 512 * 1024;
private static final String TAG = "WindowTracing";
+ private final WindowManagerService mService;
+ private final Choreographer mChoreographer;
+ private final WindowManagerGlobalLock mGlobalLock;
+
private final Object mLock = new Object();
private final WindowTraceBuffer.Builder mBufferBuilder;
@@ -57,11 +63,24 @@
private boolean mContinuousMode;
private boolean mEnabled;
private volatile boolean mEnabledLockFree;
+ private boolean mScheduled;
+ private Choreographer.FrameCallback mFrameCallback = (frameTimeNanos) ->
+ log("onFrame" /* where */);
- WindowTracing(File file) {
+ private WindowTracing(File file, WindowManagerService service, Choreographer choreographer) {
+ this(file, service, choreographer, service.mGlobalLock);
+ }
+
+ @VisibleForTesting
+ WindowTracing(File file, WindowManagerService service, Choreographer choreographer,
+ WindowManagerGlobalLock globalLock) {
mBufferBuilder = new WindowTraceBuffer.Builder()
.setTraceFile(file)
.setBufferCapacity(WINDOW_TRACE_BUFFER_SIZE);
+
+ mChoreographer = choreographer;
+ mService = service;
+ mGlobalLock = globalLock;
}
void startTrace(@Nullable PrintWriter pw) throws IOException {
@@ -111,7 +130,8 @@
}
}
- private void setContinuousMode(boolean continuous, PrintWriter pw) {
+ @VisibleForTesting
+ void setContinuousMode(boolean continuous, PrintWriter pw) {
logAndPrintln(pw, "Setting window tracing continuous mode to " + continuous);
if (mEnabled) {
@@ -123,21 +143,14 @@
WindowTraceLogLevel.TRIM;
}
- private void appendTraceEntry(ProtoOutputStream proto) {
- if (!mEnabledLockFree) {
- return;
- }
-
- mTraceBuffer.add(proto);
- }
-
boolean isEnabled() {
return mEnabledLockFree;
}
- static WindowTracing createDefaultAndStartLooper(Context context) {
+ static WindowTracing createDefaultAndStartLooper(WindowManagerService service,
+ Choreographer choreographer) {
File file = new File("/data/misc/wmtrace/wm_trace.pb");
- return new WindowTracing(file);
+ return new WindowTracing(file, service, choreographer);
}
int onShellCommand(ShellCommand shell) {
@@ -164,28 +177,65 @@
}
}
- void traceStateLocked(String where, WindowManagerService service) {
+ /**
+ * If tracing is enabled, log the current state or schedule the next frame to be logged,
+ * according to {@link #mContinuousMode}.
+ *
+ * @param where Logging point descriptor
+ */
+ void logState(String where) {
if (!isEnabled()) {
return;
}
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeToBufferLocked");
- try {
- ProtoOutputStream os = new ProtoOutputStream();
- long tokenOuter = os.start(ENTRY);
- os.write(ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos());
- os.write(WHERE, where);
+ if (mContinuousMode) {
+ schedule();
+ } else {
+ log(where);
+ }
+ }
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeToProtoLocked");
- try {
- long tokenInner = os.start(WINDOW_MANAGER_SERVICE);
- service.writeToProtoLocked(os, mWindowTraceLogLevel);
- os.end(tokenInner);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ /**
+ * Schedule the log to trace the next frame
+ */
+ private void schedule() {
+ if (mScheduled) {
+ return;
+ }
+
+ mScheduled = true;
+ mChoreographer.postFrameCallback(mFrameCallback);
+ }
+
+ /**
+ * Write the current frame to the buffer
+ *
+ * @param where Logging point descriptor
+ */
+ private void log(String where) {
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "traceStateLocked");
+ try {
+ synchronized (mGlobalLock) {
+ ProtoOutputStream os = new ProtoOutputStream();
+ long tokenOuter = os.start(ENTRY);
+ os.write(ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos());
+ os.write(WHERE, where);
+
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeToProtoLocked");
+ try {
+ long tokenInner = os.start(WINDOW_MANAGER_SERVICE);
+ mService.writeToProtoLocked(os, mWindowTraceLogLevel);
+ os.end(tokenInner);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ }
+ os.end(tokenOuter);
+ mTraceBuffer.add(os);
+
+ mScheduled = false;
}
- os.end(tokenOuter);
- appendTraceEntry(os);
+ } catch (Exception e) {
+ Log.wtf(TAG, "Exception while tracing state", e);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
index b6b9a86..2970c21 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
@@ -34,8 +34,8 @@
import android.platform.test.annotations.Presubmit;
import android.testing.DexmakerShareClassLoaderRule;
import android.util.proto.ProtoOutputStream;
+import android.view.Choreographer;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.internal.util.Preconditions;
@@ -74,6 +74,8 @@
@Mock
private WindowManagerService mWmMock;
+ @Mock
+ private Choreographer mChoreographer;
private WindowTracing mWindowTracing;
private File mFile;
@@ -85,7 +87,9 @@
mFile = testContext.getFileStreamPath("tracing_test.dat");
mFile.delete();
- mWindowTracing = new WindowTracing(mFile);
+ mWindowTracing = new WindowTracing(mFile, mWmMock, mChoreographer,
+ new WindowManagerGlobalLock());
+ mWindowTracing.setContinuousMode(false /* continuous */, null /* pw */);
}
@After
@@ -113,15 +117,14 @@
@Test
public void trace_discared_whenNotTracing() {
- mWindowTracing.traceStateLocked("where", mWmMock);
+ mWindowTracing.logState("where");
verifyZeroInteractions(mWmMock);
}
@Test
public void trace_dumpsWindowManagerState_whenTracing() throws Exception {
mWindowTracing.startTrace(mock(PrintWriter.class));
- mWindowTracing.traceStateLocked("where", mWmMock);
-
+ mWindowTracing.logState("where");
verify(mWmMock).writeToProtoLocked(any(), eq(WindowTraceLogLevel.TRIM));
}
@@ -147,7 +150,7 @@
WindowManagerTraceProto.WHERE, "TEST_WM_PROTO");
return null;
}).when(mWmMock).writeToProtoLocked(any(), any());
- mWindowTracing.traceStateLocked("TEST_WHERE", mWmMock);
+ mWindowTracing.logState("TEST_WHERE");
mWindowTracing.stopTrace(mock(PrintWriter.class));