Add metrics for broadcasts

Test: tools/diff_test_trace_processor.py <path to trace processor binary> --name-filter=".*android_boot*"
Bug: 343915767
Change-Id: I209b5063a556fd218d2329635084789e9cdec2fa
diff --git a/Android.bp b/Android.bp
index 6f7501b..1940872 100644
--- a/Android.bp
+++ b/Android.bp
@@ -5234,6 +5234,7 @@
         "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_broadcasts_metric.proto",
         "protos/perfetto/metrics/android/android_frame_timeline_metric.proto",
         "protos/perfetto/metrics/android/android_garbage_collection_unagg_metric.proto",
         "protos/perfetto/metrics/android/android_oom_adjuster_metric.proto",
@@ -5326,6 +5327,7 @@
         "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_broadcasts_metric.proto",
         "protos/perfetto/metrics/android/android_frame_timeline_metric.proto",
         "protos/perfetto/metrics/android/android_garbage_collection_unagg_metric.proto",
         "protos/perfetto/metrics/android/android_oom_adjuster_metric.proto",
@@ -5402,6 +5404,7 @@
         "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_broadcasts_metric.proto",
         "protos/perfetto/metrics/android/android_frame_timeline_metric.proto",
         "protos/perfetto/metrics/android/android_garbage_collection_unagg_metric.proto",
         "protos/perfetto/metrics/android/android_oom_adjuster_metric.proto",
@@ -12684,6 +12687,7 @@
         "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_broadcasts.sql",
         "src/trace_processor/metrics/sql/android/android_camera.sql",
         "src/trace_processor/metrics/sql/android/android_camera_unagg.sql",
         "src/trace_processor/metrics/sql/android/android_cpu.sql",
diff --git a/BUILD b/BUILD
index cc2854f..06a7b74 100644
--- a/BUILD
+++ b/BUILD
@@ -2042,6 +2042,7 @@
         "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_broadcasts.sql",
         "src/trace_processor/metrics/sql/android/android_camera.sql",
         "src/trace_processor/metrics/sql/android/android_camera_unagg.sql",
         "src/trace_processor/metrics/sql/android/android_cpu.sql",
@@ -4614,6 +4615,7 @@
         "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_broadcasts_metric.proto",
         "protos/perfetto/metrics/android/android_frame_timeline_metric.proto",
         "protos/perfetto/metrics/android/android_garbage_collection_unagg_metric.proto",
         "protos/perfetto/metrics/android/android_oom_adjuster_metric.proto",
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index af7aa8f..b9fe7ca 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -26,6 +26,7 @@
     "android_blocking_calls_unagg.proto",
     "android_boot.proto",
     "android_boot_unagg.proto",
+    "android_broadcasts_metric.proto",
     "android_frame_timeline_metric.proto",
     "android_garbage_collection_unagg_metric.proto",
     "android_oom_adjuster_metric.proto",
diff --git a/protos/perfetto/metrics/android/android_boot.proto b/protos/perfetto/metrics/android/android_boot.proto
index 938e49e..d6c33f8 100644
--- a/protos/perfetto/metrics/android/android_boot.proto
+++ b/protos/perfetto/metrics/android/android_boot.proto
@@ -83,6 +83,17 @@
     optional int64 oom_adj_event_count = 4;
     optional string oom_adj_reason = 5;
   }
+  message BroadcastCountAggregation {
+    optional string name = 1;
+    optional int64 count = 2;
+  }
+  // Stats for Broadcasts aggregated with duration.
+  message BroadcastDurationAggregation {
+    optional string name = 1;
+    optional double avg_duration = 2;
+    optional int64 max_duration = 3;
+    optional int64 sum_duration = 4;
+}
   optional ProcessStartAggregation full_trace_process_start_aggregation = 6;
   optional ProcessStartAggregation post_boot_process_start_aggregation = 7;
   optional GarbageCollectionAggregation full_trace_gc_aggregation = 8;
@@ -98,4 +109,9 @@
   repeated OomAdjBucketDurationAggregation
       post_boot_oom_adj_bucket_duration_agg_by_process = 14;
   repeated OomAdjDurationAggregation post_boot_oom_adj_duration_agg = 15;
