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

Commit 96a51f99 authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Add "cmd window trace save-for-bugreport"

This CL reworks our previous CL [1], which enabled "adb bugreport" to
include wintrace tracing files into bugreport.

In the previous CL there was a side-effect that wintrace tracing files
are saved not only when "adb bugreport" is executed but also when the
following command is manually executed.

  adb shell dumpsys window --dump-priority CRITICAL --proto

This is because we used the combination of
  --dump-priority CRITICAL
and
  --proto
as a signal that it's coming from "adb bugreport", but strictly
speaking it's not necessarily true.

Instead of relying on such a heuristic, this CL introduces a claer and
dedicated command as follows.

  adb shell cmd window tracing save-for-bugreport

With this, we can let "adb bugreport" trigger the above command to
make the behavior more understandable and maintainable.  Note that
this command is no-op when winscope is not running.

See the corresponding CL for frameworks/native [2] about how it's
triggered from "adb bugreport".

Our main motivation of this consolidation is to use the same pattern
for IME tracing, where we accidentally introduced Bug 177462676 while
attempting to save IME tracing data while running "adb bugreport" [3].

 [1]: I102bc4afab5efff361633d75c09af1df4a11812e
      9e260468
 [2]: I8be9dee9aa36c2b085596d58e418f8613d874500
      95305b3ba7bf18bc7ed3a07c67f84b1c2f4586f4
 [3]: Ie87eb8423e2bb70f28c330983d45b95e2e07062d
      ac24994a

Bug: 177462676
Test: Manually done as follows.
  1. adb shell cmd window tracing start
  2. adb logcat -d -s WindowTracing:*
       Make sure wintrace is not yet running
  3. adb shell dumpsys window \
         --dump-priority CRITICAL --proto > /dev/null
  4. adb logcat -d -s WindowTracing:*
       Make sure wintrace has not been stopped.
  5. adb shell cmd window tracing save-for-bugreport
  6. adb logcat -d -s WindowTracing:*
       Make sure wintrace was stopped then restarted.
  7. adb root && adb shell ls /data/misc/wmtrace/ -al
       Make sure wintrace files are saved.
Test: Manually done as follows.
  1. adb logcat -d -s WindowTracing:*
       Make sure wintrace is not yet running
  2. adb logcat -d -s WindowTracing:*
       Make sure there is no additional message
  3. adb shell cmd window tracing start
  4. adb logcat -d -s WindowTracing:*
       Make sure wintrace is running
  5. adb bugreport bugreport.zip
  6. adb logcat -d -s WindowTracing:*
       Make sure wintrace stopped then restarted.
  7. unzip -v bugreport.zip | grep wm_trace.pb
       Make sure "wm_trace.pb" is included.
  8. unzip -v bugreport.zip | grep wm_log.pb
       Make sure "wm_log.pb" is included.
