Merge "Support partial update for prebuilts"
diff --git a/appcompat/update.py b/appcompat/update.py
index edf4c16..15c97f3 100755
--- a/appcompat/update.py
+++ b/appcompat/update.py
@@ -34,4 +34,5 @@
 ]
 
 if __name__ == '__main__':
-    update.main(THIS_DIR, 'appcompat', appcompat_install_list, appcompat_extracted_list)
+    args = update.parse_args()
+    update.main(args, THIS_DIR, 'appcompat', appcompat_install_list, appcompat_extracted_list)
diff --git a/common/python/update_prebuilts.py b/common/python/update_prebuilts.py
index 2bbdd3e..096ad9f 100644
--- a/common/python/update_prebuilts.py
+++ b/common/python/update_prebuilts.py
@@ -170,7 +170,7 @@
     check_call(['unzip', '-DD', zip_file, '-d', unzip_path])
 
 
-def get_args():
+def parse_args(parser_modifier=None):
     """Parses and returns command line arguments."""
     parser = argparse.ArgumentParser(
         epilog='Either --build or --local-dist is required.')
@@ -189,6 +189,9 @@
         '-v', '--verbose', action='count', default=0,
         help='Increase output verbosity.')
 
+    if parser_modifier:
+        parser_modifier(parser)
+
     args = parser.parse_args()
     if ((not args.build and not args.local_dist) or
         (args.build and args.local_dist)):
@@ -196,10 +199,9 @@
     return args
 
 
-def main(work_dir, prebuilts, install_list, extracted_list, commit_message_note=None):
+def main(args, work_dir, prebuilts, install_list, extracted_list, commit_message_note=None):
     """Program entry point."""
 
-    args = get_args()
     verbose_map = (logging.WARNING, logging.INFO, logging.DEBUG)
     verbosity = args.verbose
     if verbosity > 2:
diff --git a/mainline/update.py b/mainline/update.py
index a912bf4..45a4580 100755
--- a/mainline/update.py
+++ b/mainline/update.py
@@ -27,16 +27,15 @@
 PREBUILT_DESCRIPTION = 'mainline'
 TARGET = 'mainline_modules'
 