+  repeated BroadcastCountAggregation post_boot_broadcast_process_count_by_intent = 16;
+  repeated BroadcastCountAggregation post_boot_broadcast_count_by_process = 17;
+  repeated BroadcastDurationAggregation post_boot_brodcast_duration_agg_by_intent = 18;
+  repeated BroadcastDurationAggregation post_boot_brodcast_duration_agg_by_process = 19;
+
 }
diff --git a/protos/perfetto/metrics/android/android_broadcasts_metric.proto b/protos/perfetto/metrics/android/android_broadcasts_metric.proto
new file mode 100644
index 0000000..554b42d
--- /dev/null
+++ b/protos/perfetto/metrics/android/android_broadcasts_metric.proto
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+  // Provides aggregated information about broadcasts
+  message AndroidBroadcastsMetric {
+    // Next id: 5
+    // Stats for Broadcasts aggregated with count.
+    message BroadcastCountAggregation {
+      optional string name = 1;
+      optional int64 count = 2;
+    }
+    // Stats for Broadcasts aggregated with duration.
+    message BroadcastDurationAggregation {
+      optional string name = 1;
+      optional double avg_duration = 2;
+      optional int64 max_duration = 3;
+      optional int64 sum_duration = 4;
+    }
+    repeated BroadcastCountAggregation process_count_by_intent = 1;
+    repeated BroadcastCountAggregation broadcast_count_by_process = 2;
+    repeated BroadcastDurationAggregation brodcast_duration_agg_by_intent = 3;
+    repeated BroadcastDurationAggregation brodcast_duration_agg_by_process = 4;
+  }
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index eb9f6ea..e4199f7 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -74,6 +74,7 @@
 import "protos/perfetto/metrics/android/monitor_contention_agg_metric.proto";
 import "protos/perfetto/metrics/android/app_process_starts_metric.proto";
 import "protos/perfetto/metrics/android/android_oom_adjuster_metric.proto";
+import "protos/perfetto/metrics/android/android_broadcasts_metric.proto";
 
 // Trace processor metadata
 message TraceMetadata {
@@ -120,7 +121,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 68
+// Next id: 69
 message TraceMetrics {
   reserved 4, 10, 13, 14, 16, 19;
 
@@ -312,6 +313,9 @@
   // Android OOM unaggregated metrics.
   optional AndroidOomAdjusterMetric android_oom_adjuster = 66;
 
+  // Android Broadcasts aggregated metrics
+  optional AndroidBroadcastsMetric android_broadcasts = 68;
+
   // Android
   // 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 cc4ff23..dce14b3 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -223,6 +223,17 @@
     optional int64 oom_adj_event_count = 4;
     optional string oom_adj_reason = 5;
   }
+  message BroadcastCountAggregation {
+    optional string name = 1;
+    optional int64 count = 2;
+  }
+  // Stats for Broadcasts aggregated with duration.
+  message BroadcastDurationAggregation {
+    optional string name = 1;
+    optional double avg_duration = 2;
+    optional int64 max_duration = 3;
+    optional int64 sum_duration = 4;
+}
   optional ProcessStartAggregation full_trace_process_start_aggregation = 6;
   optional ProcessStartAggregation post_boot_process_start_aggregation = 7;
   optional GarbageCollectionAggregation full_trace_gc_aggregation = 8;
@@ -238,6 +249,11 @@
   repeated OomAdjBucketDurationAggregation
       post_boot_oom_adj_bucket_duration_agg_by_process = 14;
   repeated OomAdjDurationAggregation post_boot_oom_adj_duration_agg = 15;
+  repeated BroadcastCountAggregation post_boot_broadcast_process_count_by_intent = 16;
+  repeated BroadcastCountAggregation post_boot_broadcast_count_by_process = 17;
+  repeated BroadcastDurationAggregation post_boot_brodcast_duration_agg_by_intent = 18;
+  repeated BroadcastDurationAggregation post_boot_brodcast_duration_agg_by_process = 19;
+
 }
 
 // End of protos/perfetto/metrics/android/android_boot.proto
@@ -326,6 +342,31 @@
 
 // End of protos/perfetto/metrics/android/android_boot_unagg.proto
 