Change-Id: I887ae6941b4844a606675b447f67ecee88d7f192
parent 167dea12
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -359,18 +359,6 @@ public class BaseProtoLogImpl {
                + "\nLogging definitions loaded: " + mViewerConfig.knownViewerStringsNumber();
    }

    /**
     * Writes the log buffer to a new file for the bugreport.
     *
     * This method is synchronized with {@code #startProtoLog(PrintWriter)} and
     * {@link #stopProtoLog(PrintWriter, boolean)}.
     */
    public void writeProtoLogToFile() {
        synchronized (mProtoLogEnabledLock) {
            writeProtoLogToFileLocked();
        }
    }

    private void writeProtoLogToFileLocked() {
        try {
            long offset =
+0 −9
Original line number Diff line number Diff line
@@ -273,7 +273,6 @@ import android.window.TaskSnapshot;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.IResultReceiver;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
@@ -529,14 +528,6 @@ public class WindowManagerService extends IWindowManager.Stub
        @Override
        public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args,
                boolean asProto) {
            // Bugreport dumps the trace 2x, 1x as proto and 1x as text. Save file to disk only 1x.
            if (asProto && mWindowTracing.isEnabled()) {
                mWindowTracing.stopTrace(null, false /* writeToFile */);
                BackgroundThread.getHandler().post(() -> {
                    mWindowTracing.writeTraceToFile();
                    mWindowTracing.startTrace(null);
                });
            }
            doDump(fd, pw, new String[] {"-a"}, asProto);
        }

+31 −26
Original line number Diff line number Diff line
@@ -114,15 +114,6 @@ class WindowTracing {
     * @param pw Print writer
     */
    void stopTrace(@Nullable PrintWriter pw) {
        stopTrace(pw, true /* writeToFile */);
    }

    /**
     * Stops the trace
     * @param pw Print writer
     * @param writeToFile If the current buffer should be written to disk or not
     */
    void stopTrace(@Nullable PrintWriter pw, boolean writeToFile) {
        if (IS_USER) {
            logAndPrintln(pw, "Error: Tracing is not supported on user builds.");
            return;
@@ -135,12 +126,35 @@ class WindowTracing {
                logAndPrintln(pw, "ERROR: tracing was re-enabled while waiting for flush.");
                throw new IllegalStateException("tracing enabled while waiting for flush.");
            }
            if (writeToFile) {
            writeTraceToFileLocked();
            logAndPrintln(pw, "Trace written to " + mTraceFile + ".");
        }
        ProtoLogImpl.getSingleInstance().stopProtoLog(pw, true);
    }

    /**
     * Stops the trace and write the current buffer to disk then restart, if it's already running.
     * @param pw Print writer
     */
    void saveForBugreport(@Nullable PrintWriter pw) {
        if (IS_USER) {
            logAndPrintln(pw, "Error: Tracing is not supported on user builds.");
            return;
        }
        synchronized (mEnabledLock) {
            if (!mEnabled) {
                return;
            }
            mEnabled = mEnabledLockFree = false;
            logAndPrintln(pw, "Stop tracing to " + mTraceFile + ". Waiting for traces to flush.");
            writeTraceToFileLocked();
            logAndPrintln(pw, "Trace written to " + mTraceFile + ".");
            ProtoLogImpl.getSingleInstance().stopProtoLog(pw, true);
            logAndPrintln(pw, "Start tracing to " + mTraceFile + ".");
            mBuffer.resetBuffer();
            mEnabled = mEnabledLockFree = true;
            ProtoLogImpl.getSingleInstance().startProtoLog(pw);
        }
        ProtoLogImpl.getSingleInstance().stopProtoLog(pw, writeToFile);
    }

    private void setLogLevel(@WindowTraceLogLevel int logLevel, PrintWriter pw) {
@@ -188,6 +202,9 @@ class WindowTracing {
            case "stop":
                stopTrace(pw);
                return 0;
            case "save-for-bugreport":
                saveForBugreport(pw);
                return 0;
            case "status":
                logAndPrintln(pw, getStatus());
                return 0;
@@ -230,6 +247,7 @@ class WindowTracing {
                pw.println("Window manager trace options:");
                pw.println("  start: Start logging");
                pw.println("  stop: Stop logging");
                pw.println("  save-for-bugreport: Save logging data to file if it's running.");
                pw.println("  frame: Log trace once per frame");
                pw.println("  transaction: Log each transaction");
                pw.println("  size: Set the maximum log size (in KB)");
@@ -316,19 +334,6 @@ class WindowTracing {
        }
    }

    /**
     * Writes the trace buffer to new file for the bugreport.
     *
     * This method is synchronized with {@code #startTrace(PrintWriter)} and
     * {@link #stopTrace(PrintWriter)}.
     */
    void writeTraceToFile() {
        synchronized (mEnabledLock) {
            writeTraceToFileLocked();
        }
        ProtoLogImpl.getSingleInstance().writeProtoLogToFile();
    }

    private void logAndPrintln(@Nullable PrintWriter pw, String msg) {
        Log.i(TAG, msg);
        if (pw != null) {