Add metric for Android blocking calls for all calls in trace.

The metric aggregates all blocking calls from processes main thread.
This is a generic version of the 'android_blocking_calls_cuj' metric,
that instead of only considering what's happening inside each CUJ considers
the entire trace, grouping per process.

Bug: 320674308
Test: tools/diff_test_trace_processor.py --name-filter ".*android_blocking_calls.*" out/default/trace_processor_shell
Flag: None

Change-Id: I0737b82c227ca1797cdcfc1198ea8e9f84c80c38
diff --git a/Android.bp b/Android.bp
index 585df73..f5f9b35 100644
--- a/Android.bp
+++ b/Android.bp
@@ -5151,6 +5151,7 @@
         "protos/perfetto/metrics/android/ad_services_metric.proto",
         "protos/perfetto/metrics/android/android_blocking_call.proto",
         "protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.proto",
+        "protos/perfetto/metrics/android/android_blocking_calls_unagg.proto",
         "protos/perfetto/metrics/android/android_boot.proto",
         "protos/perfetto/metrics/android/android_boot_unagg.proto",
         "protos/perfetto/metrics/android/android_frame_timeline_metric.proto",
@@ -5239,6 +5240,7 @@
         "protos/perfetto/metrics/android/ad_services_metric.proto",
         "protos/perfetto/metrics/android/android_blocking_call.proto",
         "protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.proto",
+        "protos/perfetto/metrics/android/android_blocking_calls_unagg.proto",
         "protos/perfetto/metrics/android/android_boot.proto",
         "protos/perfetto/metrics/android/android_boot_unagg.proto",
         "protos/perfetto/metrics/android/android_frame_timeline_metric.proto",
@@ -5310,6 +5312,7 @@
         "protos/perfetto/metrics/android/ad_services_metric.proto",
         "protos/perfetto/metrics/android/android_blocking_call.proto",
         "protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.proto",
+        "protos/perfetto/metrics/android/android_blocking_calls_unagg.proto",
         "protos/perfetto/metrics/android/android_boot.proto",
         "protos/perfetto/metrics/android/android_boot_unagg.proto",
         "protos/perfetto/metrics/android/android_frame_timeline_metric.proto",
@@ -11947,6 +11950,7 @@
         "src/trace_processor/metrics/sql/android/android_batt.sql",
         "src/trace_processor/metrics/sql/android/android_binder.sql",
         "src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_metric.sql",
+        "src/trace_processor/metrics/sql/android/android_blocking_calls_unagg.sql",
         "src/trace_processor/metrics/sql/android/android_boot.sql",
         "src/trace_processor/metrics/sql/android/android_boot_unagg.sql",
         "src/trace_processor/metrics/sql/android/android_camera.sql",
diff --git a/BUILD b/BUILD
index d678720..0efbc3a 100644
--- a/BUILD
+++ b/BUILD
@@ -1950,6 +1950,7 @@
         "src/trace_processor/metrics/sql/android/android_batt.sql",
         "src/trace_processor/metrics/sql/android/android_binder.sql",
         "src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_metric.sql",
+        "src/trace_processor/metrics/sql/android/android_blocking_calls_unagg.sql",
         "src/trace_processor/metrics/sql/android/android_boot.sql",
         "src/trace_processor/metrics/sql/android/android_boot_unagg.sql",
         "src/trace_processor/metrics/sql/android/android_camera.sql",
@@ -4370,6 +4371,7 @@
         "protos/perfetto/metrics/android/ad_services_metric.proto",
         "protos/perfetto/metrics/android/android_blocking_call.proto",
         "protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.proto",
+        "protos/perfetto/metrics/android/android_blocking_calls_unagg.proto",
         "protos/perfetto/metrics/android/android_boot.proto",
         "protos/perfetto/metrics/android/android_boot_unagg.proto",
         "protos/perfetto/metrics/android/android_frame_timeline_metric.proto",
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index 33f4195..5b8fab6 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -23,6 +23,7 @@
     "ad_services_metric.proto",
     "android_blocking_call.proto",
     "android_blocking_calls_cuj_metric.proto",
+    "android_blocking_calls_unagg.proto",
     "android_boot.proto",
     "android_boot_unagg.proto",
     "android_frame_timeline_metric.proto",
