Add metric for App Process start and aggregated process start

The aggregated process start metric is added to android_boot

Test: tools/diff_test_trace_processor.py <path to trace processor binary> --name-filter=".*_app_process_starts"
Bug: 325046704
Change-Id: I256a2c2e1a2034a37709baecc8aac8fc4fcc20d9
diff --git a/Android.bp b/Android.bp
index f4559d8..bb57f3b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -5121,10 +5121,12 @@
         "protos/perfetto/metrics/android/android_blocking_call.proto",
         "protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.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",
         "protos/perfetto/metrics/android/android_sysui_notifications_blocking_calls_metric.proto",
         "protos/perfetto/metrics/android/android_trusty_workqueues.proto",
         "protos/perfetto/metrics/android/anr_metric.proto",
+        "protos/perfetto/metrics/android/app_process_starts_metric.proto",
         "protos/perfetto/metrics/android/batt_metric.proto",
         "protos/perfetto/metrics/android/binder_metric.proto",
         "protos/perfetto/metrics/android/camera_metric.proto",
@@ -5206,10 +5208,12 @@
         "protos/perfetto/metrics/android/android_blocking_call.proto",
         "protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.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",
         "protos/perfetto/metrics/android/android_sysui_notifications_blocking_calls_metric.proto",
         "protos/perfetto/metrics/android/android_trusty_workqueues.proto",
         "protos/perfetto/metrics/android/anr_metric.proto",
+        "protos/perfetto/metrics/android/app_process_starts_metric.proto",
         "protos/perfetto/metrics/android/batt_metric.proto",
         "protos/perfetto/metrics/android/binder_metric.proto",
         "protos/perfetto/metrics/android/camera_metric.proto",
@@ -5274,10 +5278,12 @@
         "protos/perfetto/metrics/android/android_blocking_call.proto",
         "protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.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",
         "protos/perfetto/metrics/android/android_sysui_notifications_blocking_calls_metric.proto",
         "protos/perfetto/metrics/android/android_trusty_workqueues.proto",
         "protos/perfetto/metrics/android/anr_metric.proto",
+        "protos/perfetto/metrics/android/app_process_starts_metric.proto",
         "protos/perfetto/metrics/android/batt_metric.proto",
         "protos/perfetto/metrics/android/binder_metric.proto",
         "protos/perfetto/metrics/android/camera_metric.proto",
@@ -11607,6 +11613,7 @@
         "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_boot.sql",
+        "src/trace_processor/metrics/sql/android/android_boot_unagg.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",
@@ -11699,6 +11706,7 @@
         "src/trace_processor/metrics/sql/android/process_unagg_mem_view.sql",
         "src/trace_processor/metrics/sql/android/profiler_smaps.sql",
         "src/trace_processor/metrics/sql/android/span_view_stats.sql",
+        "src/trace_processor/metrics/sql/android/startup/android_app_process_starts.sql",
         "src/trace_processor/metrics/sql/android/startup/gc_slices.sql",
         "src/trace_processor/metrics/sql/android/startup/hsc.sql",
         "src/trace_processor/metrics/sql/android/startup/launches.sql",
diff --git a/BUILD b/BUILD
index 09790fd..6e8cf7e 100644
--- a/BUILD
+++ b/BUILD
@@ -1930,6 +1930,7 @@
         "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_boot.sql",
+        "src/trace_processor/metrics/sql/android/android_boot_unagg.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",
@@ -2022,6 +2023,7 @@
         "src/trace_processor/metrics/sql/android/process_unagg_mem_view.sql",
         "src/trace_processor/metrics/sql/android/profiler_smaps.sql",
         "src/trace_processor/metrics/sql/android/span_view_stats.sql",
+        "src/trace_processor/metrics/sql/android/startup/android_app_process_starts.sql",
         "src/trace_processor/metrics/sql/android/startup/gc_slices.sql",
         "src/trace_processor/metrics/sql/android/startup/hsc.sql",
         "src/trace_processor/metrics/sql/android/startup/launches.sql",
@@ -4278,10 +4280,12 @@
         "protos/perfetto/metrics/android/android_blocking_call.proto",
         "protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.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",
         "protos/perfetto/metrics/android/android_sysui_notifications_blocking_calls_metric.proto",
         "protos/perfetto/metrics/android/android_trusty_workqueues.proto",
         "protos/perfetto/metrics/android/anr_metric.proto",
+        "protos/perfetto/metrics/android/app_process_starts_metric.proto",
         "protos/perfetto/metrics/android/batt_metric.proto",
         "protos/perfetto/metrics/android/binder_metric.proto",
         "protos/perfetto/metrics/android/camera_metric.proto",
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index 12a4862..9caeaef 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -24,10 +24,12 @@
     "android_blocking_call.proto",
     "android_blocking_calls_cuj_metric.proto",
     "android_boot.proto",
+    "android_boot_unagg.proto",
     "android_frame_timeline_metric.proto",
     "android_sysui_notifications_blocking_calls_metric.proto",
     "android_trusty_workqueues.proto",
     "anr_metric.proto",
+    "app_process_starts_metric.proto",
     "batt_metric.proto",
     "binder_metric.proto",
     "camera_metric.proto",
diff --git a/protos/perfetto/metrics/android/android_boot.proto b/protos/perfetto/metrics/android/android_boot.proto
index 53de221..89a56d2 100644
--- a/protos/perfetto/metrics/android/android_boot.proto
+++ b/protos/perfetto/metrics/android/android_boot.proto
@@ -18,7 +18,8 @@
 
 package perfetto.protos;
 
