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

Commit eaf61d88 authored by Pablo Gamito's avatar Pablo Gamito
Browse files

Add shell side transition trace to bug reports

Test: atest BugreportManagerTestCases
Bug: 276701336
Bug: 277181336
Bug: 278691227
Change-Id: If53cce37f4787d4e03fbee4cbe5b2808719e011f
parent 909c8edd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -112,6 +112,7 @@ public class BugreportManagerTest {
            Paths.get("/data/misc/wmtrace/layers_trace.winscope"),
            Paths.get("/data/misc/wmtrace/transactions_trace.winscope"),
            Paths.get("/data/misc/wmtrace/transition_trace.winscope"),
            Paths.get("/data/misc/wmtrace/shell_transition_trace.winscope"),
    };
    private static final Path[] UI_TRACES_GENERATED_DURING_BUGREPORT = {
            Paths.get("/data/misc/wmtrace/layers_trace_from_transactions.winscope"),
+3 −2
Original line number Diff line number Diff line
@@ -544,13 +544,14 @@ public abstract class WMShellBaseModule {
            DisplayController displayController,
            @ShellMainThread ShellExecutor mainExecutor,
            @ShellMainThread Handler mainHandler,
            @ShellAnimationThread ShellExecutor animExecutor) {
            @ShellAnimationThread ShellExecutor animExecutor,
            ShellCommandHandler shellCommandHandler) {
        if (!context.getResources().getBoolean(R.bool.config_registerShellTransitionsOnInit)) {
            // TODO(b/238217847): Force override shell init if registration is disabled
            shellInit = new ShellInit(mainExecutor);
        }
        return new Transitions(context, shellInit, shellController, organizer, pool,
                displayController, mainExecutor, mainHandler, animExecutor);
                displayController, mainExecutor, mainHandler, animExecutor, shellCommandHandler);
    }

    @WMSingleton
+85 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.util.Log;
import android.util.proto.ProtoOutputStream;

import com.android.internal.util.TraceBuffer;
import com.android.wm.shell.sysui.ShellCommandHandler;

import java.io.File;
import java.io.IOException;
@@ -40,8 +41,9 @@ import java.util.Map;
/**
 * Helper class to collect and dump transition traces.
 */
public class Tracer {
public class Tracer implements ShellCommandHandler.ShellCommandActionHandler {
    private static final int ALWAYS_ON_TRACING_CAPACITY = 15 * 1024; // 15 KB
    private static final int ACTIVE_TRACING_BUFFER_CAPACITY = 5000 * 1024; // 5 MB