diff --git a/protos/perfetto/metrics/android/android_blocking_calls_unagg.proto b/protos/perfetto/metrics/android/android_blocking_calls_unagg.proto
new file mode 100644
index 0000000..96b73ba
--- /dev/null
+++ b/protos/perfetto/metrics/android/android_blocking_calls_unagg.proto
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 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 perfetto.protos;
+
+import "protos/perfetto/metrics/android/android_blocking_call.proto";
+import "protos/perfetto/metrics/android/process_metadata.proto";
+
+// All blocking calls for a trace. Shows count and total duration for each.
+message AndroidBlockingCallsUnagg {
+
+    repeated ProcessWithBlockingCalls process_with_blocking_calls = 1;
+
+    message ProcessWithBlockingCalls {
+        // Details about the process (uid, version, etc)
+        optional AndroidProcessMetadata process = 1;
+
+        // List of blocking calls on the process main thread.
+        repeated AndroidBlockingCall blocking_calls = 2;
+    }
+}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index f06f085..83395ec 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -29,6 +29,7 @@
 import "protos/perfetto/metrics/android/batt_metric.proto";
 import "protos/perfetto/metrics/android/android_sysui_notifications_blocking_calls_metric.proto";
 import "protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.proto";
+import "protos/perfetto/metrics/android/android_blocking_calls_unagg.proto";
 import "protos/perfetto/metrics/android/codec_metrics.proto";
 import "protos/perfetto/metrics/android/cpu_metric.proto";
 import "protos/perfetto/metrics/android/camera_metric.proto";
