Add shell side transition trace to bug reports

Test: atest BugreportManagerTestCases
Bug: 276701336
Bug: 277181336
Bug: 278691227
Change-Id: If53cce37f4787d4e03fbee4cbe5b2808719e011f
This commit is contained in:
Pablo Gamito
2023-04-14 15:32:20 +00:00
parent 909c8edd99
commit eaf61d885e
4 changed files with 139 additions and 5 deletions

View File

@@ -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"),

View File

@@ -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

View File

@@ -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";

View File

@@ -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 + " ");
}
}