Support for measuring hot startup

Change-Id: Ib787f353dde894c1b9f513dae0e1496107055c9f
diff --git a/tools/startup/adb_utils.py b/tools/startup/adb_utils.py
index 8dba4a2..7f1d3bc 100644
--- a/tools/startup/adb_utils.py
+++ b/tools/startup/adb_utils.py
@@ -255,6 +255,10 @@
   assert not wait_for_activity_to_launch or 'total_time' in result
   return result
 
+def navigate_to_home_screen(device_id=None):
+  cmd = create_adb_cmd('shell input keyevent KEYCODE_HOME', device_id)
+  subprocess.check_call(cmd, stdout=DEVNULL, stderr=DEVNULL)
+
 def prepare_for_interaction_with_device(device_id=None, device_pin=None):
   # Increase screen off timeout to avoid device screen turns off.
   twenty_four_hours_in_millis = 24 * 60 * 60 * 1000
diff --git a/tools/startup/measure_startup.py b/tools/startup/measure_startup.py
index d9e0801..f0b2ce9 100755
--- a/tools/startup/measure_startup.py
+++ b/tools/startup/measure_startup.py
@@ -75,6 +75,15 @@
       adb_utils.install_profile(options.app_id, options.device_id)
     else:
       adb_utils.force_compilation(options.app_id, options.device_id)
+  if options.hot_startup:
+    adb_utils.launch_activity(
+        options.app_id,
+        options.main_activity,
+        options.device_id,
+        wait_for_activity_to_launch=False)
+    time.sleep(options.startup_duration)
+    adb_utils.navigate_to_home_screen(options.device_id)
+    time.sleep(1)
   adb_utils.drop_caches(options.device_id)
   os.makedirs(out_dir, exist_ok=True)
 
@@ -147,24 +156,25 @@
         startup_metric.android_startup.startup[0].to_first_frame.dur_ms
     perfetto_startup_data['perfetto_startup'] = round(time_to_first_frame_ms)
 
-    # Compute time to first and last doFrame event.
-    bind_application_slice = perfetto_utils.find_unique_slice_by_name(
-        'bindApplication', options, trace_processor)
-    activity_start_slice = perfetto_utils.find_unique_slice_by_name(
-        'activityStart', options, trace_processor)
-    do_frame_slices = perfetto_utils.find_slices_by_name(
-        'Choreographer#doFrame', options, trace_processor)
-    first_do_frame_slice = next(do_frame_slices)
-    *_, last_do_frame_slice = do_frame_slices
+    if not options.hot_startup:
+      # Compute time to first and last doFrame event.
+      bind_application_slice = perfetto_utils.find_unique_slice_by_name(
+          'bindApplication', options, trace_processor)
+      activity_start_slice = perfetto_utils.find_unique_slice_by_name(
+          'activityStart', options, trace_processor)
+      do_frame_slices = perfetto_utils.find_slices_by_name(
+          'Choreographer#doFrame', options, trace_processor)
+      first_do_frame_slice = next(do_frame_slices)
+      *_, last_do_frame_slice = do_frame_slices
 
-    perfetto_startup_data.update({
-      'time_to_first_choreographer_do_frame_ms':
-          round(perfetto_utils.get_slice_end_since_start(
-              first_do_frame_slice, bind_application_slice)),
-      'time_to_last_choreographer_do_frame_ms':
-          round(perfetto_utils.get_slice_end_since_start(
-              last_do_frame_slice, bind_application_slice))
-    })
+      perfetto_startup_data.update({
+        'time_to_first_choreographer_do_frame_ms':
+            round(perfetto_utils.get_slice_end_since_start(
+                first_do_frame_slice, bind_application_slice)),
+        'time_to_last_choreographer_do_frame_ms':
+            round(perfetto_utils.get_slice_end_since_start(
+                last_do_frame_slice, bind_application_slice))
+      })
 
   # Return combined startup data.
   return startup_data | perfetto_startup_data
@@ -196,6 +206,10 @@
                       help='Device id (e.g., emulator-5554).')
   result.add_argument('--device-pin',
                       help='Device pin code (e.g., 1234)')
+  result.add_argument('--hot-startup',
+                      help='Measure hot startup instead of cold startup',
+                      default=False,
+                      action='store_true')
   result.add_argument('--iterations',
                       help='Number of traces to generate',
                       default=1,
@@ -212,6 +226,10 @@
                       required=True)
   result.add_argument('--baseline-profile',
                       help='Baseline profile to install')
+  result.add_argument('--startup-duration',
+                      help='Duration in seconds before shutting down app',
+                      default=15,
+                      type=int)
   options, args = result.parse_known_args(argv)
   setattr(options, 'perfetto', not options.no_perfetto)
   # Profile is only used with --aot.