+// Begin of protos/perfetto/metrics/android/android_broadcasts_metric.proto
+
+  // Provides aggregated information about broadcasts
+  message AndroidBroadcastsMetric {
+    // Next id: 5
+    // Stats for Broadcasts aggregated with count.
+    message BroadcastCountAggregation {
+      optional string name = 1;
+      optional int64 count = 2;
+    }
+    // Stats for Broadcasts aggregated with duration.
+    message BroadcastDurationAggregation {
+      optional string name = 1;
+      optional double avg_duration = 2;
+      optional int64 max_duration = 3;
+      optional int64 sum_duration = 4;
+    }
+    repeated BroadcastCountAggregation process_count_by_intent = 1;
+    repeated BroadcastCountAggregation broadcast_count_by_process = 2;
+    repeated BroadcastDurationAggregation brodcast_duration_agg_by_intent = 3;
+    repeated BroadcastDurationAggregation brodcast_duration_agg_by_process = 4;
+  }
+
+// End of protos/perfetto/metrics/android/android_broadcasts_metric.proto
+
 // Begin of protos/perfetto/metrics/android/android_frame_timeline_metric.proto
 
 message AndroidFrameTimelineMetric {
@@ -2814,7 +2855,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 68
+// Next id: 69
 message TraceMetrics {
   reserved 4, 10, 13, 14, 16, 19;
 
@@ -3006,6 +3047,9 @@
   // Android OOM unaggregated metrics.
   optional AndroidOomAdjusterMetric android_oom_adjuster = 66;
 
+  // Android Broadcasts aggregated metrics
+  optional AndroidBroadcastsMetric android_broadcasts = 68;
+
   // Android
   // Demo extensions.
   extensions 450 to 499;
diff --git a/python/perfetto/trace_processor/metrics.descriptor b/python/perfetto/trace_processor/metrics.descriptor
index 76897f3..e86eeb2 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 9eb8b04..bf4529b 100644
--- a/src/trace_processor/metrics/sql/android/BUILD.gn
+++ b/src/trace_processor/metrics/sql/android/BUILD.gn
@@ -28,6 +28,7 @@
     "android_blocking_calls_unagg.sql",
     "android_boot.sql",
     "android_boot_unagg.sql",
+    "android_broadcasts.sql",
     "android_camera.sql",
     "android_camera_unagg.sql",
     "android_cpu.sql",
diff --git a/src/trace_processor/metrics/sql/android/android_boot.sql b/src/trace_processor/metrics/sql/android/android_boot.sql
index 5738bff..222c681 100644
--- a/src/trace_processor/metrics/sql/android/android_boot.sql
+++ b/src/trace_processor/metrics/sql/android/android_boot.sql
@@ -14,10 +14,11 @@
 -- limitations under the License.
 --
 
-INCLUDE PERFETTO MODULE android.process_metadata;
 INCLUDE PERFETTO MODULE android.app_process_starts;
+INCLUDE PERFETTO MODULE android.broadcasts;
 INCLUDE PERFETTO MODULE android.garbage_collection;
 INCLUDE PERFETTO MODULE android.oom_adjuster;
+INCLUDE PERFETTO MODULE android.process_metadata;
 
 DROP VIEW IF EXISTS android_oom_adj_intervals_with_detailed_bucket_name;
 CREATE PERFETTO VIEW android_oom_adj_intervals_with_detailed_bucket_name AS
@@ -339,6 +340,77 @@
       FROM android_oom_adj_intervals_with_detailed_bucket_name
       WHERE ts > first_user_unlocked()
       GROUP BY oom_adj_reason
+      )
+    ),
+  'post_boot_broadcast_process_count_by_intent', (
+    SELECT RepeatedField(
+      AndroidBootMetric_BroadcastCountAggregation(
+        'name', intent_action,
+        'count', process_name_counts
+      )
+    )
+    FROM (
+      SELECT
+        intent_action,
+        COUNT(process_name) as process_name_counts
+      FROM _android_broadcasts_minsdk_u
+      WHERE ts > first_user_unlocked()
+      GROUP BY intent_action
+    )
+  ),
+  'post_boot_broadcast_count_by_process', (
+    SELECT RepeatedField(
+      AndroidBootMetric_BroadcastCountAggregation(
+        'name', process_name,
+        'count', broadcast_counts
+      )
+    )
+    FROM (
+      SELECT
+        process_name,
+        COUNT(id) as broadcast_counts
+      FROM _android_broadcasts_minsdk_u
+      WHERE ts > first_user_unlocked()
+      GROUP BY process_name
+    )
+  ),
+  'post_boot_brodcast_duration_agg_by_intent', (
+    SELECT RepeatedField(
+      AndroidBootMetric_BroadcastDurationAggregation(
+        'name', intent_action,
+        'avg_duration', avg_duration,
+        'max_duration', max_duration,
+        'sum_duration', sum_duration
+      )
+    )
+    FROM (
+      SELECT
+        intent_action,
+        AVG(dur) as avg_duration,
+        SUM(dur) as sum_duration,
+        MAX(dur) as max_duration
+      FROM _android_broadcasts_minsdk_u
+      WHERE ts > first_user_unlocked()
+      GROUP BY intent_action
+    )
+  ),  'post_boot_brodcast_duration_agg_by_process', (
+    SELECT RepeatedField(
+      AndroidBootMetric_BroadcastDurationAggregation(
+        'name', process_name,
+        'avg_duration', avg_duration,
+        'max_duration', max_duration,
+        'sum_duration', sum_duration
+      )
+    )
+    FROM (
+      SELECT
+        process_name,
+        AVG(dur) as avg_duration,
+        SUM(dur) as sum_duration,
+        MAX(dur) as max_duration
+      FROM _android_broadcasts_minsdk_u
+      WHERE ts > first_user_unlocked()
+      GROUP BY process_name
     )
   )
 );
