add time_to_running_state for the duration between launch and app start time.

Bug: 289134538

Test: Unit/Diff tests.

Change-Id: I626b050f96fc3eefcc2ec9c0e25baf4ef46b16ef
diff --git a/protos/perfetto/metrics/android/startup_metric.proto b/protos/perfetto/metrics/android/startup_metric.proto
index 7a85523..599a07e 100644
--- a/protos/perfetto/metrics/android/startup_metric.proto
+++ b/protos/perfetto/metrics/android/startup_metric.proto
@@ -47,7 +47,7 @@
 
   // Timing information spanning the intent received by the
   // activity manager to the first frame drawn.
-  // Next id: 35.
+  // Next id: 36.
   message ToFirstFrame {
     // The duration between the intent received and first frame.
     optional int64 dur_ns = 1;
@@ -86,6 +86,9 @@
     // The actual duration of the process start (based on the zygote slice).
     optional Slice time_during_start_process = 11;
 
+    // The duration from launch to first running state thread of startup process.
+    optional Slice time_to_running_state = 35;
+
     optional Slice to_post_fork = 18;
     optional Slice to_activity_thread_main = 19;
     optional Slice to_bind_application = 20;
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index 54a7374..70a1f52 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -1823,7 +1823,7 @@
 
   // Timing information spanning the intent received by the
   // activity manager to the first frame drawn.
-  // Next id: 35.
+  // Next id: 36.
   message ToFirstFrame {
     // The duration between the intent received and first frame.
     optional int64 dur_ns = 1;
@@ -1862,6 +1862,9 @@
     // The actual duration of the process start (based on the zygote slice).
     optional Slice time_during_start_process = 11;
 
+    // The duration from launch to first running state thread of startup process.
+    optional Slice time_to_running_state = 35;
+
     optional Slice to_post_fork = 18;
     optional Slice to_activity_thread_main = 19;
     optional Slice to_bind_application = 20;
diff --git a/python/perfetto/trace_processor/metrics.descriptor b/python/perfetto/trace_processor/metrics.descriptor
index 5a432d5..ad0d5da 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/android_startup.sql b/src/trace_processor/metrics/sql/android/android_startup.sql
index 5dc88be..407cd23 100644
--- a/src/trace_processor/metrics/sql/android/android_startup.sql
+++ b/src/trace_processor/metrics/sql/android/android_startup.sql
@@ -233,6 +233,8 @@
         SELECT startup_slice_proto(ts - launches.ts)
         FROM ZYGOTE_FORK_FOR_LAUNCH(launches.startup_id)
       ),
+      'time_to_running_state',
+      time_to_running_state_for_launch(launches.startup_id),
       'time_jit_thread_pool_on_cpu', NULL_IF_EMPTY(startup_slice_proto(
         thread_time_for_launch_state_and_thread(
          launches.startup_id,
diff --git a/src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql b/src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql
index 8603d29..8abecf7 100644
--- a/src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql
+++ b/src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql
@@ -90,3 +90,15 @@
 SELECT SUM(dur)
 FROM launch_thread_state_dur_sum l
 WHERE l.startup_id = $startup_id AND state GLOB $state AND thread_name = $thread_name;
+
+
+-- Given a launch id, returns the duration between the launch and a running state thread of
+-- startup process.
+CREATE PERFETTO FUNCTION time_to_running_state_for_launch(startup_id LONG)
+RETURNS PROTO AS
+  SELECT NULL_IF_EMPTY(
+    STARTUP_SLICE_PROTO(
+      IIF(MIN(l.ts) > launches.ts, MIN(l.ts) - launches.ts, NULL)))
+  FROM launch_threads_by_thread_state l
+  JOIN android_startups launches USING(startup_id)
+  WHERE l.startup_id = $startup_id AND l.state = "Running";
diff --git a/test/trace_processor/diff_tests/startup/android_startup.out b/test/trace_processor/diff_tests/startup/android_startup.out
index 18b879c..e19c2aa 100644
--- a/test/trace_processor/diff_tests/startup/android_startup.out
+++ b/test/trace_processor/diff_tests/startup/android_startup.out
@@ -28,6 +28,10 @@
         dur_ms: 1e-06
       }
       dur_ms: 0.000108
+      time_to_running_state {
+        dur_ns: 8
+        dur_ms: 8e-06
+      }
     }
     activity_hosting_process_count: 1
     process {
diff --git a/test/trace_processor/diff_tests/startup/android_startup_attribution.out b/test/trace_processor/diff_tests/startup/android_startup_attribution.out
index ea41497..d99f957 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_attribution.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_attribution.out
@@ -53,6 +53,10 @@
         dur_ns: 2
         dur_ms: 2e-06
       }
+      time_to_running_state {
+        dur_ns: 55
+        dur_ms: 5.5e-05
+      }
     }
     activity_hosting_process_count: 1
     process {
diff --git a/test/trace_processor/diff_tests/startup/android_startup_attribution_slow.out b/test/trace_processor/diff_tests/startup/android_startup_attribution_slow.out
index 4bf3fff..db0495e 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_attribution_slow.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_attribution_slow.out
@@ -49,6 +49,10 @@
         dur_ns: 20000000000
         dur_ms: 20000.0
       }
+      time_to_running_state {
+        dur_ns: 55000000000
+        dur_ms: 55000.0
+      }
     }
     activity_hosting_process_count: 1
     process {
diff --git a/test/trace_processor/diff_tests/startup/android_startup_breakdown.out b/test/trace_processor/diff_tests/startup/android_startup_breakdown.out
index 09864ed..b3ff7de 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_breakdown.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_breakdown.out
@@ -55,6 +55,10 @@
       mcycles_by_core_type {
         unknown: 103
       }
+      time_to_running_state {
+        dur_ns: 78000000000
+        dur_ms: 78000.0
+      }
     }
     activity_hosting_process_count: 1
     process {
@@ -77,6 +81,11 @@
       method: "performCreate"
       ts_method_start: 188000000000
     }
