Extend measure_startup.by to accept bundles

Change-Id: I0cd2cb4214b0d9a249296d0cc3977f9fe95b151a
diff --git a/tools/startup/adb_utils.py b/tools/startup/adb_utils.py
index 108896e..1c138f0 100755
--- a/tools/startup/adb_utils.py
+++ b/tools/startup/adb_utils.py
@@ -56,13 +56,15 @@
   cmd = create_adb_cmd('shell am broadcast -a %s %s' % (action, component), device_id)
   return subprocess.check_output(cmd).decode('utf-8').strip().splitlines()
 
-def build_apks_from_bundle(bundle, output):
+def build_apks_from_bundle(bundle, output, overwrite=False):
   print('Building %s' % bundle)
   cmd = [
       'java', '-jar', utils.BUNDLETOOL_JAR,
       'build-apks',
       '--bundle=%s' % bundle,
       '--output=%s' % output]
+  if overwrite:
+    cmd.append('--overwrite')
   subprocess.check_call(cmd, stdout=DEVNULL, stderr=DEVNULL)
 
 def capture_screen(target, device_id=None):
diff --git a/tools/startup/measure_startup.py b/tools/startup/measure_startup.py
index 46609fe..e00797c 100755
--- a/tools/startup/measure_startup.py
+++ b/tools/startup/measure_startup.py
@@ -47,13 +47,13 @@
       teardown_options['previous_screen_off_timeout'],
       options.device_id)
 
-def run_all(apk, options, tmp_dir):
+def run_all(apk_or_apks, options, tmp_dir):
   # Launch app while collecting information.
   data_total = {}
   for iteration in range(1, options.iterations + 1):
     print('Starting iteration %i' % iteration)
     out_dir = os.path.join(options.out_dir, str(iteration))
-    teardown_options = setup_for_run(apk, out_dir, options)
+    teardown_options = setup_for_run(apk_or_apks, out_dir, options)
     data = run(out_dir, options, tmp_dir)
     teardown_for_run(out_dir, options, teardown_options)
     add_data(data_total, data)
@@ -76,12 +76,17 @@
     data_summary['%s_med' % key] = statistics.median(value)
   return data_summary
 
-def setup_for_run(apk, out_dir, options):
+def setup_for_run(apk_or_apks, out_dir, options):
   adb_utils.root(options.device_id)
 
   print('Installing')
   adb_utils.uninstall(options.app_id, options.device_id)
-  adb_utils.install(apk, options.device_id)
+  if apk_or_apks['apk']:
+    adb_utils.install(apk_or_apks['apk'], options.device_id)
+  else:
+    assert apk_or_apks['apks']
+    adb_utils.install_apks(apk_or_apks['apks'], options.device_id)
+
   os.makedirs(out_dir, exist_ok=True)
 
   # AOT compile.
@@ -250,8 +255,11 @@
                       default=False,
                       action='store_true')
   result.add_argument('--apk',
-                      help='Path to the APK',
-                      required=True)
+                      help='Path to the .apk')
+  result.add_argument('--apks',
+                      help='Path to the .apks')
+  result.add_argument('--bundle',
+                      help='Path to the .aab')
   result.add_argument('--capture-screen',
                       help='Take a screenshot after each test',
                       default=False,
@@ -290,8 +298,23 @@
                       type=int)
   options, args = result.parse_known_args(argv)
   setattr(options, 'perfetto', not options.no_perfetto)
+
+  paths = [
+      path for path in [options.apk, options.apks, options.bundle]
+      if path is not None]
+  assert len(paths) == 1, 'Expected exactly one .apk, .apks, or .aab file.'
+
+  # Build .apks file up front to avoid building the bundle upon each install.
+  if options.bundle:
+    os.makedirs(options.out_dir, exist_ok=True)
+    options.apks = os.path.join(options.out_dir, 'Bundle.apks')
+    adb_utils.build_apks_from_bundle(
+        options.bundle, options.apks, overwrite=True)
+    del options.bundle
+
   # Profile is only used with --aot.
   assert options.aot or not options.baseline_profile
+
   return options, args
 
 def global_setup(options):
@@ -316,10 +339,13 @@
 def main(argv):
   (options, args) = parse_options(argv)
   with utils.TempDir() as tmp_dir:
-    apk = apk_utils.add_baseline_profile_to_apk(
-        options.apk, options.baseline_profile, tmp_dir)
+    apk_or_apks = { 'apk': options.apk, 'apks': options.apks }
+    if options.baseline_profile:
+      assert not options.apks, 'Unimplemented'
+      apk_or_apks['apk'] = apk_utils.add_baseline_profile_to_apk(
+          options.apk, options.baseline_profile, tmp_dir)
     teardown_options = global_setup(options)
-    run_all(apk, options, tmp_dir)
+    run_all(apk_or_apks, options, tmp_dir)
     global_teardown(options, teardown_options)
 
 if __name__ == '__main__':