diff --git a/src/trace_processor/metrics/sql/android/android_broadcasts.sql b/src/trace_processor/metrics/sql/android/android_broadcasts.sql
new file mode 100644
index 0000000..bba437c
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/android_broadcasts.sql
@@ -0,0 +1,88 @@
+--
+-- 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.
+--
+INCLUDE PERFETTO MODULE android.broadcasts;
+
+DROP VIEW IF EXISTS android_broadcasts_output;
+CREATE PERFETTO VIEW android_broadcasts_output AS
+SELECT AndroidBroadcastsMetric(
+  'process_count_by_intent', (
+    SELECT RepeatedField(
+      AndroidBroadcastsMetric_BroadcastCountAggregation(
+        'name', intent_action,
+        'count', process_name_counts
+      )
+    )
+    FROM (
+      SELECT
+        intent_action,
+        COUNT(process_name) as process_name_counts
+      FROM _android_broadcasts_minsdk_u
+      GROUP BY intent_action
+    )
+  ),
+  'broadcast_count_by_process', (
+    SELECT RepeatedField(
+      AndroidBroadcastsMetric_BroadcastCountAggregation(
+        'name', process_name,
+        'count', broadcast_counts
+      )
+    )
+    FROM (
+      SELECT
+        process_name,
+        COUNT(id) as broadcast_counts
+      FROM _android_broadcasts_minsdk_u
+      GROUP BY process_name
+    )
+  ),
+  'brodcast_duration_agg_by_intent', (
+    SELECT RepeatedField(
+      AndroidBroadcastsMetric_BroadcastDurationAggregation(
+        'name', intent_action,
+        'avg_duration', avg_duration,
+        'max_duration', max_duration,
+        'sum_duration', sum_duration
+      )
+    )
+    FROM (
+      SELECT
+        intent_action,
+        AVG(dur) as avg_duration,
+        SUM(dur) as sum_duration,
+        MAX(dur) as max_duration
+      FROM _android_broadcasts_minsdk_u
+      GROUP BY intent_action
+    )
+  ),  'brodcast_duration_agg_by_process', (
+    SELECT RepeatedField(
+      AndroidBroadcastsMetric_BroadcastDurationAggregation(
+        'name', process_name,
+        'avg_duration', avg_duration,
+        'max_duration', max_duration,
+        'sum_duration', sum_duration
+      )
+    )
+    FROM (
+      SELECT
+        process_name,
+        AVG(dur) as avg_duration,
+        SUM(dur) as sum_duration,
+        MAX(dur) as max_duration
+      FROM _android_broadcasts_minsdk_u
+      GROUP BY process_name
+    )
+  )
+)
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/metrics/android/android_boot.out b/test/trace_processor/diff_tests/metrics/android/android_boot.out
index 50f4757..3d69fdc 100644
--- a/test/trace_processor/diff_tests/metrics/android/android_boot.out
+++ b/test/trace_processor/diff_tests/metrics/android/android_boot.out
@@ -912,4 +912,304 @@
 oom_adj_event_count: 2
 oom_adj_reason: "unbindService"
 }