-// This metric computes how much time processes spend in UNINTERRUPTIBLE_SLEEP state
+// This metric computes how much time processes spend in UNINTERRUPTIBLE_SLEEP
+// state
 message ProcessStateDurations {
   optional int64 total_dur = 2;
   optional int64 uninterruptible_sleep_dur = 3;
@@ -35,4 +36,12 @@
     optional int64 cold_start_dur = 1;
   }
   optional LauncherBreakdown launcher_breakdown = 5;
+
+  message ProcessStartAggregation {
+    optional int64 total_start_sum = 1;
+    optional int64 num_of_processes = 2;
+    optional double average_start_time = 3;
+  }
+  optional ProcessStartAggregation full_trace_process_start_aggregation = 6;
+  optional ProcessStartAggregation post_boot_process_start_aggregation = 7;
 }
diff --git a/protos/perfetto/metrics/android/android_boot_unagg.proto b/protos/perfetto/metrics/android/android_boot_unagg.proto
new file mode 100644
index 0000000..12bf12b
--- /dev/null
+++ b/protos/perfetto/metrics/android/android_boot_unagg.proto
@@ -0,0 +1,25 @@
+/*
+ * 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/app_process_starts_metric.proto";
+
+message AndroidBootUnagg {
+  optional AndroidAppProcessStartsMetric android_app_process_start_metric = 1;
+}
diff --git a/protos/perfetto/metrics/android/app_process_starts_metric.proto b/protos/perfetto/metrics/android/app_process_starts_metric.proto
new file mode 100644
index 0000000..dafce94
--- /dev/null
+++ b/protos/perfetto/metrics/android/app_process_starts_metric.proto
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+// Looks at all apps started after boot complete broadcast.
+message AndroidAppProcessStartsMetric {
+  // Next id : 4
+  message ProcessStart {
+    optional string process_name = 1;
+    optional string intent = 2;
+    optional string reason = 3;
+    optional int64 proc_start_dur = 4;
+    optional int64 bind_app_dur = 5;
+    optional int64 intent_dur = 6;
+    optional int64 total_dur = 7;
+  }
+  // Provides java process startup information for
+  // all processes starting after Boot completed broadcast in a trace.
+  repeated ProcessStart all_apps = 1;
+  // Provides java process startup information for all
+  // processes started from a broadcast after Boot Complete broadcasts.
+  repeated ProcessStart started_by_broadcast = 2;
+  // Provides java process startup information for all
+  // processes started from a service after Boot Complete broadcasts.
+  repeated ProcessStart started_by_service = 3;
+}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index 5587efa..8bd4d38 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -20,6 +20,7 @@
 
 import "protos/perfetto/metrics/android/ad_services_metric.proto";
 import "protos/perfetto/metrics/android/android_boot.proto";
+import "protos/perfetto/metrics/android/android_boot_unagg.proto";
 import "protos/perfetto/metrics/android/sysui_notif_shade_list_builder_metric.proto";
 import "protos/perfetto/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.proto";
 import "protos/perfetto/metrics/android/android_frame_timeline_metric.proto";
@@ -67,6 +68,7 @@
 import "protos/perfetto/metrics/android/binder_metric.proto";
 import "protos/perfetto/metrics/android/monitor_contention_metric.proto";
 import "protos/perfetto/metrics/android/monitor_contention_agg_metric.proto";
+import "protos/perfetto/metrics/android/app_process_starts_metric.proto";
 
 // Trace processor metadata
 message TraceMetadata {
@@ -113,7 +115,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 61
+// Next id: 63
 message TraceMetrics {
   reserved 4, 10, 13, 14, 16, 19;
 
@@ -277,6 +279,13 @@
   optional SysuiNotifShadeListBuilderMetric sysui_notif_shade_list_builder_metric = 59;
 
   optional SysuiUpdateNotifOnUiModeChangedMetric sysui_update_notif_on_ui_mode_changed_metric = 60;
+
+  // Metrics for Process starts.
+  optional AndroidAppProcessStartsMetric android_app_process_starts = 61;
+
+  // Android boot unaggregated metrics.
+  optional AndroidBootUnagg android_boot_unagg = 62;
+
   // 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 32640f6..c96a4a2 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -147,7 +147,8 @@
 
 // Begin of protos/perfetto/metrics/android/android_boot.proto
 
-// This metric computes how much time processes spend in UNINTERRUPTIBLE_SLEEP state
+// This metric computes how much time processes spend in UNINTERRUPTIBLE_SLEEP
+// state
 message ProcessStateDurations {
   optional int64 total_dur = 2;
   optional int64 uninterruptible_sleep_dur = 3;
@@ -164,10 +165,53 @@
     optional int64 cold_start_dur = 1;
   }
   optional LauncherBreakdown launcher_breakdown = 5;
+
+  message ProcessStartAggregation {
+    optional int64 total_start_sum = 1;
+    optional int64 num_of_processes = 2;
+    optional double average_start_time = 3;
+  }
+  optional ProcessStartAggregation full_trace_process_start_aggregation = 6;
+  optional ProcessStartAggregation post_boot_process_start_aggregation = 7;
 }
 
 // End of protos/perfetto/metrics/android/android_boot.proto
 
+// Begin of protos/perfetto/metrics/android/app_process_starts_metric.proto
+
+// Looks at all apps started after boot complete broadcast.
+message AndroidAppProcessStartsMetric {
+  // Next id : 4
+  message ProcessStart {
+    optional string process_name = 1;
+    optional string intent = 2;
+    optional string reason = 3;
+    optional int64 proc_start_dur = 4;
+    optional int64 bind_app_dur = 5;
+    optional int64 intent_dur = 6;
+    optional int64 total_dur = 7;
+  }
+  // Provides java process startup information for
+  // all processes starting after Boot completed broadcast in a trace.
+  repeated ProcessStart all_apps = 1;
+  // Provides java process startup information for all
+  // processes started from a broadcast after Boot Complete broadcasts.
+  repeated ProcessStart started_by_broadcast = 2;
+  // Provides java process startup information for all
+  // processes started from a service after Boot Complete broadcasts.
+  repeated ProcessStart started_by_service = 3;
+}
+
+// End of protos/perfetto/metrics/android/app_process_starts_metric.proto
+
+// Begin of protos/perfetto/metrics/android/android_boot_unagg.proto
+
+message AndroidBootUnagg {
+  optional AndroidAppProcessStartsMetric android_app_process_start_metric = 1;
+}
+
+// End of protos/perfetto/metrics/android/android_boot_unagg.proto
+
 // Begin of protos/perfetto/metrics/android/android_frame_timeline_metric.proto
 
 message AndroidFrameTimelineMetric {
@@ -2411,7 +2455,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 61
+// Next id: 63
 message TraceMetrics {
   reserved 4, 10, 13, 14, 16, 19;
 
@@ -2575,6 +2619,13 @@
   optional SysuiNotifShadeListBuilderMetric sysui_notif_shade_list_builder_metric = 59;
 
   optional SysuiUpdateNotifOnUiModeChangedMetric sysui_update_notif_on_ui_mode_changed_metric = 60;
+
+  // Metrics for Process starts.
+  optional AndroidAppProcessStartsMetric android_app_process_starts = 61;
+
+  // Android boot unaggregated metrics.
+  optional AndroidBootUnagg android_boot_unagg = 62;
+
   // Demo extensions.
   extensions 450 to 499;
 
diff --git a/python/perfetto/trace_processor/metrics.descriptor b/python/perfetto/trace_processor/metrics.descriptor
index f77d217..c4832d5 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 8aeaee6..c92ba32 100644
--- a/src/trace_processor/metrics/sql/android/BUILD.gn
+++ b/src/trace_processor/metrics/sql/android/BUILD.gn
@@ -25,6 +25,7 @@
     "android_binder.sql",
     "android_blocking_calls_cuj_metric.sql",
     "android_boot.sql",
+    "android_boot_unagg.sql",
     "android_camera.sql",
     "android_camera_unagg.sql",
     "android_cpu.sql",
@@ -118,6 +119,7 @@
     "process_unagg_mem_view.sql",
     "profiler_smaps.sql",
     "span_view_stats.sql",
+    "startup/android_app_process_starts.sql",
     "startup/gc_slices.sql",
     "startup/hsc.sql",
     "startup/launches.sql",
diff --git a/src/trace_processor/metrics/sql/android/android_boot.sql b/src/trace_processor/metrics/sql/android/android_boot.sql
index d0df436..a81f28a 100644
--- a/src/trace_processor/metrics/sql/android/android_boot.sql
+++ b/src/trace_processor/metrics/sql/android/android_boot.sql
@@ -15,6 +15,7 @@
 --
 
 INCLUDE PERFETTO MODULE android.process_metadata;
+INCLUDE PERFETTO MODULE android.app_process_starts;
 
 CREATE OR REPLACE PERFETTO FUNCTION get_durations(process_name STRING)
 RETURNS TABLE(uint_sleep_dur LONG, total_dur LONG) AS
@@ -51,5 +52,31 @@
     'launcher_breakdown', (
         SELECT NULL_IF_EMPTY(AndroidBootMetric_LauncherBreakdown(
             'cold_start_dur', dur))
-        FROM slice where name="LauncherColdStartup")
+        FROM slice where name="LauncherColdStartup"),
+    'full_trace_process_start_aggregation', (
+        SELECT NULL_IF_EMPTY(AndroidBootMetric_ProcessStartAggregation(
+            'total_start_sum', (SELECT SUM(total_dur) FROM android_app_process_starts),
+            'num_of_processes', (SELECT COUNT(process_name) FROM android_app_process_starts GROUP BY process_name),
+            'average_start_time', (SELECT AVG(total_dur) FROM android_app_process_starts)))
+            FROM android_app_process_starts),
+    'post_boot_process_start_aggregation', (
+        SELECT NULL_IF_EMPTY(AndroidBootMetric_ProcessStartAggregation(
+            'total_start_sum', (SELECT SUM(total_dur) FROM android_app_process_starts
+              WHERE proc_start_ts > (SELECT COALESCE(MIN(ts), 0)
+                FROM thread_slice WHERE name GLOB "*android.intent.action.USER_UNLOCKED*"
+                ORDER BY ts ASC LIMIT 1 )
+            ),
+            'num_of_processes', (SELECT COUNT(process_name) FROM android_app_process_starts
+              WHERE proc_start_ts > (SELECT COALESCE(MIN(ts), 0) FROM thread_slice
+                WHERE name GLOB "*android.intent.action.USER_UNLOCKED*" ORDER BY ts
+                ASC LIMIT 1 )
+              GROUP BY process_name
+            ),
+            'average_start_time', (SELECT AVG(total_dur) FROM android_app_process_starts
+              WHERE proc_start_ts > (SELECT COALESCE(MIN(ts), 0) FROM thread_slice
+                WHERE name GLOB "*android.intent.action.USER_UNLOCKED*" ORDER BY ts
+                ASC LIMIT 1 )
+            )
+        ))
+    )
 );
diff --git a/src/trace_processor/metrics/sql/android/android_boot_unagg.sql b/src/trace_processor/metrics/sql/android/android_boot_unagg.sql
new file mode 100644
index 0000000..2444b22
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/android_boot_unagg.sql
@@ -0,0 +1,76 @@
+--
+-- 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.app_process_starts;
+
+DROP VIEW IF EXISTS android_boot_unagg_output;
+CREATE PERFETTO VIEW android_boot_unagg_output AS
+SELECT AndroidBootUnagg(
+  'android_app_process_start_metric', (
+    SELECT AndroidAppProcessStartsMetric(
+        'all_apps', (
+            SELECT RepeatedField(
+                AndroidAppProcessStartsMetric_ProcessStart(
+                    'process_name', process_name,
+                    'intent', intent,
+                    'reason', reason,
+                    'proc_start_dur', proc_start_dur,
+                    'bind_app_dur', bind_app_dur,
+                    'intent_dur', intent_dur,
+                    'total_dur', total_dur
+                )
+            )
+            FROM android_app_process_starts WHERE proc_start_ts > (SELECT COALESCE(MIN(ts), 0)
+            FROM thread_slice WHERE name GLOB "*android.intent.action.USER_UNLOCKED*" ORDER BY ts
+            ASC LIMIT 1)
+        ),
+        'started_by_broadcast', (
+            SELECT RepeatedField(
+                AndroidAppProcessStartsMetric_ProcessStart(
+                    'process_name', process_name,
+                    'intent', intent,
+                    'reason', reason,
+                    'proc_start_dur', proc_start_dur,
+                    'bind_app_dur', bind_app_dur,
+                    'intent_dur', intent_dur,
+                    'total_dur', total_dur
+                )
+            )
+            FROM android_app_process_starts WHERE proc_start_ts > (SELECT COALESCE(MIN(ts), 0)
+            FROM thread_slice WHERE name GLOB "*android.intent.action.USER_UNLOCKED*" ORDER BY ts
+            ASC LIMIT 1)
+            AND reason = "broadcast"
+        ),
+        'started_by_service', (
+            SELECT RepeatedField(
+                AndroidAppProcessStartsMetric_ProcessStart(
+                    'process_name', process_name,
+                    'intent', intent,
+                    'reason', reason,
+                    'proc_start_dur', proc_start_dur,
+                    'bind_app_dur', bind_app_dur,
+                    'intent_dur', intent_dur,
+                    'total_dur', total_dur
+                )
+            )
+            FROM android_app_process_starts WHERE proc_start_ts > (SELECT COALESCE(MIN(ts), 0)
+            FROM thread_slice WHERE name GLOB "*android.intent.action.USER_UNLOCKED*" ORDER BY ts
+            ASC LIMIT 1 )
+            AND reason = "service"
+        )
+    )
+  )
+);
diff --git a/src/trace_processor/metrics/sql/android/startup/android_app_process_starts.sql b/src/trace_processor/metrics/sql/android/startup/android_app_process_starts.sql
new file mode 100644
index 0000000..1364c35
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/startup/android_app_process_starts.sql
@@ -0,0 +1,64 @@
+--
+-- 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.app_process_starts;
+
+DROP VIEW IF EXISTS android_app_process_starts_output;
+CREATE PERFETTO VIEW android_app_process_starts_output AS
+SELECT AndroidAppProcessStartsMetric(
+  'all_apps', (
+    SELECT RepeatedField(
+        AndroidAppProcessStartsMetric_ProcessStart(
+            'process_name', process_name,
+            'intent', intent,
+            'reason', reason,
+            'proc_start_dur', proc_start_dur,
+            'bind_app_dur', bind_app_dur,
+            'intent_dur', intent_dur,
+            'total_dur', total_dur
+        )
+    )
+    FROM android_app_process_starts
+  ),
+  'started_by_broadcast', (
+    SELECT RepeatedField(
+        AndroidAppProcessStartsMetric_ProcessStart(
+            'process_name', process_name,
+            'intent', intent,
+            'reason', reason,
+            'proc_start_dur', proc_start_dur,
+            'bind_app_dur', bind_app_dur,
+            'intent_dur', intent_dur,
+            'total_dur', total_dur
+        )
+    )
+    FROM android_app_process_starts where reason = "broadcast"
+  ),
+  'started_by_service', (
+    SELECT RepeatedField(
+        AndroidAppProcessStartsMetric_ProcessStart(
+            'process_name', process_name,
+            'intent', intent,
+            'reason', reason,
+            'proc_start_dur', proc_start_dur,
+            'bind_app_dur', bind_app_dur,
+            'intent_dur', intent_dur,
+            'total_dur', total_dur
+        )
+    )
+    FROM android_app_process_starts where reason = "service"
+  )
+);
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/app_process_starts.sql b/src/trace_processor/perfetto_sql/stdlib/android/app_process_starts.sql
index 2e68b5f..bff8d0e 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/app_process_starts.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/app_process_starts.sql
@@ -103,10 +103,9 @@
   ON proc_start.process_name = cold_start.process_name AND cold_start.ts > proc_start.ts
 GROUP BY cold_start.upid;
 
--- TODO(b/323052521): Refactor this table name to android_startups.
 -- All app cold starts with information about their cold start reason:
 -- broadcast, service, activity or provider.
-CREATE PERFETTO TABLE _android_app_process_starts(
+CREATE PERFETTO TABLE android_app_process_starts(
   -- Slice id of the bindApplication slice in the app. Uniquely identifies a process start.
   start_id INT,
   -- Slice id of intent received in the app.
diff --git a/test/data/android_postboot_unlock.pftrace.sha256 b/test/data/android_postboot_unlock.pftrace.sha256
new file mode 100644
index 0000000..7a0e9dc
--- /dev/null
+++ b/test/data/android_postboot_unlock.pftrace.sha256
@@ -0,0 +1 @@
+445cd34686c12847640c26dee271069383d2e25c8a8c0e36f0b1ed8d94514488
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/metrics/android/android_app_process_starts.out b/test/trace_processor/diff_tests/metrics/android/android_app_process_starts.out
new file mode 100644
index 0000000..da3583d
--- /dev/null
+++ b/test/trace_processor/diff_tests/metrics/android/android_app_process_starts.out
@@ -0,0 +1,315 @@
+android_app_process_starts {
+  all_apps {
+    process_name: "com.google.android.providers.media.module"
+    intent: "com.android.providers.media.fuse.ExternalStorageServiceImpl"
+    reason: "service"
+    proc_start_dur: 11229493
+    bind_app_dur: 517852702
+    intent_dur: 10584229
+    total_dur: 582811036
+  }
+  all_apps {
+    process_name: "com.google.android.googlequicksearchbox:interactor"
+    intent: "com.google.android.voiceinteraction.GsaVoiceInteractionService"
+    reason: "service"
+    proc_start_dur: 9032552
+    bind_app_dur: 977818441
+    intent_dur: 201066650
+    total_dur: 1224463420
+  }
+  all_apps {
+    process_name: "com.google.android.apps.messaging:rcs"
+    intent: "com.google.android.ims.binding.SystemBindingService"
+    reason: "service"
+    proc_start_dur: 16897502
+    bind_app_dur: 822825195
+    intent_dur: 53585938
+    total_dur: 935336101
+  }
+  all_apps {
+    process_name: "com.google.android.connectivitythermalpowermanager"
+    intent: "com.google.android.connectivitythermalpowermanager.ConnectivityThermalPowerManagerService"
+    reason: "service"
+    proc_start_dur: 32508748
+    bind_app_dur: 82229981
+    intent_dur: 391083293
+    total_dur: 552657145
+  }
+  all_apps {
+    process_name: "com.google.android.calendar"
+    intent: " android.appwidget.action.APPWIDGET_ENABLED"
+    reason: "broadcast"
+    proc_start_dur: 12347046
+    bind_app_dur: 793497640
+    intent_dur: 51051310
+    total_dur: 1012425578
+  }
+  all_apps {
+    process_name: "com.google.android.googlequicksearchbox:search"
+    intent: "com.google.android.apps.search.podcasts.browser.PodcastBrowserService"
+    reason: "service"
+    proc_start_dur: 52551066
+    bind_app_dur: 673431316
+    intent_dur: 12822713
+    total_dur: 905843466
+  }
+  all_apps {
+    process_name: "com.google.android.apps.dreamliner"
+    intent: "com.google.android.apps.dreamliner.notification.DreamlinerNotificationService"
+    reason: "service"
+    proc_start_dur: 13374675
+    bind_app_dur: 205802776
+    intent_dur: 143158203
+    total_dur: 439490479
+  }
+  all_apps {
+    process_name: "com.google.android.as.oss"
+    intent: "com.google.android.gms.learning.internal.training.InAppJobService"
+    reason: "service"
+    proc_start_dur: 87438151
+    bind_app_dur: 208729451
+    intent_dur: 459920
+    total_dur: 479233521
+  }
+  all_apps {
+    process_name: "com.google.ar.core"
+    intent: "com.google.ar.core.services.profiles.ProfileDownloadJobService"
+    reason: "service"
+    proc_start_dur: 22607056
+    bind_app_dur: 651136923
+    intent_dur: 18350912
+    total_dur: 803594402
+  }
+  all_apps {
+    process_name: "com.android.keychain"
+    intent: "com.android.keychain.KeyChainService"
+    reason: "service"
+    proc_start_dur: 143594686
+    bind_app_dur: 124117351
+    intent_dur: -1
+    total_dur: 583162190
+  }
+  all_apps {
+    process_name: "com.google.android.as"
+    reason: "provider"
+    proc_start_dur: 7981446
+    bind_app_dur: -1
+    total_dur: 60545572
+  }
+  all_apps {
+    process_name: "com.android.nfc"
+    reason: "provider"
+    proc_start_dur: 12938395
+    bind_app_dur: 706180624
+    total_dur: 785690837
+  }
+  all_apps {
+    process_name: "com.google.SSRestartDetector"
+    reason: "provider"
+    proc_start_dur: 12119792
+    bind_app_dur: 133668783
+    total_dur: 195917888
+  }
+  all_apps {
+    process_name: "com.android.pixellogger"
+    reason: "provider"
+    proc_start_dur: 19349406
+    bind_app_dur: 182837565
+    total_dur: 227891032
+  }
+  all_apps {
+    process_name: "com.google.android.apps.youtube.music"
+    reason: "provider"
+    proc_start_dur: 34101441
+    bind_app_dur: -1
+    total_dur: 135004394
+  }
+  all_apps {
+    process_name: "com.google.android.youtube"
+    reason: "provider"
+    proc_start_dur: 73083374
+    bind_app_dur: -1
+    total_dur: 121121785
+  }
+  all_apps {
+    process_name: "com.amazon.mp3"
+    reason: "provider"
+    proc_start_dur: 127611247
+    bind_app_dur: -1
+    total_dur: 173187580
+  }
+  all_apps {
+    process_name: "com.apple.android.music"
+    reason: "provider"
+    proc_start_dur: 29364055
+    bind_app_dur: -1
+    total_dur: 91992879
+  }
+  all_apps {
+    process_name: "com.blinkslabs.blinkist.android"
+    reason: "provider"
+    proc_start_dur: 57628744
+    bind_app_dur: -1
+    total_dur: 78990559
+  }
+  all_apps {
+    process_name: "com.google.android.apps.books"
+    reason: "provider"
+    proc_start_dur: 142572509
+    bind_app_dur: -1
+    total_dur: 193448851
+  }
+  all_apps {
+    process_name: "com.overdrive.mobile.android.libby"
+    reason: "provider"
+    proc_start_dur: 20993978
+    bind_app_dur: -1
+    total_dur: 130225300
+  }
+  all_apps {
+    process_name: "org.thoughtcrime.securesms"
+    reason: "provider"
+    proc_start_dur: 299099894
+    bind_app_dur: -1
+    total_dur: 299780394
+  }
+  all_apps {
+    process_name: "com.patreon.android"
+    reason: "provider"
+    proc_start_dur: 30774414
+    bind_app_dur: -1
+    total_dur: 86755370
+  }
+  all_apps {
+    process_name: "com.spotify.music"
+    reason: "provider"
+    proc_start_dur: 24248860
+    bind_app_dur: -1
+    total_dur: 97743773
+  }
+  all_apps {
+    process_name: "com.google.android.keep"
+    reason: "provider"
+    proc_start_dur: 24017578
+    bind_app_dur: -1
+    total_dur: 67608316
+  }
+  all_apps {
+    process_name: "org.videolan.vlc"
+    reason: "provider"
+    proc_start_dur: 59140991
+    bind_app_dur: -1
+    total_dur: 108707193
+  }
+  all_apps {
+    process_name: "com.android.printspooler"
+    reason: "provider"
+    proc_start_dur: 20540893
+    bind_app_dur: -1
+    total_dur: 66699706
+  }
+  all_apps {
+    process_name: "com.android.providers.calendar"
+    reason: "provider"
+    proc_start_dur: 67028117
+    bind_app_dur: -1
+    total_dur: 101619669
+  }
+  all_apps {
+    process_name: "com.google.android.apps.wallpaper"
+    reason: "provider"
+    proc_start_dur: 50665365
+    bind_app_dur: -1
+    total_dur: 136349243
+  }
+  started_by_broadcast {
+    process_name: "com.google.android.calendar"
+    intent: " android.appwidget.action.APPWIDGET_ENABLED"
+    reason: "broadcast"
+    proc_start_dur: 12347046
+    bind_app_dur: 793497640
+    intent_dur: 51051310
+    total_dur: 1012425578
+  }
+  started_by_service {
+    process_name: "com.google.android.providers.media.module"
+    intent: "com.android.providers.media.fuse.ExternalStorageServiceImpl"
+    reason: "service"
+    proc_start_dur: 11229493
+    bind_app_dur: 517852702
+    intent_dur: 10584229
+    total_dur: 582811036
+  }
+  started_by_service {
+    process_name: "com.google.android.googlequicksearchbox:interactor"
+    intent: "com.google.android.voiceinteraction.GsaVoiceInteractionService"
+    reason: "service"
+    proc_start_dur: 9032552
+    bind_app_dur: 977818441
+    intent_dur: 201066650
+    total_dur: 1224463420
+  }
+  started_by_service {
+    process_name: "com.google.android.apps.messaging:rcs"
+    intent: "com.google.android.ims.binding.SystemBindingService"
+    reason: "service"
+    proc_start_dur: 16897502
+    bind_app_dur: 822825195
+    intent_dur: 53585938
+    total_dur: 935336101
+  }
+  started_by_service {
+    process_name: "com.google.android.connectivitythermalpowermanager"
+    intent: "com.google.android.connectivitythermalpowermanager.ConnectivityThermalPowerManagerService"
+    reason: "service"
+    proc_start_dur: 32508748
+    bind_app_dur: 82229981
+    intent_dur: 391083293
+    total_dur: 552657145
+  }
+  started_by_service {
+    process_name: "com.google.android.googlequicksearchbox:search"
+    intent: "com.google.android.apps.search.podcasts.browser.PodcastBrowserService"
+    reason: "service"
+    proc_start_dur: 52551066
+    bind_app_dur: 673431316
+    intent_dur: 12822713
+    total_dur: 905843466
+  }
+  started_by_service {
+    process_name: "com.google.android.apps.dreamliner"
+    intent: "com.google.android.apps.dreamliner.notification.DreamlinerNotificationService"
+    reason: "service"
+    proc_start_dur: 13374675
+    bind_app_dur: 205802776
+    intent_dur: 143158203
+    total_dur: 439490479
+  }
+  started_by_service {
+    process_name: "com.google.android.as.oss"
+    intent: "com.google.android.gms.learning.internal.training.InAppJobService"
+    reason: "service"
+    proc_start_dur: 87438151
+    bind_app_dur: 208729451
+    intent_dur: 459920
+    total_dur: 479233521
+  }
+  started_by_service {
+    process_name: "com.google.ar.core"
+    intent: "com.google.ar.core.services.profiles.ProfileDownloadJobService"
+    reason: "service"
+    proc_start_dur: 22607056
+    bind_app_dur: 651136923
+    intent_dur: 18350912
+    total_dur: 803594402
+  }
+  started_by_service {
+    process_name: "com.android.keychain"
+    intent: "com.android.keychain.KeyChainService"
+    reason: "service"
+    proc_start_dur: 143594686
+    bind_app_dur: 124117351
+    intent_dur: -1
+    total_dur: 583162190
+  }
+}
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/metrics/android/android_boot_unagg.out b/test/trace_processor/diff_tests/metrics/android/android_boot_unagg.out
new file mode 100644
index 0000000..568da0b
--- /dev/null
+++ b/test/trace_processor/diff_tests/metrics/android/android_boot_unagg.out
@@ -0,0 +1,217 @@
+android_boot_unagg {
+  android_app_process_start_metric {
+    all_apps {
+      process_name: "com.google.android.calendar"
+      intent: " android.appwidget.action.APPWIDGET_ENABLED"
+      reason: "broadcast"
+      proc_start_dur: 12347046
+      bind_app_dur: 793497640
+      intent_dur: 51051310
+      total_dur: 1012425578
+    }
+    all_apps {
+      process_name: "com.google.android.googlequicksearchbox:search"
+      intent: "com.google.android.apps.search.podcasts.browser.PodcastBrowserService"
+      reason: "service"
+      proc_start_dur: 52551066
+      bind_app_dur: 673431316
+      intent_dur: 12822713
+      total_dur: 905843466
+    }
+    all_apps {
+      process_name: "com.google.android.apps.dreamliner"
+      intent: "com.google.android.apps.dreamliner.notification.DreamlinerNotificationService"
+      reason: "service"
+      proc_start_dur: 13374675
+      bind_app_dur: 205802776
+      intent_dur: 143158203
+      total_dur: 439490479
+    }
+    all_apps {
+      process_name: "com.google.android.as.oss"
+      intent: "com.google.android.gms.learning.internal.training.InAppJobService"
+      reason: "service"
+      proc_start_dur: 87438151
+      bind_app_dur: 208729451
+      intent_dur: 459920
+      total_dur: 479233521
+    }
+    all_apps {
+      process_name: "com.google.ar.core"
+      intent: "com.google.ar.core.services.profiles.ProfileDownloadJobService"
+      reason: "service"
+      proc_start_dur: 22607056
+      bind_app_dur: 651136923
+      intent_dur: 18350912
+      total_dur: 803594402
+    }
+    all_apps {
+      process_name: "com.android.keychain"
+      intent: "com.android.keychain.KeyChainService"
+      reason: "service"
+      proc_start_dur: 143594686
+      bind_app_dur: 124117351
+      intent_dur: -1
+      total_dur: 583162190
+    }
+    all_apps {
+      process_name: "com.google.android.apps.youtube.music"
+      reason: "provider"
+      proc_start_dur: 34101441
+      bind_app_dur: -1
+      total_dur: 135004394
+    }
+    all_apps {
+      process_name: "com.google.android.youtube"
+      reason: "provider"
+      proc_start_dur: 73083374
+      bind_app_dur: -1
+      total_dur: 121121785
+    }
+    all_apps {
+      process_name: "com.amazon.mp3"
+      reason: "provider"
+      proc_start_dur: 127611247
+      bind_app_dur: -1
+      total_dur: 173187580
+    }
+    all_apps {
+      process_name: "com.apple.android.music"
+      reason: "provider"
+      proc_start_dur: 29364055
+      bind_app_dur: -1
+      total_dur: 91992879
+    }
+    all_apps {
+      process_name: "com.blinkslabs.blinkist.android"
+      reason: "provider"
+      proc_start_dur: 57628744
+      bind_app_dur: -1
+      total_dur: 78990559
+    }
+    all_apps {
+      process_name: "com.google.android.apps.books"
+      reason: "provider"
+      proc_start_dur: 142572509
+      bind_app_dur: -1
+      total_dur: 193448851
+    }
+    all_apps {
+      process_name: "com.overdrive.mobile.android.libby"
+      reason: "provider"
+      proc_start_dur: 20993978
+      bind_app_dur: -1
+      total_dur: 130225300
+    }
+    all_apps {
+      process_name: "org.thoughtcrime.securesms"
+      reason: "provider"
+      proc_start_dur: 299099894
+      bind_app_dur: -1
+      total_dur: 299780394
+    }
+    all_apps {
+      process_name: "com.patreon.android"
+      reason: "provider"
+      proc_start_dur: 30774414
+      bind_app_dur: -1
+      total_dur: 86755370
+    }
+    all_apps {
+      process_name: "com.spotify.music"
+      reason: "provider"
+      proc_start_dur: 24248860
+      bind_app_dur: -1
+      total_dur: 97743773
+    }
+    all_apps {
+      process_name: "com.google.android.keep"
+      reason: "provider"
+      proc_start_dur: 24017578
+      bind_app_dur: -1
+      total_dur: 67608316
+    }
+    all_apps {
+      process_name: "org.videolan.vlc"
+      reason: "provider"
+      proc_start_dur: 59140991
+      bind_app_dur: -1
+      total_dur: 108707193
+    }
+    all_apps {
+      process_name: "com.android.printspooler"
+      reason: "provider"
+      proc_start_dur: 20540893
+      bind_app_dur: -1
+      total_dur: 66699706
+    }
+    all_apps {
+      process_name: "com.android.providers.calendar"
+      reason: "provider"
+      proc_start_dur: 67028117
+      bind_app_dur: -1
+      total_dur: 101619669
+    }
+    all_apps {
+      process_name: "com.google.android.apps.wallpaper"
+      reason: "provider"
+      proc_start_dur: 50665365
+      bind_app_dur: -1
+      total_dur: 136349243
+    }
+    started_by_broadcast {
+      process_name: "com.google.android.calendar"
+      intent: " android.appwidget.action.APPWIDGET_ENABLED"
+      reason: "broadcast"
+      proc_start_dur: 12347046
+      bind_app_dur: 793497640
+      intent_dur: 51051310
+      total_dur: 1012425578
+    }
+    started_by_service {
+      process_name: "com.google.android.googlequicksearchbox:search"
+      intent: "com.google.android.apps.search.podcasts.browser.PodcastBrowserService"
+      reason: "service"
+      proc_start_dur: 52551066
+      bind_app_dur: 673431316
+      intent_dur: 12822713
+      total_dur: 905843466
+    }
+    started_by_service {
+      process_name: "com.google.android.apps.dreamliner"
+      intent: "com.google.android.apps.dreamliner.notification.DreamlinerNotificationService"
+      reason: "service"
+      proc_start_dur: 13374675
+      bind_app_dur: 205802776
+      intent_dur: 143158203
+      total_dur: 439490479
+    }
+    started_by_service {
+      process_name: "com.google.android.as.oss"
+      intent: "com.google.android.gms.learning.internal.training.InAppJobService"
+      reason: "service"
+      proc_start_dur: 87438151
+      bind_app_dur: 208729451
+      intent_dur: 459920
+      total_dur: 479233521
+    }
+    started_by_service {
+      process_name: "com.google.ar.core"
+      intent: "com.google.ar.core.services.profiles.ProfileDownloadJobService"
+      reason: "service"
+      proc_start_dur: 22607056
+      bind_app_dur: 651136923
+      intent_dur: 18350912
+      total_dur: 803594402
+    }
+    started_by_service {
+      process_name: "com.android.keychain"
+      intent: "com.android.keychain.KeyChainService"
+      reason: "service"
+      proc_start_dur: 143594686
+      bind_app_dur: 124117351
+      intent_dur: -1
+      total_dur: 583162190
+    }
+  }
+}
\ 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 4206419..4f15081 100644
--- a/test/trace_processor/diff_tests/metrics/android/tests.py
+++ b/test/trace_processor/diff_tests/metrics/android/tests.py
@@ -188,13 +188,38 @@
 
   def test_android_boot(self):
     return DiffTestBlueprint(
-        trace=DataPath('android_boot.pftrace'),
+        trace=DataPath('android_postboot_unlock.pftrace'),
         query=Metric('android_boot'),
         out=TextProto(r"""
         android_boot {
           system_server_durations {
-            total_dur: 267193980530
-            uninterruptible_sleep_dur: 3843119529
+            total_dur: 90219646678
+            uninterruptible_sleep_dur: 618417159
+          }
+          systemui_durations {
+            total_dur: 48481027953
+            uninterruptible_sleep_dur: 796263
+          }
+          launcher_durations {
+            total_dur: 23595248987
+            uninterruptible_sleep_dur: 257290255
+          }
+          gms_durations {
+            total_dur: 27804143410
+            uninterruptible_sleep_dur: 101685087
+          }
+          launcher_breakdown {
+            cold_start_dur: 403543498
+          }
+          full_trace_process_start_aggregation {
+            total_start_sum: 10678297679
+            num_of_processes: 1
+            average_start_time: 368217161.3448276
+          }
+          post_boot_process_start_aggregation {
+            total_start_sum: 6112984648
+            num_of_processes: 1
+            average_start_time: 291094507.04761904
           }
         }
         """))
@@ -223,3 +248,17 @@
            }
          }
         """))
+
+  def test_android_boot_unagg(self):
+    return DiffTestBlueprint(
+      trace=DataPath('android_postboot_unlock.pftrace'),
+      query=Metric("android_boot_unagg"),
+      out=Path('android_boot_unagg.out')
+    )
+
+  def test_android_app_process_starts(self):
+    return DiffTestBlueprint(
+      trace=DataPath('android_postboot_unlock.pftrace'),
+      query=Metric("android_app_process_starts"),
+      out=Path('android_app_process_starts.out')
+    )
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/stdlib/android/tests.py b/test/trace_processor/diff_tests/stdlib/android/tests.py
index 897fe4f..956ac87 100644
--- a/test/trace_processor/diff_tests/stdlib/android/tests.py
+++ b/test/trace_processor/diff_tests/stdlib/android/tests.py
@@ -1057,7 +1057,7 @@
         intent_ts,
         intent_dur,
         total_dur
-        FROM _android_app_process_starts
+        FROM android_app_process_starts
         ORDER BY proc_start_ts
       """,
         out=Csv("""