diff --git a/core/java/com/android/internal/util/TraceBuffer.java b/core/java/com/android/internal/util/TraceBuffer.java
index bfcd65d4f2778..fcc77bd4f043b 100644
--- a/core/java/com/android/internal/util/TraceBuffer.java
+++ b/core/java/com/android/internal/util/TraceBuffer.java
@@ -103,6 +103,10 @@ public class TraceBuffer
{
this(bufferCapacity, new ProtoOutputStreamProvider(), null);
}
+ public TraceBuffer(int bufferCapacity, Consumer protoDequeuedCallback) {
+ this(bufferCapacity, new ProtoOutputStreamProvider(), protoDequeuedCallback);
+ }
+
public TraceBuffer(int bufferCapacity, ProtoProvider protoProvider,
Consumer protoDequeuedCallback) {
mBufferCapacity = bufferCapacity;
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index 54978bd4496df..6a79bc1f46c2c 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -125,6 +125,34 @@ prebuilt_etc {
// End ProtoLog
+gensrcs {
+ name: "wm-shell-protos",
+
+ tools: [
+ "aprotoc",
+ "protoc-gen-javastream",
+ "soong_zip",
+ ],
+
+ tool_files: [
+ ":libprotobuf-internal-protos",
+ ],
+
+ cmd: "mkdir -p $(genDir)/$(in) " +
+ "&& $(location aprotoc) " +
+ " --plugin=$(location protoc-gen-javastream) " +
+ " --javastream_out=$(genDir)/$(in) " +
+ " -Iexternal/protobuf/src " +
+ " -I . " +
+ " $(in) " +
+ "&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)",
+
+ srcs: [
+ "proto/**/*.proto",
+ ],
+ output_extension: "srcjar",
+}
+
java_library {
name: "WindowManager-Shell-proto",
@@ -142,6 +170,7 @@ android_library {
// TODO(b/168581922) protologtool do not support kotlin(*.kt)
":wm_shell-sources-kt",
":wm_shell-aidls",
+ ":wm-shell-protos",
],
resource_dirs: [
"res",
diff --git a/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto b/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto
new file mode 100644
index 0000000000000..6e0110193a057
--- /dev/null
+++ b/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package com.android.wm.shell;
+
+option java_multiple_files = true;
+
+/* Represents a file full of transition entries.
+ Encoded, it should start with 0x09 0x57 0x4D 0x53 0x54 0x52 0x41 0x43 0x45 (.WMSTRACE), such
+ that it can be easily identified. */
+message WmShellTransitionTraceProto {
+ /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L
+ (this is needed because enums have to be 32 bits and there's no nice way to put 64bit
+ constants into .proto files. */
+ enum MagicNumber {
+ INVALID = 0;
+ MAGIC_NUMBER_L = 0x54534D57; /* WMST (little-endian ASCII) */
+ MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */
+ }
+
+ // Must be the first field, set to value in MagicNumber
+ required fixed64 magic_number = 1;
+ repeated Transition transitions = 2;
+ repeated HandlerMapping handlerMappings = 3;
+}
+
+message Transition {
+ required int32 id = 1;
+ optional int64 dispatch_time_ns = 2;
+ optional int32 handler = 3;
+ optional int64 merge_time_ns = 4;
+ optional int64 merge_request_time_ns = 5;
+ optional int32 merged_into = 6;
+ optional int64 abort_time_ns = 7;
+}
+
+message HandlerMapping {
+ required int32 id = 1;
+ required string name = 2;
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java
new file mode 100644
index 0000000000000..7753d174e68c9
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.transition;
+
+import static android.os.Build.IS_USER;
+
+import static com.android.wm.shell.WmShellTransitionTraceProto.MAGIC_NUMBER;
+import static com.android.wm.shell.WmShellTransitionTraceProto.MAGIC_NUMBER_H;
+import static com.android.wm.shell.WmShellTransitionTraceProto.MAGIC_NUMBER_L;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.SystemClock;
+import android.os.Trace;
+import android.util.Log;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.util.TraceBuffer;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Helper class to collect and dump transition traces.
+ */
+public class Tracer {
+ private static final int ALWAYS_ON_TRACING_CAPACITY = 15 * 1024; // 15 KB
+
+ private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
+
+ static final String WINSCOPE_EXT = ".winscope";
+ private static final String TRACE_FILE =
+ "/data/misc/wmtrace/shell_transition_trace" + WINSCOPE_EXT;
+
+ private final Object mEnabledLock = new Object();
+
+ private final TraceBuffer mTraceBuffer = new TraceBuffer(ALWAYS_ON_TRACING_CAPACITY,
+ (proto) -> handleOnEntryRemovedFromTrace(proto));
+ private final Map