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

Commit d5df08e3 authored by Nataniel Borges's avatar Nataniel Borges Committed by Android (Google) Code Review
Browse files

Merge "Log window trace data per frame in continuous mode"

parents da17a202 48d9aa96
Loading
Loading
Loading
Loading
+4 −13
Original line number Diff line number Diff line
@@ -188,6 +188,7 @@ import android.util.SparseBooleanArray;
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 @@ public class WindowManagerService extends IWindowManager.Stub
            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 @@ public class WindowManagerService extends IWindowManager.Stub
        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 @@ public class WindowManagerService extends IWindowManager.Stub
        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)");
+79 −29
Original line number Diff line number Diff line
@@ -24,12 +24,14 @@ import static com.android.server.wm.WindowManagerTraceProto.WHERE;
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 @@ class WindowTracing {
    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 @@ class WindowTracing {
    private boolean mContinuousMode;
    private boolean mEnabled;
    private volatile boolean mEnabledLockFree;
    private boolean mScheduled;
    private Choreographer.FrameCallback mFrameCallback = (frameTimeNanos) ->
            log("onFrame" /* where */);

    private WindowTracing(File file, WindowManagerService service, Choreographer choreographer) {
        this(file, service, choreographer, service.mGlobalLock);
    }

    WindowTracing(File file) {
    @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 @@ class WindowTracing {
        }
    }

    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 @@ class WindowTracing {
                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,13 +177,45 @@ class WindowTracing {
        }
    }

    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");
        if (mContinuousMode) {
            schedule();
        } else {
            log(where);
        }
    }

    /**
     * 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());
@@ -179,13 +224,18 @@ class WindowTracing {
                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeToProtoLocked");
                try {
                    long tokenInner = os.start(WINDOW_MANAGER_SERVICE);
                service.writeToProtoLocked(os, mWindowTraceLogLevel);
                    mService.writeToProtoLocked(os, mWindowTraceLogLevel);
                    os.end(tokenInner);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
                }
                os.end(tokenOuter);
            appendTraceEntry(os);
                mTraceBuffer.add(os);

                mScheduled = false;
            }
        } catch (Exception e) {
            Log.wtf(TAG, "Exception while tracing state", e);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
        }
+9 −6
Original line number Diff line number Diff line
@@ -34,8 +34,8 @@ import android.content.Context;
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 @@ public class WindowTracingTest {

    @Mock
    private WindowManagerService mWmMock;
    @Mock
    private Choreographer mChoreographer;
    private WindowTracing mWindowTracing;
    private File mFile;

@@ -85,7 +87,9 @@ public class WindowTracingTest {
        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 @@ public class WindowTracingTest {

    @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 @@ public class WindowTracingTest {
                    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));