Merge "Revert^2 "Add top level handler slices to android_blocking_calls_cuj_metric"" into main
diff --git a/src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_metric.sql b/src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_metric.sql
index 7be45a6..35dcc55 100644
--- a/src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_metric.sql
+++ b/src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_metric.sql
@@ -130,6 +130,20 @@
             OR s.name GLOB 'NotificationStackScrollLayout#onMeasure'
             OR s.name GLOB 'ExpNotRow#*'
             OR s.name GLOB 'GC: Wait For*'
+            OR (
+                -- Some top level handler slices
+                    s.depth = 0
+                AND s.name NOT GLOB '*Choreographer*'
+                AND s.name NOT GLOB '*Input*'
+                AND s.name NOT GLOB '*input*'
+                AND s.name NOT GLOB 'android.os.Handler: #*'
+                AND (
+                   -- Handler pattern heuristics
+                      s.name GLOB '*Handler: *$*'
+                   OR s.name GLOB '*.*.*: *$*'
+                   OR s.name GLOB '*.*$*: #*'
+                )
+            )
         )
     UNION ALL
     SELECT
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/slices.sql b/src/trace_processor/perfetto_sql/stdlib/android/slices.sql
index 236ff48..40e6ccf 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/slices.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/slices.sql
@@ -13,6 +13,16 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 
+
+CREATE PERFETTO FUNCTION internal_remove_lambda_name(
+-- Raw slice name containing at least one "$"
+  name STRING)
+-- Removes everything after the first "$"
+RETURNS STRING AS
+SELECT
+    substr($name, 0, instr($name, "$"))
+END;
+
 -- Some slice names have params in them. This functions removes them to make it
 -- possible to aggregate by name.
 -- Some examples are:
@@ -39,5 +49,15 @@
     WHEN $name GLOB "OpenDexFilesFromOat*" THEN "OpenDexFilesFromOat"
     WHEN $name GLOB "Open oat file*" THEN "Open oat file"
     WHEN $name GLOB "GC: Wait For*" THEN "Garbage Collector"
+    -- Top level handlers slices heuristics:
+        -- E.g. android.os.Handler: com.android.systemui.qs.external.TileServiceManager$1
+        -- To: Handler: com.android.systemui.qs.external.TileServiceManager
+    WHEN $name GLOB "*Handler: *$*" THEN internal_remove_lambda_name(substr($name, instr($name, "Handler:")))
+        -- E.g. : android.view.ViewRootImpl$ViewRootHandler: com.android.systemui.someClass$enableMarquee$1
+        -- To: Handler: android.view.ViewRootImpl
+    WHEN $name GLOB "*.*.*: *$*" THEN "Handler: " || internal_remove_lambda_name(substr($name, ": "))
+        -- E.g.: android.os.AsyncTask$InternalHandler: #1
+        -- To: Handler: android.os.AsyncTask
+    WHEN $name GLOB "*.*$*: #*" THEN "Handler: " || internal_remove_lambda_name($name)
     ELSE $name
   END;