-COMMIT_MESSAGE_NOTE = """\
-CL prepared by prebuilts/runtime/mainline/update.py. See
-prebuilts/runtime/mainline/README.md for update instructions.
+COMMIT_MESSAGE_NOTE_TEMPLATE = """\
+CL prepared by prebuilts/runtime/mainline/update.py with the following
+targets: {}
+
+See prebuilts/runtime/mainline/README.md for update instructions.
 
 Test: Presubmits
 """
 
-mainline_install_list = []
-mainline_extracted_list = []
-
 def InstallApexEntries(apex_name, install_dir):
   res = []
   for arch in ['arm', 'arm64', 'x86', 'x86_64']:
@@ -64,48 +63,64 @@
       install_dir,
       install_unzipped=True)]
 
-# CompOS (T+)
-mainline_install_list.extend(
-    InstallSdkEntries('compos-module-sdk', 'compos/sdk'))
+PREBUILT_INSTALL_MODULES = {
+    # CompOS (T+)
+    'compos': InstallSdkEntries('compos-module-sdk', 'compos/sdk'),
 
-# Conscrypt
-mainline_install_list.extend(
-    InstallApexEntries('com.android.conscrypt', 'conscrypt/apex') +
-    InstallSdkEntries('conscrypt-module-test-exports', 'conscrypt/test-exports') +
-    InstallSdkEntries('conscrypt-module-host-exports', 'conscrypt/host-exports'))
+    # Conscrypt
+    'conscrypt': (
+        InstallApexEntries('com.android.conscrypt', 'conscrypt/apex') +
+        InstallSdkEntries('conscrypt-module-test-exports', 'conscrypt/test-exports') +
+        InstallSdkEntries('conscrypt-module-host-exports', 'conscrypt/host-exports')),
 
-# Runtime (Bionic)
-mainline_install_list.extend(
-    InstallApexEntries('com.android.runtime', 'runtime/apex') +
-    InstallSdkEntries('runtime-module-sdk', 'runtime/sdk') +
-    InstallSdkEntries('runtime-module-host-exports', 'runtime/host-exports'))
+    # Runtime (Bionic)
+    'runtime': (
+        InstallApexEntries('com.android.runtime', 'runtime/apex') +
+        InstallSdkEntries('runtime-module-sdk', 'runtime/sdk') +
+        InstallSdkEntries('runtime-module-host-exports', 'runtime/host-exports')),
 
-# I18N
-mainline_install_list.extend(
-    InstallApexEntries('com.android.i18n', 'i18n/apex') +
-    InstallSdkEntries('i18n-module-sdk', 'i18n/sdk') +
-    InstallSdkEntries('i18n-module-test-exports', 'i18n/test-exports'))
+    # I18N
+    'i18n': (
+        InstallApexEntries('com.android.i18n', 'i18n/apex') +
+        InstallSdkEntries('i18n-module-sdk', 'i18n/sdk') +
+        InstallSdkEntries('i18n-module-test-exports', 'i18n/test-exports')),
 
-# tzdata
-mainline_install_list.extend(
-    InstallApexEntries('com.android.tzdata', 'tzdata/apex') +
-    InstallSdkEntries('tzdata-module-test-exports', 'tzdata/test-exports'))
+    # tzdata
+    'tzdata': (
+        InstallApexEntries('com.android.tzdata', 'tzdata/apex') +
+        InstallSdkEntries('tzdata-module-test-exports', 'tzdata/test-exports')),
 
-# statsd
-mainline_install_list.extend(
-    InstallApexEntries('com.android.os.statsd', 'statsd/apex'))
+    # statsd
+    'statsd': InstallApexEntries('com.android.os.statsd', 'statsd/apex'),
 
-# Platform
-mainline_install_list.extend(
-    InstallSdkEntries('platform-mainline-sdk', 'platform/sdk') +
-    InstallSdkEntries('platform-mainline-test-exports', 'platform/test-exports') +
-    # Shared libraries that are stubs in SDKs, but for which we need their
-    # implementation for device testing.
-    InstallSharedLibEntries('heapprofd_client_api', 'platform/impl') +
-    InstallSharedLibEntries('libartpalette-system', 'platform/impl') +
-    InstallSharedLibEntries('liblog', 'platform/impl'))
+    # Platform
+    'platform': (
+        InstallSdkEntries('platform-mainline-sdk', 'platform/sdk') +
+        InstallSdkEntries('platform-mainline-test-exports', 'platform/test-exports') +
+        # Shared libraries that are stubs in SDKs, but for which we need their
+        # implementation for device testing.
+        InstallSharedLibEntries('heapprofd_client_api', 'platform/impl') +
+        InstallSharedLibEntries('libartpalette-system', 'platform/impl') +
+        InstallSharedLibEntries('liblog', 'platform/impl')),
+}
+
+def add_additional_arguments(parser):
+    parser.add_argument('--install-module', choices=['all'] + PREBUILT_INSTALL_MODULES.keys(),
+                        default='all',
+                        help="The prebuilt module(s) to install.")
 
 if __name__ == '__main__':
-    update.main(THIS_DIR, PREBUILT_DESCRIPTION,
-                mainline_install_list, mainline_extracted_list,
-                COMMIT_MESSAGE_NOTE)
+    args = update.parse_args(add_additional_arguments)
+
+    mainline_install_list = []
+    if args.install_module == 'all':
+      modules = PREBUILT_INSTALL_MODULES.keys()
+    else:
+      modules = [args.install_module]
+    for module in modules:
+      mainline_install_list.extend(PREBUILT_INSTALL_MODULES[module])
+
+    commit_message_note = COMMIT_MESSAGE_NOTE_TEMPLATE.format(', '.join(modules))
+
+    update.main(args, THIS_DIR, PREBUILT_DESCRIPTION, mainline_install_list, [],
+                commit_message_note)
diff --git a/update.py b/update.py
index ddb104c..8023455 100755
--- a/update.py
+++ b/update.py
@@ -32,4 +32,5 @@
 ]
 
 if __name__ == '__main__':
-    update.main(THIS_DIR, 'adb', adb_install_list, adb_extracted_list)
+    args = update.parse_args()
+    update.main(args, THIS_DIR, 'adb', adb_install_list, adb_extracted_list)