@@ -116,7 +117,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 64
+// Next id: 66
 message TraceMetrics {
   reserved 4, 10, 13, 14, 16, 19;
 
@@ -294,6 +295,9 @@
   // Specific for Android Auto
   optional AndroidMultiuserMetric android_auto_multiuser = 64;
 
+  // All blocking calls (e.g. binder calls) for a trace.
+  optional AndroidBlockingCallsUnagg android_blocking_calls_unagg = 65;
+
   // Demo extensions.
   extensions 450 to 499;
 
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index b2c3392..abfe9f6 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -145,6 +145,24 @@
 
 // End of protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.proto
 
+// Begin of protos/perfetto/metrics/android/android_blocking_calls_unagg.proto
+
+// All blocking calls for a trace. Shows count and total duration for each.
+message AndroidBlockingCallsUnagg {
+
+    repeated ProcessWithBlockingCalls process_with_blocking_calls = 1;
+
+    message ProcessWithBlockingCalls {
+        // Details about the process (uid, version, etc)
+        optional AndroidProcessMetadata process = 1;
+
+        // List of blocking calls on the process main thread.
+        repeated AndroidBlockingCall blocking_calls = 2;
+    }
+}
+
+// End of protos/perfetto/metrics/android/android_blocking_calls_unagg.proto
+
 // Begin of protos/perfetto/metrics/android/android_boot.proto
 
 // This metric computes how much time processes spend in UNINTERRUPTIBLE_SLEEP
@@ -2520,7 +2538,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 64
+// Next id: 66
 message TraceMetrics {
   reserved 4, 10, 13, 14, 16, 19;
 
@@ -2698,6 +2716,9 @@
   // Specific for Android Auto
   optional AndroidMultiuserMetric android_auto_multiuser = 64;
 
+  // All blocking calls (e.g. binder calls) for a trace.
+  optional AndroidBlockingCallsUnagg android_blocking_calls_unagg = 65;
+
   // Demo extensions.
   extensions 450 to 499;
 
diff --git a/python/perfetto/trace_processor/metrics.descriptor b/python/perfetto/trace_processor/metrics.descriptor
index 6b4b352..a5fe326 100644
--- a/python/perfetto/trace_processor/metrics.descriptor
+++ b/python/perfetto/trace_processor/metrics.descriptor
Binary files differ
diff --git a/src/trace_processor/metrics/sql/android/BUILD.gn b/src/trace_processor/metrics/sql/android/BUILD.gn
index f87b560..bd77d0a 100644
--- a/src/trace_processor/metrics/sql/android/BUILD.gn
+++ b/src/trace_processor/metrics/sql/android/BUILD.gn
@@ -25,6 +25,7 @@
     "android_batt.sql",
     "android_binder.sql",
     "android_blocking_calls_cuj_metric.sql",
+    "android_blocking_calls_unagg.sql",
     "android_boot.sql",
     "android_boot_unagg.sql",
     "android_camera.sql",
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 eaa2104..5838125 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
@@ -21,6 +21,7 @@
 
 INCLUDE PERFETTO MODULE android.slices;
 INCLUDE PERFETTO MODULE android.binder;
+INCLUDE PERFETTO MODULE android.critical_blocking_calls;
 
 -- Jank "J<*>" and latency "L<*>" cujs are put together in android_cujs table.
 -- They are computed separately as latency ones are slightly different, don't
@@ -75,99 +76,22 @@
 SELECT ROW_NUMBER() OVER (ORDER BY ts) AS cuj_id, *
 FROM all_cujs;
 
-DROP TABLE IF EXISTS relevant_binder_calls_with_names;
-CREATE TABLE relevant_binder_calls_with_names AS
-SELECT DISTINCT
-    tx.aidl_name AS name,
-    tx.client_ts AS ts,
-    s.track_id,
-    tx.client_dur AS dur,
-    s.id,
-    tx.client_process as process_name,
-    tx.client_utid as utid,
-    tx.client_upid as upid
-FROM android_binder_txns AS tx
-         JOIN slice AS s ON s.id = tx.binder_txn_id
-WHERE is_main_thread AND aidl_name IS NOT NULL AND is_sync = 1;
-
-DROP TABLE IF EXISTS android_blocking_calls_cuj_calls;
-CREATE TABLE android_blocking_calls_cuj_calls AS
-WITH all_main_thread_relevant_slices AS (
-    SELECT DISTINCT
-        android_standardize_slice_name(s.name) AS name,
-        s.ts,
-        s.track_id,
-        s.dur,
-        s.id,
-        process.name AS process_name,
-        thread.utid,
-        process.upid
-    FROM slice s
-        JOIN thread_track ON s.track_id = thread_track.id
-        JOIN thread USING (utid)
-        JOIN process USING (upid)
-    WHERE
-        thread.is_main_thread AND (
-               s.name = 'measure'
-            OR s.name = 'layout'
-            OR s.name = 'configChanged'
-            OR s.name = 'animation'
-            OR s.name = 'input'
-            OR s.name = 'traversal'
-            OR s.name = 'Contending for pthread mutex'
-            OR s.name = 'postAndWait'
-            OR s.name GLOB 'monitor contention with*'
-            OR s.name GLOB 'SuspendThreadByThreadId*'
-            OR s.name GLOB 'LoadApkAssetsFd*'
-            OR s.name GLOB '*binder transaction*'
-            OR s.name GLOB 'inflate*'
-            OR s.name GLOB 'Lock contention on*'
-            OR s.name GLOB 'android.os.Handler: kotlinx.coroutines*'
-            OR s.name GLOB 'relayoutWindow*'
-            OR s.name GLOB 'ImageDecoder#decode*'
-            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
-        name,
-        ts,
-        track_id,
-        dur,
-        id,
-        process_name,
-        utid,
-        upid
-    FROM relevant_binder_calls_with_names
-),
--- Now we have:
---  (1) a list of slices from the main thread of each process
+-- We have:
+--  (1) a list of slices from the main thread of each process from the
+--  all_main_thread_relevant_slices table.
 --  (2) a list of android cuj with beginning, end, and process
 -- It's needed to:
 --  (1) assign a cuj to each slice. If there are multiple cujs going on during a
 --      slice, there needs to be 2 entries for that slice, one for each cuj id.
 --  (2) each slice needs to be trimmed to be fully inside the cuj associated
 --      (as we don't care about what's outside cujs)
+DROP TABLE IF EXISTS android_blocking_calls_cuj_calls;
+CREATE TABLE android_blocking_calls_cuj_calls AS
+WITH
 main_thread_slices_scoped_to_cujs AS (
 SELECT
     s.id,
     s.id AS slice_id,
-    s.track_id,
     s.name,
     max(s.ts, cuj.ts) AS ts,
     min(s.ts + s.dur, cuj.ts_end) as ts_end,
@@ -177,7 +101,7 @@
     s.process_name,
     s.upid,
     s.utid
-FROM all_main_thread_relevant_slices s
+FROM _android_critical_blocking_calls s
     JOIN  android_cujs cuj
     -- only when there is an overlap
     ON s.ts + s.dur > cuj.ts AND s.ts < cuj.ts_end
diff --git a/src/trace_processor/metrics/sql/android/android_blocking_calls_unagg.sql b/src/trace_processor/metrics/sql/android/android_blocking_calls_unagg.sql
new file mode 100644
index 0000000..2008c0b
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/android_blocking_calls_unagg.sql
@@ -0,0 +1,96 @@
+--
+-- Copyright 2024 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
+--
+--     https://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.
+
+SELECT RUN_METRIC('android/process_metadata.sql');
+
+INCLUDE PERFETTO MODULE android.slices;
+INCLUDE PERFETTO MODULE android.binder;
+INCLUDE PERFETTO MODULE android.critical_blocking_calls;
+
+DROP TABLE IF EXISTS process_info;
+CREATE TABLE process_info AS
+SELECT
+  process.upid AS upid,
+  process.name AS process_name,
+  process_metadata.metadata AS process_metadata
+FROM process
+JOIN process_metadata USING (upid);
+
+DROP TABLE IF EXISTS android_blocking_calls_unagg_calls;
+CREATE TABLE android_blocking_calls_unagg_calls AS
+SELECT
+  name,
+  COUNT(*) AS occurrences,
+  MAX(dur) AS max_dur_ns,
+  MIN(dur) AS min_dur_ns,
+  SUM(dur) AS total_dur_ns,
+  upid,
+  process_name
+FROM
+  _android_critical_blocking_calls
+GROUP BY name, upid, process_name;
+
+DROP TABLE IF EXISTS filtered_processes_with_non_zero_blocking_calls;
+CREATE TABLE filtered_processes_with_non_zero_blocking_calls AS
+SELECT pi.upid,
+  pi.process_name,
+  pi.process_metadata
+FROM process_info pi WHERE pi.upid IN
+  (SELECT DISTINCT upid FROM _android_critical_blocking_calls);
+
+
+DROP TABLE IF EXISTS filtered_processes_with_non_zero_blocking_calls;
+CREATE TABLE filtered_processes_with_non_zero_blocking_calls AS
+SELECT pi.upid,
+  pi.process_name,
+  pi.process_metadata
+FROM process_info pi WHERE pi.upid IN
+  (SELECT DISTINCT upid FROM _android_critical_blocking_calls);
+
+DROP VIEW IF EXISTS android_blocking_calls_unagg_output;
+CREATE PERFETTO VIEW android_blocking_calls_unagg_output AS
+SELECT AndroidBlockingCallsUnagg(
+  'process_with_blocking_calls', (
+     SELECT RepeatedField(
+       AndroidBlockingCallsUnagg_ProcessWithBlockingCalls(
+         'process', e.process_metadata,
+         'blocking_calls', (
+            SELECT RepeatedField(
+              AndroidBlockingCall(
+                'name', d.name,
+                'cnt', d.occurrences,
+                'total_dur_ms', CAST(total_dur_ns / 1e6 AS INT),
+                'max_dur_ms', CAST(max_dur_ns / 1e6 AS INT),
+                'min_dur_ms', CAST(min_dur_ns / 1e6 AS INT),
+                'total_dur_ns', d.total_dur_ns,
+                'max_dur_ns', d.max_dur_ns,
+                'min_dur_ns', d.min_dur_ns
+              )
+            ) FROM (
+            SELECT b.name,
+              b.occurrences,
+              b.total_dur_ns,
+              b.max_dur_ns,
+              b.min_dur_ns
+            FROM android_blocking_calls_unagg_calls b INNER JOIN filtered_processes_with_non_zero_blocking_calls c
+            ON b.upid = c.upid WHERE b.upid = e.upid
+            ORDER BY total_dur_ns DESC
+            ) d
+         )
+       )
+     )
+     FROM filtered_processes_with_non_zero_blocking_calls e
+  )
+);
diff --git a/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_unagg.out b/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_unagg.out
new file mode 100644
index 0000000..4f288a7
--- /dev/null
+++ b/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_unagg.out
@@ -0,0 +1,362 @@
+android_blocking_calls_unagg {
+  process_with_blocking_calls {
+    process {
+      name: "com.android.systemui"
+      uid: 10001
+      pid: 1000
+    }
+    blocking_calls {
+      name: "binder transaction"
+      cnt: 7
+      total_dur_ms: 20
+      max_dur_ms: 10
+      min_dur_ms: 1
+      total_dur_ns: 20000000
+      max_dur_ns: 10000000
+      min_dur_ns: 1000000
+    }
+    blocking_calls {
+      name: "monitor contention with <...>"
+      cnt: 1
+      total_dur_ms: 12
+      max_dur_ms: 12
+      min_dur_ms: 12
+      total_dur_ns: 12000000
+      max_dur_ns: 12000000
+      min_dur_ns: 12000000
+    }
+    blocking_calls {
+      name: "AIDL::java::IWindowManager::hasNavigationBar::server"
+      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
+    }
+  }
+  process_with_blocking_calls {
+   process {
+      name: "com.google.android.apps.nexuslauncher"
+      uid: 10002
+      pid: 2000
+    }
+    blocking_calls {
+      name: "binder transaction"
+      cnt: 6
+      total_dur_ms: 10
+      max_dur_ms: 3
+      min_dur_ms: 1
+      total_dur_ns: 10000000
+      max_dur_ns: 3000000
+      min_dur_ns: 1000000
+   }
+ }
+ process_with_blocking_calls {
+   process {
+     name: "com.google.android.third.process"
+     uid: 10003
+     pid: 3000
+   }
+
+   blocking_calls {
+     name: "CoroutineContinuation"
+     cnt: 2
+     total_dur_ms: 20
+     max_dur_ms: 10
+     min_dur_ms: 10
+     total_dur_ns: 20000000
+     max_dur_ns: 10000000
+     min_dur_ns: 10000000
+   }
+   blocking_calls {
+     name: "Contending for pthread mutex"
+     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: "ExpNotRow#onMeasure(BigTextStyle)"
+     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: "ExpNotRow#onMeasure(MessagingStyle)"
+     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: "Garbage Collector"
+     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: "ImageDecoder#decodeBitmap"
+     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: "ImageDecoder#decodeDrawable"
+     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: "LoadApkAssetsFd <...>"
+     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: "Lock contention on a monitor lock <...>"
+     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: "Lock contention on thread list lock <...>"
+     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: "Lock contention on thread suspend count lock <...>"
+     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: "NotificationStackScrollLayout#onMeasure"
+     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: "SuspendThreadByThreadId <...>"
+     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: "animation"
+     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: "binder transaction"
+     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: "configChanged"
+     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: "inflate"
+     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: "input"
+     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: "layout"
+     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: "measure"
+     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: "monitor contention with <...>"
+     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: "postAndWait"
+     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: "relayoutWindow <...>"
+     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: "traversal"
+     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
+   }
+}
+process_with_blocking_calls {
+   process {
+     name: "com.google.android.top.level.slices"
+     uid: 10004
+     pid: 4000
+   }
+
+   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
+   }
+   }
+}
diff --git a/test/trace_processor/diff_tests/metrics/android/tests.py b/test/trace_processor/diff_tests/metrics/android/tests.py
index 5038aec..06cbe59 100644
--- a/test/trace_processor/diff_tests/metrics/android/tests.py
+++ b/test/trace_processor/diff_tests/metrics/android/tests.py
@@ -121,6 +121,12 @@
         query=Metric('android_blocking_calls_cuj_metric'),
         out=Path('android_blocking_calls_cuj_metric.out'))
 
+  def test_android_blocking_calls_unagg(self):
+    return DiffTestBlueprint(
+        trace=Path('android_blocking_calls_cuj_metric.py'),
+        query=Metric('android_blocking_calls_unagg'),
+        out=Path('android_blocking_calls_unagg.out'))
+
   def test_android_blocking_calls_on_jank_cujs(self):
     return DiffTestBlueprint(
         trace=Path('../graphics/android_jank_cuj.py'),
@@ -296,4 +302,4 @@
            duration_ms: 3878
          }
        }
-       """))
\ No newline at end of file
+       """))
diff --git a/tools/check_sql_metrics.py b/tools/check_sql_metrics.py
index 3819c27..f025f47 100755
--- a/tools/check_sql_metrics.py
+++ b/tools/check_sql_metrics.py
@@ -41,6 +41,11 @@
         'android_cujs', 'relevant_binder_calls_with_names',
         'android_blocking_calls_cuj_calls'
     ],
+    ('/android'
+    '/android_blocking_calls_unagg.sql'): [
+        'filtered_processes_with_non_zero_blocking_calls',
+        'process_info', 'android_blocking_calls_unagg_calls'
+    ],
     '/android/jank/cujs.sql': ['android_jank_cuj'],
     '/chrome/gesture_flow_event.sql': [
         '{{prefix}}_latency_info_flow_step_filtered'