diff --git a/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.out b/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.out
index 6d99a2b..707bd49 100644
--- a/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.out
+++ b/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.out
@@ -274,6 +274,67 @@
   }
   cuj {
     id: 4
+    name: "CUJ_WITH_TOP_LEVEL_SLICES"
+    process {
+      name: "com.google.android.top.level.slices"
+      uid: 10004
+      pid: 4000
+    }
+    ts: 2000000
+    dur: 70000000
+    blocking_calls {
+      name: "Handler: android.os.AsyncTask"
+      cnt: 1
+      total_dur_ms: 10
+      max_dur_ms: 10
+      min_dur_ms: 10
+      total_dur_ns: 10000000
+      max_dur_ns: 10000000
+      min_dur_ns: 10000000
+    }
+    blocking_calls {
+      name: "Handler: android.view.View"
+      cnt: 1
+      total_dur_ms: 10
+      max_dur_ms: 10
+      min_dur_ms: 10
+      total_dur_ns: 10000000
+      max_dur_ns: 10000000
+      min_dur_ns: 10000000
+    }
+    blocking_calls {
+      name: "Handler: com.android.keyguard.KeyguardUpdateMonitor"
+      cnt: 1
+      total_dur_ms: 10
+      max_dur_ms: 10
+      min_dur_ms: 10
+      total_dur_ns: 10000000
+      max_dur_ns: 10000000
+      min_dur_ns: 10000000
+    }
+    blocking_calls {
+      name: "Handler: com.android.systemui.broadcast.ActionReceiver"
+      cnt: 1
+      total_dur_ms: 10
+      max_dur_ms: 10
+      min_dur_ms: 10
+      total_dur_ns: 10000000
+      max_dur_ns: 10000000
+      min_dur_ns: 10000000
+    }
+    blocking_calls {
+      name: "Handler: com.android.systemui.qs.external.TileServiceManager"
+      cnt: 1
+      total_dur_ms: 10
+      max_dur_ms: 10
+      min_dur_ms: 10
+      total_dur_ns: 10000000
+      max_dur_ns: 10000000
+      min_dur_ns: 10000000
+    }
+  }
+  cuj {
+    id: 5
     name: "OVERLAPPING_CUJ_1"
     process {
       name: "com.android.systemui"
@@ -294,7 +355,7 @@
     }
   }
   cuj {
-    id: 5
+    id: 6
     name: "OVERLAPPING_CUJ_2"
     process {
       name: "com.android.systemui"
@@ -315,7 +376,7 @@
     }
   }
   cuj {
-    id: 6
+    id: 7
     name: "WITH_NAMED_BINDER_TRANSACTION"
     process {
       name: "com.android.systemui"
diff --git a/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.py b/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.py
index 71f6d45..5a3b40c 100755
--- a/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.py
+++ b/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.py
@@ -23,6 +23,8 @@
 
 THIRD_PROCESS_PID = 3000
 
+TOP_LEVEL_SLICES_PID = 4000
+
 # List of blocking calls
 blocking_call_names = [
     'monitor contention with something else', 'SuspendThreadByThreadId 123',
@@ -38,6 +40,16 @@
     'GC: Wait For Completion Alloc', 'Should not be in the metric'
 ]
 
+top_level_names = [
+    'android.view.ViewRootImpl$ViewRootHandler: android.view.View$$Lambda4',
+    'android.os.AsyncTask$InternalHandler: #1',
+    'android.os.Handler: com.android.systemui.broadcast.ActionReceiver$1$1',
+    'com.android.keyguard.KeyguardUpdateMonitor$13: #302',
+    'android.os.Handler: com.android.systemui.qs.external.TileServiceManager$1',
+    # The following are not expected in the output
+    'receiveMessage(inputChannel=62b8bb4 NotificationShade',
+    'android.os.Handler: #0',
+]
 
 def add_main_thread_atrace(trace, ts, ts_end, buf, pid):
   trace.add_atrace_begin(ts=ts, tid=pid, pid=pid, buf=buf)
@@ -121,6 +133,43 @@
       pid=pid)
 
 
+def add_cuj_with_top_level_slices(trace, cuj_name, pid):
+  blocking_call_dur = 10_000_000
+  blocking_call_ts = 2_000_000
+
+  cuj_dur = len(top_level_names) * blocking_call_dur
+  add_async_trace(
+      trace,
+      ts=blocking_call_ts,
+      ts_end=blocking_call_ts + cuj_dur,
+      buf=cuj_name,
+      pid=pid)
+
+  for top_level_slice in top_level_names:
+    add_main_thread_atrace(
+        trace,
+        ts=blocking_call_ts,
+        ts_end=blocking_call_ts + blocking_call_dur,
+        buf=top_level_slice,
+        pid=pid)
+    blocking_call_ts += blocking_call_dur
+
+  # Some top level unrelated to handler
+  add_main_thread_atrace(
+      trace,
+      ts=blocking_call_ts,
+      ts_end=blocking_call_ts + blocking_call_dur,
+      buf="some top level slice that should not be in the output",
+      pid=pid)
+  # Nested inside the previous, should not be in the output as not top level.
+  add_main_thread_atrace(
+      trace,
+      ts=blocking_call_ts + 1,
+      ts_end=blocking_call_ts + blocking_call_dur - 1,
+      buf="should.not.be.in.the.output.Handler: not.in.the.output$1",
+      pid=pid)
+
+
 # Creates a cuj that contains one of each blocking call.
 def add_all_blocking_calls_in_cuj(trace, pid):
   blocking_call_dur = 10_000_000
@@ -213,6 +262,11 @@
       package_name="com.google.android.third.process",
       uid=10003,
       pid=THIRD_PROCESS_PID)