+    activities {
+      name: "com.google.android.calendar.MainActivity"
+      method: "performResume"
+      ts_method_start: 193000000000
+    }
     optimization_status {
       odex_status: "up-to-date"
       compilation_filter: "speed"
diff --git a/test/trace_processor/diff_tests/startup/android_startup_breakdown.py b/test/trace_processor/diff_tests/startup/android_startup_breakdown.py
index 5a5b4a4..4f937d9 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_breakdown.py
+++ b/test/trace_processor/diff_tests/startup/android_startup_breakdown.py
@@ -67,7 +67,7 @@
 trace.add_atrace_end(ts=to_s(192), tid=3, pid=3)
 trace.add_atrace_end(ts=to_s(192), tid=3, pid=3)
 trace.add_atrace_begin(
-    ts=193,
+    ts=to_s(193),
     tid=3,
     pid=3,
     buf='performResume:com.google.android.calendar.MainActivity')
diff --git a/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.out b/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.out
index 9e7aad7..9aac34c 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.out
@@ -20,8 +20,8 @@
         dur_ms: 8000.0
       }
       time_bind_application {
-        dur_ns: 9000000000
-        dur_ms: 9000.0
+        dur_ns: 10000000000
+        dur_ms: 10000.0
       }
       time_activity_start {
         dur_ns: 1000000000
@@ -55,6 +55,10 @@
       mcycles_by_core_type {
         unknown: 103
       }
+      time_to_running_state {
+        dur_ns: 78000000000
+        dur_ms: 78000.0
+      }
     }
     activity_hosting_process_count: 1
     process {
@@ -77,6 +81,11 @@
       method: "performCreate"
       ts_method_start: 188000000000
     }
+    activities {
+      name: "com.google.android.calendar.MainActivity"
+      method: "performResume"
+      ts_method_start: 193000000000
+    }
     optimization_status {
       odex_status: "up-to-date"
       compilation_filter: "speed-profile"
diff --git a/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.py b/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.py
index 06422a2..f4ea962 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.py
+++ b/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.py
@@ -29,7 +29,7 @@
 trace.add_process(3, 1, 'com.google.android.calendar', uid=10001)
 
 trace.add_package_list(
-    ts=100, name='com.google.android.calendar', uid=10001, version_code=123)
+    ts=to_s(100), name='com.google.android.calendar', uid=10001, version_code=123)
 
 trace.add_ftrace_packet(cpu=0)
 
@@ -67,7 +67,7 @@
 trace.add_atrace_end(ts=to_s(192), tid=3, pid=3)
 trace.add_atrace_end(ts=to_s(192), tid=3, pid=3)
 trace.add_atrace_begin(
-    ts=193,
+    ts=to_s(193),
     tid=3,
     pid=3,
     buf='performResume:com.google.android.calendar.MainActivity')
diff --git a/test/trace_processor/diff_tests/startup/android_startup_process_track.out b/test/trace_processor/diff_tests/startup/android_startup_process_track.out
index bd6ccea..8e4df59 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_process_track.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_process_track.out
@@ -105,6 +105,7 @@
         dur_ns: 3
         dur_ms: 3e-06
       }
+
     }
     activity_hosting_process_count: 1
     process {
diff --git a/test/trace_processor/diff_tests/startup/android_startup_slow.out b/test/trace_processor/diff_tests/startup/android_startup_slow.out
index f791fd6..63ca0e2 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_slow.out
+++ b/test/trace_processor/diff_tests/startup/android_startup_slow.out
@@ -28,6 +28,10 @@
         dur_ms: 1000
       }
       dur_ms: 108000
+      time_to_running_state {
+        dur_ns: 8000000000
+        dur_ms: 8000.0
+      }
     }
     activity_hosting_process_count: 1
     process {