+post_boot_broadcast_process_count_by_intent {
+name: "android.appwidget.action.APPWIDGET_ENABLED"
+count: 2
 }
+post_boot_broadcast_process_count_by_intent {
+name: "android.appwidget.action.APPWIDGET_UPDATE"
+count: 2
+}
+post_boot_broadcast_process_count_by_intent {
+name: "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS"
+count: 1
+}
+post_boot_broadcast_process_count_by_intent {
+name: "android.intent.action.BATTERY_CHANGED"
+count: 2
+}
+post_boot_broadcast_process_count_by_intent {
+name: "android.intent.action.SIM_STATE_CHANGED"
+count: 38
+}
+post_boot_broadcast_process_count_by_intent {
+name: "android.intent.action.USER_PRESENT"
+count: 10
+}
+post_boot_broadcast_process_count_by_intent {
+name: "android.intent.action.USER_UNLOCKED"
+count: 104
+}
+post_boot_broadcast_process_count_by_intent {
+name: "android.net.conn.CONNECTIVITY_CHANGE"
+count: 1
+}
+post_boot_broadcast_process_count_by_intent {
+name: "android.net.wifi.WIFI_STATE_CHANGED"
+count: 2
+}
+post_boot_broadcast_process_count_by_intent {
+name: "com.google.android.calendar.APPWIDGET_REFRESH_MODEL"
+count: 1
+}
+post_boot_broadcast_count_by_process {
+name: "com.android.phone"
+count: 43
+}
+post_boot_broadcast_count_by_process {
+name: "com.android.settings"
+count: 1
+}
+post_boot_broadcast_count_by_process {
+name: "com.android.systemui"
+count: 5
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.apps.nexuslauncher"
+count: 2
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.apps.scone"
+count: 9
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.apps.wellbeing"
+count: 11
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.apps.work.clouddpc"
+count: 11
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.apps.youtube.music"
+count: 1
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.bluetooth"
+count: 2
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.calendar"
+count: 4
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.connectivitythermalpowermanager"
+count: 4
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.deskclock"
+count: 11
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.devicelockcontroller"
+count: 1
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.dialer"
+count: 14
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.euicc"
+count: 11
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.gms"
+count: 2
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.gms.persistent"
+count: 5
+}
+post_boot_broadcast_count_by_process {
+name: "com.google.android.ims"
+count: 2
+}
+post_boot_broadcast_count_by_process {
+name: "com.shannon.imsservice"
+count: 2
+}
+post_boot_broadcast_count_by_process {
+name: "system"
+count: 22
+}
+post_boot_brodcast_duration_agg_by_intent {
+name: "android.appwidget.action.APPWIDGET_ENABLED"
+avg_duration: 832137248.0
+max_duration: 1604539755
+sum_duration: 1664274496
+}
+post_boot_brodcast_duration_agg_by_intent {
+name: "android.appwidget.action.APPWIDGET_UPDATE"
+avg_duration: 91613911.5
+max_duration: 183227824
+sum_duration: 183227823
+}
+post_boot_brodcast_duration_agg_by_intent {
+name: "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS"
+avg_duration: 105377889.0
+max_duration: 105377889
+sum_duration: 105377889
+}
+post_boot_brodcast_duration_agg_by_intent {
+name: "android.intent.action.BATTERY_CHANGED"
+avg_duration: 165913.5
+max_duration: 222493
+sum_duration: 331827
+}
+post_boot_brodcast_duration_agg_by_intent {
+name: "android.intent.action.SIM_STATE_CHANGED"
+avg_duration: 9982735.5
+max_duration: 195921793
+sum_duration: 379343949
+}
+post_boot_brodcast_duration_agg_by_intent {
+name: "android.intent.action.USER_PRESENT"
+avg_duration: 14583.3
+max_duration: 20304
+sum_duration: 145833
+}
+post_boot_brodcast_duration_agg_by_intent {
+name: "android.intent.action.USER_UNLOCKED"
+avg_duration: 66555.72115384616
+max_duration: 1414754
+sum_duration: 6921795
+}
+post_boot_brodcast_duration_agg_by_intent {
+name: "android.net.conn.CONNECTIVITY_CHANGE"
+avg_duration: 50415.0
+max_duration: 50415
+sum_duration: 50415
+}
+post_boot_brodcast_duration_agg_by_intent {
+name: "android.net.wifi.WIFI_STATE_CHANGED"
+avg_duration: 290506.5
+max_duration: 538533
+sum_duration: 581013
+}
+post_boot_brodcast_duration_agg_by_intent {
+name: "com.google.android.calendar.APPWIDGET_REFRESH_MODEL"
+avg_duration: -1.0
+max_duration: -1
+sum_duration: -1
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.android.phone"
+avg_duration: 3517922.534883721
+max_duration: 146637410
+sum_duration: 151270669
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.android.settings"
+avg_duration: 38697.0
+max_duration: 38697
+sum_duration: 38697
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.android.systemui"
+avg_duration: 95906.4
+max_duration: 189982
+sum_duration: 479532
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.apps.nexuslauncher"
+avg_duration: 33793.0
+max_duration: 50252
+sum_duration: 67586
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.apps.scone"
+avg_duration: 22935.666666666668
+max_duration: 41830
+sum_duration: 206421
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.apps.wellbeing"
+avg_duration: 69202.63636363637
+max_duration: 523967
+sum_duration: 761229
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.apps.work.clouddpc"
+avg_duration: 53555.63636363636
+max_duration: 371867
+sum_duration: 589112
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.apps.youtube.music"
+avg_duration: 50415.0
+max_duration: 50415
+sum_duration: 50415
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.bluetooth"
+avg_duration: 221008.0
+max_duration: 406819
+sum_duration: 442016
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.calendar"
+avg_duration: 87085113.25
+max_duration: 183227824
+sum_duration: 348340453
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.connectivitythermalpowermanager"
+avg_duration: 228210.0
+max_duration: 538533
+sum_duration: 912840
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.deskclock"
+avg_duration: 145975538.0
+max_duration: 1604539755
+sum_duration: 1605730918
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.devicelockcontroller"
+avg_duration: 23682.0
+max_duration: 23682
+sum_duration: 23682
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.dialer"
+avg_duration: 138898.5
+max_duration: 1414754
+sum_duration: 1944579
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.euicc"
+avg_duration: 47296.72727272727
+max_duration: 305339
+sum_duration: 520264
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.gms"
+avg_duration: 113945576.5
+max_duration: 195921793
+sum_duration: 227891153
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.gms.persistent"
+avg_duration: 18220.8
+max_duration: 32430
+sum_duration: 91104
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.google.android.ims"
+avg_duration: 307169.5
+max_duration: 436726
+sum_duration: 614339
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "com.shannon.imsservice"
+avg_duration: 40283.0
+max_duration: 46305
+sum_duration: 80566
+}
+post_boot_brodcast_duration_agg_by_process {
+name: "system"
+avg_duration: 9066.545454545454
+max_duration: 26774
+sum_duration: 199464
+}
+}
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/metrics/android/android_broadcasts.out b/test/trace_processor/diff_tests/metrics/android/android_broadcasts.out
new file mode 100644
index 0000000..2d033ce
--- /dev/null
+++ b/test/trace_processor/diff_tests/metrics/android/android_broadcasts.out
@@ -0,0 +1,302 @@
+android_broadcasts {
+process_count_by_intent {
+name: "android.appwidget.action.APPWIDGET_ENABLED"
+count: 2
+}
+process_count_by_intent {
+name: "android.appwidget.action.APPWIDGET_UPDATE"
+count: 2
+}
+process_count_by_intent {
+name: "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS"
+count: 1
+}
+process_count_by_intent {
+name: "android.intent.action.BATTERY_CHANGED"
+count: 2
+}
+process_count_by_intent {
+name: "android.intent.action.SIM_STATE_CHANGED"
+count: 38
+}
+process_count_by_intent {
+name: "android.intent.action.USER_PRESENT"
+count: 10
+}
+process_count_by_intent {
+name: "android.intent.action.USER_UNLOCKED"
+count: 105
+}
+process_count_by_intent {
+name: "android.net.conn.CONNECTIVITY_CHANGE"
+count: 1
+}
+process_count_by_intent {
+name: "android.net.wifi.WIFI_STATE_CHANGED"
+count: 2
+}
+process_count_by_intent {
+name: "com.google.android.calendar.APPWIDGET_REFRESH_MODEL"
+count: 1
+}
+broadcast_count_by_process {
+name: "com.android.phone"
+count: 43
+}
+broadcast_count_by_process {
+name: "com.android.settings"
+count: 1
+}
+broadcast_count_by_process {
+name: "com.android.systemui"
+count: 5
+}
+broadcast_count_by_process {
+name: "com.google.android.apps.nexuslauncher"
+count: 2
+}
+broadcast_count_by_process {
+name: "com.google.android.apps.scone"
+count: 9
+}
+broadcast_count_by_process {
+name: "com.google.android.apps.wellbeing"
+count: 11
+}
+broadcast_count_by_process {
+name: "com.google.android.apps.work.clouddpc"
+count: 11
+}
+broadcast_count_by_process {
+name: "com.google.android.apps.youtube.music"
+count: 1
+}
+broadcast_count_by_process {
+name: "com.google.android.bluetooth"
+count: 2
+}
+broadcast_count_by_process {
+name: "com.google.android.calendar"
+count: 4
+}
+broadcast_count_by_process {
+name: "com.google.android.connectivitythermalpowermanager"
+count: 4
+}
+broadcast_count_by_process {
+name: "com.google.android.deskclock"
+count: 11
+}
+broadcast_count_by_process {
+name: "com.google.android.devicelockcontroller"
+count: 1
+}
+broadcast_count_by_process {
+name: "com.google.android.dialer"
+count: 14
+}
+broadcast_count_by_process {
+name: "com.google.android.euicc"
+count: 11
+}
+broadcast_count_by_process {
+name: "com.google.android.gms"
+count: 2
+}
+broadcast_count_by_process {
+name: "com.google.android.gms.persistent"
+count: 5
+}
+broadcast_count_by_process {
+name: "com.google.android.ims"
+count: 2
+}
+broadcast_count_by_process {
+name: "com.shannon.imsservice"
+count: 2
+}
+broadcast_count_by_process {
+name: "system"
+count: 23
+}
+brodcast_duration_agg_by_intent {
+name: "android.appwidget.action.APPWIDGET_ENABLED"
+avg_duration: 832137248.0
+max_duration: 1604539755
+sum_duration: 1664274496
+}
+brodcast_duration_agg_by_intent {
+name: "android.appwidget.action.APPWIDGET_UPDATE"
+avg_duration: 91613911.5
+max_duration: 183227824
+sum_duration: 183227823
+}
+brodcast_duration_agg_by_intent {
+name: "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS"
+avg_duration: 105377889.0
+max_duration: 105377889
+sum_duration: 105377889
+}
+brodcast_duration_agg_by_intent {
+name: "android.intent.action.BATTERY_CHANGED"
+avg_duration: 165913.5
+max_duration: 222493
+sum_duration: 331827
+}
+brodcast_duration_agg_by_intent {
+name: "android.intent.action.SIM_STATE_CHANGED"
+avg_duration: 9982735.5
+max_duration: 195921793
+sum_duration: 379343949
+}
+brodcast_duration_agg_by_intent {
+name: "android.intent.action.USER_PRESENT"
+avg_duration: 14583.3
+max_duration: 20304
+sum_duration: 145833
+}
+brodcast_duration_agg_by_intent {
+name: "android.intent.action.USER_UNLOCKED"
+avg_duration: 66119.10476190476
+max_duration: 1414754
+sum_duration: 6942506
+}
+brodcast_duration_agg_by_intent {
+name: "android.net.conn.CONNECTIVITY_CHANGE"
+avg_duration: 50415.0
+max_duration: 50415
+sum_duration: 50415
+}
+brodcast_duration_agg_by_intent {
+name: "android.net.wifi.WIFI_STATE_CHANGED"
+avg_duration: 290506.5
+max_duration: 538533
+sum_duration: 581013
+}
+brodcast_duration_agg_by_intent {
+name: "com.google.android.calendar.APPWIDGET_REFRESH_MODEL"
+avg_duration: -1.0
+max_duration: -1
+sum_duration: -1
+}
+brodcast_duration_agg_by_process {
+name: "com.android.phone"
+avg_duration: 3517922.534883721
+max_duration: 146637410
+sum_duration: 151270669
+}
+brodcast_duration_agg_by_process {
+name: "com.android.settings"
+avg_duration: 38697.0
+max_duration: 38697
+sum_duration: 38697
+}
+brodcast_duration_agg_by_process {
+name: "com.android.systemui"
+avg_duration: 95906.4
+max_duration: 189982
+sum_duration: 479532
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.apps.nexuslauncher"
+avg_duration: 33793.0
+max_duration: 50252
+sum_duration: 67586
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.apps.scone"
+avg_duration: 22935.666666666668
+max_duration: 41830
+sum_duration: 206421
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.apps.wellbeing"
+avg_duration: 69202.63636363637
+max_duration: 523967
+sum_duration: 761229
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.apps.work.clouddpc"
+avg_duration: 53555.63636363636
+max_duration: 371867
+sum_duration: 589112
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.apps.youtube.music"
+avg_duration: 50415.0
+max_duration: 50415
+sum_duration: 50415
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.bluetooth"
+avg_duration: 221008.0
+max_duration: 406819
+sum_duration: 442016
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.calendar"
+avg_duration: 87085113.25
+max_duration: 183227824
+sum_duration: 348340453
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.connectivitythermalpowermanager"
+avg_duration: 228210.0
+max_duration: 538533
+sum_duration: 912840
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.deskclock"
+avg_duration: 145975538.0
+max_duration: 1604539755
+sum_duration: 1605730918
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.devicelockcontroller"
+avg_duration: 23682.0
+max_duration: 23682
+sum_duration: 23682
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.dialer"
+avg_duration: 138898.5
+max_duration: 1414754
+sum_duration: 1944579
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.euicc"
+avg_duration: 47296.72727272727
+max_duration: 305339
+sum_duration: 520264
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.gms"
+avg_duration: 113945576.5
+max_duration: 195921793
+sum_duration: 227891153
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.gms.persistent"
+avg_duration: 18220.8
+max_duration: 32430
+sum_duration: 91104
+}
+brodcast_duration_agg_by_process {
+name: "com.google.android.ims"
+avg_duration: 307169.5
+max_duration: 436726
+sum_duration: 614339
+}
+brodcast_duration_agg_by_process {
+name: "com.shannon.imsservice"
+avg_duration: 40283.0
+max_duration: 46305
+sum_duration: 80566
+}
+brodcast_duration_agg_by_process {
+name: "system"
+avg_duration: 9572.826086956522
+max_duration: 26774
+sum_duration: 220175
+}
+}
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/metrics/android/tests.py b/test/trace_processor/diff_tests/metrics/android/tests.py
index 42b718a..f2c7eb7 100644
--- a/test/trace_processor/diff_tests/metrics/android/tests.py
+++ b/test/trace_processor/diff_tests/metrics/android/tests.py
@@ -356,3 +356,9 @@
         trace=DataPath('android_postboot_unlock.pftrace'),
         query=Metric("android_oom_adjuster"),
         out=Path('android_oom_adjuster.out'))
+
+  def test_android_broadcasts(self):
+    return DiffTestBlueprint(
+        trace=DataPath('android_postboot_unlock.pftrace'),
+        query=Metric("android_broadcasts"),
+        out=Path('android_broadcasts.out'))