+  add_process(
+      trace,
+      package_name="com.google.android.top.level.slices",
+      uid=10004,
+      pid=TOP_LEVEL_SLICES_PID)
   trace.add_ftrace_packet(cpu=0)
   add_async_trace(trace, ts=0, ts_end=5, buf="J<IGNORED>", pid=SYSUI_PID)
   return trace
@@ -223,6 +277,8 @@
 add_cuj_with_blocking_calls(trace, "L<TEST_SYSUI_LATENCY_EVENT>", pid=SYSUI_PID)
 add_cuj_with_blocking_calls(
     trace, "L<TEST_LAUNCHER_LATENCY_EVENT>", pid=LAUNCHER_PID)
+add_cuj_with_top_level_slices(
+    trace, "L<CUJ_WITH_TOP_LEVEL_SLICES>", pid=TOP_LEVEL_SLICES_PID)
 
 add_all_blocking_calls_in_cuj(trace, pid=THIRD_PROCESS_PID)
 
diff --git a/test/trace_processor/diff_tests/stdlib/android/android_slice_standardization.out b/test/trace_processor/diff_tests/stdlib/android/android_slice_standardization.out
deleted file mode 100644
index c885c7f..0000000
--- a/test/trace_processor/diff_tests/stdlib/android/android_slice_standardization.out
+++ /dev/null
@@ -1,14 +0,0 @@
-"name"
-"APK load"
-"Choreographer#doFrame"
-"CoroutineContinuation"
-"CoroutineContinuation"
-"DrawFrames"
-"Garbage Collector"
-"LoadApkAssetsFd <...>"
-"Lock contention on <...>"
-"Open oat file"
-"OpenDexFilesFromOat"
-"SuspendThreadByThreadId <...>"
-"monitor contention with <...>"
-"relayoutWindow <...>"
diff --git a/test/trace_processor/diff_tests/stdlib/android/android_slice_standardization.py b/test/trace_processor/diff_tests/stdlib/android/android_slice_standardization.py
index af3cd24..0b07010 100644
--- a/test/trace_processor/diff_tests/stdlib/android/android_slice_standardization.py
+++ b/test/trace_processor/diff_tests/stdlib/android/android_slice_standardization.py
@@ -41,6 +41,11 @@
     "Open oat file /data/misc/apexdata/com.android.art/dalvik-cache/boot.oat",
     "android.os.Handler: kotlinx.coroutines.internal.DispatchedContinuation",
     "GC: Wait For Completion Alloc",
+    'android.view.ViewRootImpl$ViewRootHandler: android.view.View$$Lambda4',
+    'android.os.AsyncTask$InternalHandler: #1',
+    'android.os.Handler: com.android.systemui.broadcast.ActionReceiver$1$1',
+    'com.android.keyguard.KeyguardUpdateMonitor$13: #302',
+    'android.os.Handler: com.android.systemui.qs.TileServiceManager$1',
 ]
 
 for name in slices_to_standardize:
diff --git a/test/trace_processor/diff_tests/stdlib/android/tests.py b/test/trace_processor/diff_tests/stdlib/android/tests.py
index 3f2800f..00c4481 100644
--- a/test/trace_processor/diff_tests/stdlib/android/tests.py
+++ b/test/trace_processor/diff_tests/stdlib/android/tests.py
@@ -226,9 +226,28 @@
         INCLUDE PERFETTO MODULE android.slices;
         SELECT ANDROID_STANDARDIZE_SLICE_NAME(slice.name) name
         FROM slice
-        ORDER BY name;
         """,
-        out=Path('android_slice_standardization.out'))
+        out=Csv("""
+        "name"
+        "Lock contention on <...>"
+        "monitor contention with <...>"
+        "SuspendThreadByThreadId <...>"
+        "LoadApkAssetsFd <...>"
+        "relayoutWindow <...>"
+        "CoroutineContinuation"
+        "Choreographer#doFrame"
+        "DrawFrames"
+        "APK load"
+        "OpenDexFilesFromOat"
+        "Open oat file"
+        "CoroutineContinuation"
+        "Garbage Collector"
+        "Handler: android.view.View"
+        "Handler: android.os.AsyncTask"
+        "Handler: com.android.systemui.broadcast.ActionReceiver"
+        "Handler: com.android.keyguard.KeyguardUpdateMonitor"
+        "Handler: com.android.systemui.qs.TileServiceManager"
+        """))
 
   def test_monitor_contention_extraction(self):
     return DiffTestBlueprint(