    private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;

@@ -50,6 +52,7 @@ public class Tracer {
            "/data/misc/wmtrace/shell_transition_trace" + WINSCOPE_EXT;

    private final Object mEnabledLock = new Object();
    private boolean mActiveTracingEnabled = false;

    private final TraceBuffer mTraceBuffer = new TraceBuffer(ALWAYS_ON_TRACING_CAPACITY,
            (proto) -> handleOnEntryRemovedFromTrace(proto));
@@ -157,6 +160,54 @@ public class Tracer {
        mTraceBuffer.add(outputStream);
    }

    /**
     * Starts collecting transitions for the trace.
     * If called while a trace is already running, this will reset the trace.
     */
    public void startTrace(@Nullable PrintWriter pw) {
        if (IS_USER) {
            LogAndPrintln.e(pw, "Tracing is not supported on user builds.");
            return;
        }
        Trace.beginSection("Tracer#startTrace");
        LogAndPrintln.i(pw, "Starting shell transition trace.");
        synchronized (mEnabledLock) {
            mActiveTracingEnabled = true;
            mTraceBuffer.resetBuffer();
            mTraceBuffer.setCapacity(ACTIVE_TRACING_BUFFER_CAPACITY);
        }
        Trace.endSection();
    }

    /**
     * Stops collecting the transition trace and dump to trace to file.
     *
     * Dumps the trace to @link{TRACE_FILE}.
     */
    public void stopTrace(@Nullable PrintWriter pw) {
        stopTrace(pw, new File(TRACE_FILE));
    }

    /**
     * Stops collecting the transition trace and dump to trace to file.
     * @param outputFile The file to dump the transition trace to.
     */
    public void stopTrace(@Nullable PrintWriter pw, File outputFile) {
        if (IS_USER) {
            LogAndPrintln.e(pw, "Tracing is not supported on user builds.");
            return;
        }
        Trace.beginSection("Tracer#stopTrace");
        LogAndPrintln.i(pw, "Stopping shell transition trace.");
        synchronized (mEnabledLock) {
            mActiveTracingEnabled = false;
            writeTraceToFileLocked(pw, outputFile);
            mTraceBuffer.resetBuffer();
            mTraceBuffer.setCapacity(ALWAYS_ON_TRACING_CAPACITY);
        }
        Trace.endSection();
    }

    /**
     * Being called while taking a bugreport so that tracing files can be included in the bugreport.
     *
@@ -213,6 +264,39 @@ public class Tracer {
        }
    }

    @Override
    public boolean onShellCommand(String[] args, PrintWriter pw) {
        switch (args[0]) {
            case "start": {
                startTrace(pw);
                return true;
            }
            case "stop": {
                stopTrace(pw);
                return true;
            }
            case "save-for-bugreport": {
                saveForBugreport(pw);
                return true;
            }
            default: {
                pw.println("Invalid command: " + args[0]);
                printShellCommandHelp(pw, "");
                return false;
            }
        }
    }

    @Override
    public void printShellCommandHelp(PrintWriter pw, String prefix) {
        pw.println(prefix + "start");
        pw.println(prefix + "  Start tracing the transitions.");
        pw.println(prefix + "stop");
        pw.println(prefix + "  Stop tracing the transitions.");
        pw.println(prefix + "save-for-bugreport");
        pw.println(prefix + "  Flush in memory transition trace to file.");
    }

    private static class LogAndPrintln {
        private static final String LOG_TAG = "ShellTransitionTracer";

+50 −2
Original line number Diff line number Diff line
@@ -74,10 +74,12 @@ import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.util.TransitionUtil;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;

@@ -106,7 +108,8 @@ import java.util.Arrays;
 * track, it will be marked as SYNC. This means that all currently active tracks must be flushed
 * before the SYNC transition can play.
 */
public class Transitions implements RemoteCallable<Transitions> {
public class Transitions implements RemoteCallable<Transitions>,
        ShellCommandHandler.ShellCommandActionHandler {
    static final String TAG = "ShellTransitions";

    /** Set to {@code true} to enable shell transitions. */
@@ -171,6 +174,9 @@ public class Transitions implements RemoteCallable<Transitions> {
    /** List of possible handlers. Ordered by specificity (eg. tapped back to front). */
    private final ArrayList<TransitionHandler> mHandlers = new ArrayList<>();

    @Nullable
    private final ShellCommandHandler mShellCommandHandler;

    private final ArrayList<TransitionObserver> mObservers = new ArrayList<>();

    /** List of {@link Runnable} instances to run when the last active transition has finished.  */
@@ -246,8 +252,23 @@ public class Transitions implements RemoteCallable<Transitions> {
            @NonNull WindowOrganizer organizer,
            @NonNull TransactionPool pool,
            @NonNull DisplayController displayController,
            @NonNull ShellExecutor mainExecutor, @NonNull Handler mainHandler,
            @NonNull ShellExecutor mainExecutor,
            @NonNull Handler mainHandler,
            @NonNull ShellExecutor animExecutor) {
        this(context, shellInit, shellController, organizer, pool, displayController, mainExecutor,
                mainHandler, animExecutor, null);
    }

    public Transitions(@NonNull Context context,
            @NonNull ShellInit shellInit,
            @NonNull ShellController shellController,
            @NonNull WindowOrganizer organizer,
            @NonNull TransactionPool pool,
            @NonNull DisplayController displayController,
            @NonNull ShellExecutor mainExecutor,
            @NonNull Handler mainHandler,
            @NonNull ShellExecutor animExecutor,
            @Nullable ShellCommandHandler shellCommandHandler) {
        mOrganizer = organizer;
        mContext = context;
        mMainExecutor = mainExecutor;
@@ -263,6 +284,7 @@ public class Transitions implements RemoteCallable<Transitions> {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "addHandler: Default");
        // Next lowest priority is remote transitions.
        mHandlers.add(mRemoteTransitionHandler);
        mShellCommandHandler = shellCommandHandler;
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "addHandler: Remote");
        shellInit.addInitCallback(this::onInit, this);
    }
@@ -294,6 +316,10 @@ public class Transitions implements RemoteCallable<Transitions> {
            // Pre-load the instance.
            TransitionMetrics.getInstance();
        }

        if (mShellCommandHandler != null) {
            mShellCommandHandler.addCommandCallback("transitions", this, this);
        }
    }

    public boolean isRegistered() {
@@ -1373,4 +1399,26 @@ public class Transitions implements RemoteCallable<Transitions> {
            mMainExecutor.execute(() -> dispatchAnimScaleSetting(mTransitionAnimationScaleSetting));
        }
    }


    @Override
    public boolean onShellCommand(String[] args, PrintWriter pw) {
        switch (args[0]) {
            case "tracing": {
                mTracer.onShellCommand(Arrays.copyOfRange(args, 1, args.length), pw);
                return true;
            }
            default: {
                pw.println("Invalid command: " + args[0]);
                printShellCommandHelp(pw, "");
                return false;
            }
        }
    }

    @Override
    public void printShellCommandHelp(PrintWriter pw, String prefix) {
        pw.println(prefix + "tracing");
        mTracer.printShellCommandHelp(pw, prefix + "  ");
    }
}