#!/usr/bin/env python3
# Lint as: python2, python3
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from __future__ import print_function

import argparse
import contextlib
import copy
import logging
import os
import re
import shutil
import stat
import subprocess
import tempfile
import textwrap
import zipfile
# Use 'sudo pip install jinja2' to install.
from jinja2 import Template


# TODO(ihf): Assign better TIME to control files. Scheduling uses this to run
# LENGTHY first, then LONG, MEDIUM etc. But we need LENGTHY for the collect
# job, downgrade all others. Make sure this still works in CQ/smoke suite.
_CONTROLFILE_TEMPLATE = Template(
        textwrap.dedent("""\
    # Copyright {{year}} The Chromium OS Authors. All rights reserved.
    # Use of this source code is governed by a BSD-style license that can be
    # found in the LICENSE file.

    # This file has been automatically generated. Do not edit!
    {%- if servo_support_needed %}

    from autotest_lib.server import utils

    {%- endif %}

    AUTHOR = 'ARC++ Team'
    NAME = '{{name}}'
    ATTRIBUTES = '{{attributes}}'
    DEPENDENCIES = '{{dependencies}}'
    JOB_RETRIES = {{job_retries}}
    TEST_TYPE = 'server'
    TIME = '{{test_length}}'
    MAX_RESULT_SIZE_KB = {{max_result_size_kb}}
    {%- if sync_count and sync_count > 1 %}
    SYNC_COUNT = {{sync_count}}
    {%- endif %}
    {%- if priority %}
    PRIORITY = {{priority}}
    {%- endif %}
    DOC = '{{DOC}}'
    {%- if servo_support_needed %}

    # For local debugging, if your test setup doesn't have servo, REMOVE these
    # two lines.
    args_dict = utils.args_to_dict(args)
    servo_args = hosts.CrosHost.get_servo_arguments(args_dict)

    {%- endif %}
    {% if sync_count and sync_count > 1 %}
    from autotest_lib.server import utils as server_utils
    def {{test_func_name}}(ntuples):
        host_list = [hosts.create_host(machine) for machine in ntuples]
    {% else %}
    def {{test_func_name}}(machine):
        {%- if servo_support_needed %}
        # REMOVE 'servo_args=servo_args' arg for local debugging if your test
        # setup doesn't have servo.
        try:
            host_list = [hosts.create_host(machine, servo_args=servo_args)]
        except:
            # Just ignore any servo setup flakiness.
            host_list = [hosts.create_host(machine)]
        {%- else %}
        host_list = [hosts.create_host(machine)]
        {%- endif %}
    {%- endif %}
        job.run_test(
            '{{base_name}}',
    {%- if camera_facing %}
            camera_facing='{{camera_facing}}',
            cmdline_args=args,
    {%- endif %}
            hosts=host_list,
            iterations=1,
    {%- if max_retries != None %}
            max_retry={{max_retries}},
    {%- endif %}
    {%- if enable_default_apps %}
            enable_default_apps=True,
    {%- endif %}
    {%- if needs_push_media %}
            needs_push_media={{needs_push_media}},
    {%- endif %}
    {%- if needs_cts_helpers %}
            use_helpers={{needs_cts_helpers}},
    {%- endif %}
            tag='{{tag}}',
            test_name='{{name}}',
    {%- if authkey %}
            authkey='{{authkey}}',
    {%- endif %}
            run_template={{run_template}},
            retry_template={{retry_template}},
            target_module={% if target_module %}'{{target_module}}'{% else %}None{%endif%},
            target_plan={% if target_plan %}'{{target_plan}}'{% else %}None{% endif %},
    {%- if abi %}
            bundle='{{abi}}',
    {%- endif %}
    {%- if extra_artifacts %}
            extra_artifacts={{extra_artifacts}},
    {%- endif %}
    {%- if extra_artifacts_host %}
            extra_artifacts_host={{extra_artifacts_host}},
    {%- endif %}
    {%- if uri %}
            uri='{{uri}}',
    {%- endif %}
    {%- for arg in extra_args %}
            {{arg}},
    {%- endfor %}
    {%- if servo_support_needed %}
            hard_reboot_on_failure=True,
    {%- endif %}
    {%- if camera_facing %}
            retry_manual_tests=True,
    {%- endif %}
            timeout={{timeout}})

    {% if sync_count and sync_count > 1 -%}
    ntuples, failures = server_utils.form_ntuples_from_machines(machines,
                                                                SYNC_COUNT)
    # Use log=False in parallel_simple to avoid an exception in setting up
    # the incremental parser when SYNC_COUNT > 1.
    parallel_simple({{test_func_name}}, ntuples, log=False)
    {% else -%}
    parallel_simple({{test_func_name}}, machines)
    {% endif %}
"""))

CONFIG = None

_COLLECT = 'tradefed-run-collect-tests-only-internal'
_PUBLIC_COLLECT = 'tradefed-run-collect-tests-only'
_CTSHARDWARE_COLLECT = 'tradefed-run-collect-tests-only-hardware-internal'
_PUBLIC_CTSHARDWARE_COLLECT = 'tradefed-run-collect-tests-only-hardware'


_TEST_LENGTH = {1: 'FAST', 2: 'SHORT', 3: 'MEDIUM', 4: 'LONG', 5: 'LENGTHY'}

_ALL = 'all'


def get_tradefed_build(line):
    """Gets the build of Android CTS from tradefed.

    @param line Tradefed identification output on startup. Example:
                Android Compatibility Test Suite 7.0 (3423912)
    @return Tradefed CTS build. Example: 2813453.
    """
    # Sample string:
    # - Android Compatibility Test Suite 7.0 (3423912)
    # - Android Compatibility Test Suite for Instant Apps 1.0 (4898911)
    # - Android Google Mobile Services (GMS) Test Suite 6.0_r1 (4756896)
    m = re.search(r' \((.*)\)', line)
    if m:
        return m.group(1)
    logging.warning('Could not identify build in line "%s".', line)
    return '<unknown>'


def get_tradefed_revision(line):
    """Gets the revision of Android CTS from tradefed.

    @param line Tradefed identification output on startup.
                Example:
                 Android Compatibility Test Suite 6.0_r6 (2813453)
                 Android Compatibility Test Suite for Instant Apps 1.0 (4898911)
    @return Tradefed CTS revision. Example: 6.0_r6.
    """
    tradefed_identifier_list = [
            r'Android Google Mobile Services \(GMS\) Test Suite (.*) \(',
            r'Android Compatibility Test Suite(?: for Instant Apps)? (.*) \(',
            r'Android Vendor Test Suite (.*) \(',
            r'Android Security Test Suite (.*) \('
    ]

    for identifier in tradefed_identifier_list:
        m = re.search(identifier, line)
        if m:
            return m.group(1)

    logging.warning('Could not identify revision in line "%s".', line)
    return None


def get_bundle_abi(filename):
    """Makes an educated guess about the ABI.

    In this case we chose to guess by filename, but we could also parse the
    xml files in the module. (Maybe this needs to be done in the future.)
    """
    if CONFIG.get('SINGLE_CONTROL_FILE'):
        return None
    if filename.endswith('arm.zip'):
        return 'arm'
    if filename.endswith('arm64.zip'):
        return 'arm64'
    if filename.endswith('x86.zip'):
        return 'x86'
    if filename.endswith('x86_64.zip'):
        return 'x86_64'

    assert(CONFIG['TRADEFED_CTS_COMMAND'] =='gts'), 'Only GTS has empty ABI'
    return ''


def get_extension(module,
                  abi,
                  revision,
                  is_public=False,
                  led_provision=None,
                  camera_facing=None,
                  hardware_suite=False,
                  abi_bits=None):
    """Defines a unique string.

    Notice we chose module revision first, then abi, as the module revision
    changes regularly. This ordering makes it simpler to add/remove modules.
    @param module: CTS module which will be tested in the control file. If 'all'
                   is specified, the control file will runs all the tests.
    @param public: boolean variable to specify whether or not the bundle is from
                   public source or not.
    @param led_provision: string or None indicate whether the camerabox has led
                          light or not.
    @param camera_facing: string or None indicate whether it's camerabox tests
                          for specific camera facing or not.
    @param abi_bits: 32 or 64 or None indicate the bitwidth for the specific
                     abi to run.
    @return string: unique string for specific tests. If public=True then the
                    string is "<abi>.<module>", otherwise, the unique string is
                    "<revision>.<abi>.<module>". Note that if abi is empty, the
                    abi part is omitted.
    """
    ext_parts = []
    if not CONFIG.get('SINGLE_CONTROL_FILE') and not is_public:
        ext_parts = [revision]
    if not CONFIG.get('SINGLE_CONTROL_FILE') and abi:
        ext_parts += [abi]
    ext_parts += [module]
    if led_provision:
        ext_parts += [led_provision]
    if camera_facing:
        ext_parts += ['camerabox', camera_facing]
    if hardware_suite and module not in get_collect_modules(
            is_public, hardware_suite):
        ext_parts += ['ctshardware']
    if not CONFIG.get('SINGLE_CONTROL_FILE') and abi and abi_bits:
        ext_parts += [str(abi_bits)]
    return '.'.join(ext_parts)


def get_doc(modules, abi, is_public):
    """Defines the control file DOC string."""
    if modules.intersection(get_collect_modules(is_public)) or CONFIG.get(
            'SINGLE_CONTROL_FILE'):
        module_text = 'all'
    else:
        # Generate per-module DOC
        module_text = 'module ' + ', '.join(sorted(list(modules)))

    abi_text = (' using %s ABI' % abi) if abi else ''

    doc = ('Run %s of the %s%s in the ARC++ container.'
           % (module_text, CONFIG['DOC_TITLE'], abi_text))
    return doc


def servo_support_needed(modules, is_public=True):
    """Determines if servo support is needed for a module."""
    return not is_public and all(module in CONFIG['NEEDS_POWER_CYCLE']
                                 for module in modules)


def get_controlfile_name(module,
                         abi,
                         revision,
                         is_public=False,
                         led_provision=None,
                         camera_facing=None,
                         abi_bits=None,
                         hardware_suite=False):
    """Defines the control file name.

    @param module: CTS module which will be tested in the control file. If 'all'
                   is specified, the control file will runs all the tests.
    @param public: boolean variable to specify whether or not the bundle is from
                   public source or not.
    @param camera_facing: string or None indicate whether it's camerabox tests
                          for specific camera facing or not.
    @param led_provision: string or None indicate whether the camerabox has led
                          light or not.
    @param abi_bits: 32 or 64 or None indicate the bitwidth for the specific
                     abi to run.
    @return string: control file for specific tests. If public=True or
                    module=all, then the name will be "control.<abi>.<module>",
                    otherwise, the name will be
                    "control.<revision>.<abi>.<module>".
    """
    return 'control.%s' % get_extension(module, abi, revision, is_public,
                                        led_provision, camera_facing, hardware_suite,
                                        abi_bits)


def get_sync_count(_modules, _abi, _is_public):
    return 1


def get_suites(modules, abi, is_public, camera_facing=None,
               hardware_suite=False):
    """Defines the suites associated with a module.

    @param module: CTS module which will be tested in the control file. If 'all'
                   is specified, the control file will runs all the tests.
    # TODO(ihf): Make this work with the "all" and "collect" generation,
    # which currently bypass this function.
    """
    cts_hardware_modules = set(CONFIG.get('HARDWARE_MODULES', []))

    if is_public:
        for module in modules:
            suites = set([CONFIG['MOBLAB_SUITE_NAME']])
            if hardware_suite and module in cts_hardware_modules:
                suites = set([CONFIG['MOBLAB_HARDWARE_SUITE_NAME']])
        return sorted(list(suites))

    suites = set(CONFIG['INTERNAL_SUITE_NAMES'])

    for module in modules:
        if module in get_collect_modules(is_public, hardware_suite):
            # We collect all tests both in arc-gts and arc-gts-qual as both have
            # a chance to be complete (and used for submission).
            suites |= set(CONFIG['QUAL_SUITE_NAMES'])
        if module in CONFIG['EXTRA_ATTRIBUTES']:
            # Special cases come with their own suite definitions.
            suites |= set(CONFIG['EXTRA_ATTRIBUTES'][module])
        if module in CONFIG['SMOKE'] and (abi == 'arm' or abi == ''):
            # Handle VMTest by adding a few jobs to suite:smoke.
            suites.add('suite:smoke')
        if module in CONFIG['HARDWARE_DEPENDENT_MODULES']:
            # CTS modules to be run on all unibuild models.
            suites.add('suite:arc-cts-unibuild-hw')
        if abi == 'x86':
            # Handle a special builder for running all of CTS in a betty VM.
            # TODO(ihf): figure out if this builder is still alive/needed.
            vm_suite = None
            for suite in CONFIG['VMTEST_INFO_SUITES']:
                if not vm_suite:
                    vm_suite = suite
                if module in CONFIG['VMTEST_INFO_SUITES'][suite]:
                    vm_suite = suite
            if vm_suite is not None:
                suites.add('suite:%s' % vm_suite)
        # One or two modules hould be in suite:bvt-arc to cover CQ/PFQ. A few
        # spare/fast modules can run in suite:bvt-perbuild in case we need a
        # replacement for the module in suite:bvt-arc (integration test for
        # cheets_CTS only, not a correctness test for CTS content).
        if module in CONFIG['BVT_ARC'] and (abi == 'arm' or abi == ''):
            suites.add('suite:bvt-arc')
        elif module in CONFIG['BVT_PERBUILD'] and (abi == 'arm' or abi == ''):
            suites.add('suite:bvt-perbuild')

    if hardware_suite:
        suites = set([CONFIG['HARDWARE_SUITE_NAME']])

    if camera_facing != None:
        suites.add('suite:arc-cts-camera')

    return sorted(list(suites))


def get_dependencies(modules, abi, is_public, led_provision, camera_facing):
    """Defines lab dependencies needed to schedule a module.

    @param module: CTS module which will be tested in the control file. If 'all'
                   is specified, the control file will runs all the tests.
    @param abi: string that specifies the application binary interface of the
                current test.
    @param is_public: boolean variable to specify whether or not the bundle is
                      from public source or not.
    @param led_provision: specify if led is provisioned in the camerabox setup. 'noled' when
                          there is no led light in the box and 'led' otherwise.
    @param camera_facing: specify requirement of camerabox setup with target
                          test camera facing. Set to None if it's not camerabox
                          related test.
    """
    dependencies = ['arc']
    if abi in CONFIG['LAB_DEPENDENCY']:
        dependencies += CONFIG['LAB_DEPENDENCY'][abi]

    if led_provision is not None:
        dependencies.append('camerabox_light:'+led_provision)

    if camera_facing is not None:
        dependencies.append('camerabox_facing:'+camera_facing)

    for module in modules:
        if is_public and module in CONFIG['PUBLIC_DEPENDENCIES']:
            dependencies.extend(CONFIG['PUBLIC_DEPENDENCIES'][module])

    return ', '.join(dependencies)


def get_job_retries(modules, is_public, suites):
    """Define the number of job retries associated with a module.

    @param module: CTS module which will be tested in the control file. If a
                   special module is specified, the control file will runs all
                   the tests without retry.
    @param is_public: true if the control file is for moblab (public) use.
    @param suites: the list of suites that the control file belongs to.
    """
    # TODO(haddowk): remove this when cts p has stabalized.
    if is_public:
        return CONFIG['CTS_JOB_RETRIES_IN_PUBLIC']
    # Presubmit check forces to set 2 or more retries for CQ tests.
    if 'suite:bvt-arc' in suites:
        return 2
    retries = 1  # 0 is NO job retries, 1 is one retry etc.
    for module in modules:
        # We don't want job retries for module collection or special cases.
        if (module in get_collect_modules(is_public) or module == _ALL or
            ('CtsDeqpTestCases' in CONFIG['EXTRA_MODULES'] and
             module in CONFIG['EXTRA_MODULES']['CtsDeqpTestCases']
             )):
            retries = 0
    return retries


def get_max_retries(modules, abi, suites, is_public):
    """Partners experiance issues where some modules are flaky and require more

       retries.  Calculate the retry number per module on moblab.
    @param module: CTS module which will be tested in the control file.
    """
    retry = -1
    if is_public:
        if _ALL in CONFIG['PUBLIC_MODULE_RETRY_COUNT']:
            retry = CONFIG['PUBLIC_MODULE_RETRY_COUNT'][_ALL]

        # In moblab at partners we may need many more retries than in lab.
        for module in modules:
            if module in CONFIG['PUBLIC_MODULE_RETRY_COUNT']:
                retry = max(retry, CONFIG['PUBLIC_MODULE_RETRY_COUNT'][module])
    else:
        # See if we have any special values for the module, chose the largest.
        for module in modules:
            if module in CONFIG['CTS_MAX_RETRIES']:
                retry = max(retry, CONFIG['CTS_MAX_RETRIES'][module])

    # Ugly overrides.
    # In bvt we don't want to hold the CQ/PFQ too long.
    if 'suite:bvt-arc' in suites:
        retry = 3
    # Not strict as CQ for bvt-perbuild. Let per-module config take priority.
    if retry == -1 and 'suite:bvt-perbuild' in suites:
        retry = 3
    # During qualification we want at least 9 retries, possibly more.
    # TODO(kinaba&yoshiki): do not abuse suite names
    if CONFIG.get('QUAL_SUITE_NAMES') and \
            set(CONFIG['QUAL_SUITE_NAMES']) & set(suites):
        retry = max(retry, CONFIG['CTS_QUAL_RETRIES'])
    # Collection should never have a retry. This needs to be last.
    if modules.intersection(get_collect_modules(is_public)):
        retry = 0

    if retry >= 0:
        return retry
    # Default case omits the retries in the control file, so tradefed_test.py
    # can chose its own value.
    return None


def get_max_result_size_kb(modules, is_public):
    """Returns the maximum expected result size in kB for autotest.

    @param modules: List of CTS modules to be tested by the control file.
    """
    for module in modules:
        if (module in get_collect_modules(is_public) or
            module == 'CtsDeqpTestCases'):
            # CTS tests and dump logs for android-cts.
            return CONFIG['LARGE_MAX_RESULT_SIZE']
    # Individual module normal produces less results than all modules.
    return CONFIG['NORMAL_MAX_RESULT_SIZE']


def get_extra_args(modules, is_public):
    """Generate a list of extra arguments to pass to the test.

    Some params are specific to a particular module, particular mode or
    combination of both, generate a list of arguments to pass into the template.

    @param modules: List of CTS modules to be tested by the control file.
    """
    extra_args = set()
    preconditions = []
    login_preconditions = []
    prerequisites = []
    for module in sorted(modules):
        # Remove this once JDK9 is the base JDK for lab.
        if CONFIG.get('USE_JDK9', False):
            extra_args.add('use_jdk9=True')
        if module in CONFIG.get('USE_OLD_ADB', []):
            extra_args.add('use_old_adb=True')
        if is_public:
            extra_args.add('warn_on_test_retry=False')
            extra_args.add('retry_manual_tests=True')
            preconditions.extend(CONFIG['PUBLIC_PRECONDITION'].get(module, []))
        else:
            preconditions.extend(CONFIG['PRECONDITION'].get(module, []))
            login_preconditions.extend(
                CONFIG['LOGIN_PRECONDITION'].get(module, []))
            prerequisites.extend(CONFIG['PREREQUISITES'].get(module,[]))

    # Notice: we are just squishing the preconditions for all modules together
    # with duplicated command removed. This may not always be correct.
    # In such a case one should split the bookmarks in a way that the modules
    # with conflicting preconditions end up in separate control files.
    def deduped(lst):
        """Keep only the first occurrence of each element."""
        return [e for i, e in enumerate(lst) if e not in lst[0:i]]

    if preconditions:
        # To properly escape the public preconditions we need to format the list
        # manually using join.
        extra_args.add('precondition_commands=[%s]' % ', '.join(
            deduped(preconditions)))
    if login_preconditions:
        extra_args.add('login_precondition_commands=[%s]' % ', '.join(
            deduped(login_preconditions)))
    if prerequisites:
        extra_args.add("prerequisites=['%s']" % "', '".join(
            deduped(prerequisites)))
    return sorted(list(extra_args))


def get_test_length(modules):
    """ Calculate the test length based on the module name.

    To better optimize DUT's connected to moblab, it is better to run the
    longest tests and tests that require limited resources.  For these modules
    override from the default test length.

    @param module: CTS module which will be tested in the control file. If 'all'
                   is specified, the control file will runs all the tests.

    @return string: one of the specified test lengths:
                    ['FAST', 'SHORT', 'MEDIUM', 'LONG', 'LENGTHY']
    """
    length = 3  # 'MEDIUM'
    for module in modules:
        if module in CONFIG['OVERRIDE_TEST_LENGTH']:
            length = max(length, CONFIG['OVERRIDE_TEST_LENGTH'][module])
    return _TEST_LENGTH[length]


def get_test_priority(modules, is_public):
    """ Calculate the test priority based on the module name.

    On moblab run all long running tests and tests that have some unique
    characteristic at a higher priority (50).

    This optimizes the total run time of the suite assuring the shortest
    time between suite kick off and 100% complete.

    @param module: CTS module which will be tested in the control file.

    @return int: 0 if priority not to be overridden, or priority number otherwise.
    """
    if not is_public:
        return 0

    priority = 0
    overide_test_priority_dict = CONFIG.get('PUBLIC_OVERRIDE_TEST_PRIORITY', {})
    for module in modules:
        if module in overide_test_priority_dict:
            priority = max(priority, overide_test_priority_dict[module])
        elif (module in CONFIG['OVERRIDE_TEST_LENGTH'] or
                module in CONFIG['PUBLIC_DEPENDENCIES'] or
                module in CONFIG['PUBLIC_PRECONDITION'] or
                module.split('.')[0] in CONFIG['OVERRIDE_TEST_LENGTH']):
            priority = max(priority, 50)
    return priority


def get_authkey(is_public):
    if is_public or not CONFIG['AUTHKEY']:
        return None
    return CONFIG['AUTHKEY']


def _format_collect_cmd(is_public, abi_to_run, retry, is_hardware=False):
    """Returns a list specifying tokens for tradefed to list all tests."""
    if retry:
        return None
    cmd = ['run', 'commandAndExit', 'collect-tests-only']
    if CONFIG['TRADEFED_DISABLE_REBOOT_ON_COLLECTION']:
        cmd += ['--disable-reboot']
    if is_hardware:
        cmd.append('--subplan')
        cmd.append('cts-hardware')
    for m in CONFIG['MEDIA_MODULES']:
        cmd.append('--module-arg')
        cmd.append('%s:skip-media-download:true' % m)
    if (not is_public and
            not CONFIG.get('NEEDS_DYNAMIC_CONFIG_ON_COLLECTION', True)):
        cmd.append('--dynamic-config-url=')
    if abi_to_run:
        cmd += ['--abi', abi_to_run]
    return cmd


def _get_special_command_line(modules, _is_public):
    """This function allows us to split a module like Deqp into segments."""
    cmd = []
    for module in sorted(modules):
        cmd += CONFIG['EXTRA_COMMANDLINE'].get(module, [])
    return cmd


def _format_modules_cmd(is_public,
                        abi_to_run,
                        modules=None,
                        retry=False,
                        whole_module_set=None,
                        is_hardware=False):
    """Returns list of command tokens for tradefed."""
    if retry:
        assert(CONFIG['TRADEFED_RETRY_COMMAND'] == 'cts' or
               CONFIG['TRADEFED_RETRY_COMMAND'] == 'retry')

        cmd = ['run', 'commandAndExit', CONFIG['TRADEFED_RETRY_COMMAND'],
               '--retry', '{session_id}']
    else:
        # For runs create a logcat file for each individual failure.
        cmd = ['run', 'commandAndExit', CONFIG['TRADEFED_CTS_COMMAND']]

        special_cmd = _get_special_command_line(modules, is_public)
        if special_cmd:
            cmd.extend(special_cmd)
        elif _ALL in modules:
            pass
        elif len(modules) == 1:
            cmd += ['--module', list(modules)[0]]
        else:
            if whole_module_set is None:
                assert (CONFIG['TRADEFED_CTS_COMMAND'] != 'cts-instant'), \
                       'cts-instant cannot include multiple modules'
                # We run each module with its own --include-filter option.
                # https://source.android.com/compatibility/cts/run
                for module in sorted(modules):
                    # b/196756614 32-bit jobs should skip [parameter] modules.
                    if is_parameterized_module(module) and abi_to_run in [
                            'x86', 'armeabi-v7a'
                    ]:
                        continue
                    cmd += ['--include-filter', module]
            else:
                # CTS-Instant does not support --include-filter due to
                # its implementation detail. Instead, exclude the complement.
                for module in sorted(whole_module_set - set(modules)):
                    cmd += ['--exclude-filter', module]

        # For runs create a logcat file for each individual failure.
        # Not needed on moblab, nobody is going to look at them.
        if (not modules.intersection(CONFIG['DISABLE_LOGCAT_ON_FAILURE']) and
            not is_public and
            CONFIG['TRADEFED_CTS_COMMAND'] != 'gts'):
            cmd.append('--logcat-on-failure')

        if CONFIG['TRADEFED_IGNORE_BUSINESS_LOGIC_FAILURE']:
            cmd.append('--ignore-business-logic-failure')

    if CONFIG['TRADEFED_DISABLE_REBOOT']:
        cmd.append('--disable-reboot')
    if (CONFIG['TRADEFED_MAY_SKIP_DEVICE_INFO'] and
        not (modules.intersection(CONFIG['BVT_ARC'] + CONFIG['SMOKE'] +
             CONFIG['NEEDS_DEVICE_INFO']))):
        cmd.append('--skip-device-info')
    if abi_to_run:
        cmd += ['--abi', abi_to_run]
    # If NEEDS_DYNAMIC_CONFIG is set, disable the feature except on the modules
    # that explicitly set as needed.
    if (not is_public and CONFIG.get('NEEDS_DYNAMIC_CONFIG') and
            not modules.intersection(CONFIG['NEEDS_DYNAMIC_CONFIG'])):
        cmd.append('--dynamic-config-url=')

    return cmd


def get_run_template(modules,
                     is_public,
                     retry=False,
                     abi_to_run=None,
                     whole_module_set=None,
                     is_hardware=False):
    """Command to run the modules specified by a control file."""
    no_intersection = not modules.intersection(get_collect_modules(is_public,
                          is_hardware))
    collect_present = (_COLLECT in modules or _PUBLIC_COLLECT in modules or
                       _CTSHARDWARE_COLLECT in modules or
                       _PUBLIC_CTSHARDWARE_COLLECT in modules)
    all_present = _ALL in modules
    if no_intersection or (all_present and not collect_present):
        return _format_modules_cmd(is_public,
                                   abi_to_run,
                                   modules,
                                   retry=retry,
                                   whole_module_set=whole_module_set,
                                   is_hardware=is_hardware)
    elif collect_present:
        return _format_collect_cmd(is_public, abi_to_run, retry=retry,
                   is_hardware=is_hardware)
    return None

def get_retry_template(modules, is_public):
    """Command to retry the failed modules as specified by a control file."""
    return get_run_template(modules, is_public, retry=True)


def get_extra_modules_dict(is_public, abi):
    if not is_public:
        return CONFIG['EXTRA_MODULES']

    extra_modules = copy.deepcopy(CONFIG['PUBLIC_EXTRA_MODULES'])
    if abi in CONFIG['EXTRA_SUBMODULE_OVERRIDE']:
        for _, config in extra_modules.items():
            for old, news in CONFIG['EXTRA_SUBMODULE_OVERRIDE'][abi].items():
                if old in config.keys():
                    suite = config[old]
                    config.pop(old)
                    for module in news:
                        config[module] = suite

    return extra_modules

def get_extra_hardware_modules_dict(is_public, abi):
    return CONFIG.get('HARDWAREONLY_EXTRA_MODULES', {})


def get_extra_artifacts(modules):
    artifacts = []
    for module in modules:
        if module in CONFIG['EXTRA_ARTIFACTS']:
            artifacts += CONFIG['EXTRA_ARTIFACTS'][module]
    return artifacts


def get_extra_artifacts_host(modules):
    if not 'EXTRA_ARTIFACTS_HOST' in CONFIG:
        return

    artifacts = []
    for module in modules:
        if module in CONFIG['EXTRA_ARTIFACTS_HOST']:
            artifacts += CONFIG['EXTRA_ARTIFACTS_HOST'][module]
    return artifacts


def calculate_timeout(modules, suites):
    """Calculation for timeout of tradefed run.

    Timeout is at least one hour, except if part of BVT_ARC.
    Notice these do get adjusted dynamically by number of ABIs on the DUT.
    """
    if 'suite:bvt-arc' in suites:
        return int(3600 * CONFIG['BVT_TIMEOUT'])
    if CONFIG.get('QUAL_SUITE_NAMES') and \
            CONFIG.get('QUAL_TIMEOUT') and \
            ((set(CONFIG['QUAL_SUITE_NAMES']) & set(suites)) and \
            not (_COLLECT in modules or _PUBLIC_COLLECT in modules)):
        return int(3600 * CONFIG['QUAL_TIMEOUT'])

    timeout = 0
    # First module gets 1h (standard), all other half hour extra (heuristic).
    default_timeout = int(3600 * CONFIG['CTS_TIMEOUT_DEFAULT'])
    delta = default_timeout
    for module in modules:
        if module in CONFIG['CTS_TIMEOUT']:
            # Modules that run very long are encoded here.
            timeout += int(3600 * CONFIG['CTS_TIMEOUT'][module])
        elif module.startswith('CtsDeqpTestCases.dEQP-VK.'):
            # TODO: Optimize this temporary hack by reducing this value or
            # setting appropriate values for each test if possible.
            timeout = max(timeout, int(3600 * 12))
        elif 'Jvmti' in module:
            # We have too many of these modules and they run fast.
            timeout += 300
        else:
            timeout += delta
            delta = default_timeout // 2
    return timeout


def needs_push_media(modules):
    """Oracle to determine if to push several GB of media files to DUT."""
    if modules.intersection(set(CONFIG['NEEDS_PUSH_MEDIA'])):
        return True
    return False


def needs_cts_helpers(modules):
    """Oracle to determine if CTS helpers should be downloaded from DUT."""
    if 'NEEDS_CTS_HELPERS' not in CONFIG:
        return False
    if modules.intersection(set(CONFIG['NEEDS_CTS_HELPERS'])):
        return True
    return False


def enable_default_apps(modules):
    """Oracle to determine if to enable default apps (eg. Files.app)."""
    if modules.intersection(set(CONFIG['ENABLE_DEFAULT_APPS'])):
        return True
    return False


def is_parameterized_module(module):
    """Determines if the given module is a parameterized module."""
    return '[' in module


def get_controlfile_content(combined,
                            modules,
                            abi,
                            revision,
                            build,
                            uri,
                            suites=None,
                            is_public=False,
                            is_latest=False,
                            abi_bits=None,
                            led_provision=None,
                            camera_facing=None,
                            hardware_suite=False,
                            whole_module_set=None):
    """Returns the text inside of a control file.

    @param combined: name to use for this combination of modules.
    @param modules: set of CTS modules which will be tested in the control
                   file. If 'all' is specified, the control file will run
                   all the tests.
    """
    # We tag results with full revision now to get result directories containing
    # the revision. This fits stainless/ better.
    tag = '%s' % get_extension(combined, abi, revision, is_public,
                               led_provision, camera_facing, hardware_suite, abi_bits)
    # For test_that the NAME should be the same as for the control file name.
    # We could try some trickery here to get shorter extensions for a default
    # suite/ARM. But with the monthly uprevs this will quickly get confusing.
    name = '%s.%s' % (CONFIG['TEST_NAME'], tag)
    if not suites:
        suites = get_suites(modules, abi, is_public, camera_facing, hardware_suite)
    attributes = ', '.join(suites)
    uri = 'LATEST' if is_latest else (None if is_public else uri)
    target_module = None
    if (combined not in get_collect_modules(is_public) and combined != _ALL):
        target_module = combined
    for target, config in get_extra_modules_dict(is_public, abi).items():
        if combined in config.keys():
            target_module = target
    abi_to_run = {
            ("arm", 32): 'armeabi-v7a',
            ("arm", 64): 'arm64-v8a',
            ("x86", 32): 'x86',
            ("x86", 64): 'x86_64'
    }.get((abi, abi_bits), None)
    subplan = None
    if _CTSHARDWARE_COLLECT in modules or _PUBLIC_CTSHARDWARE_COLLECT in modules:
        subplan = 'cts-hardware'
    return _CONTROLFILE_TEMPLATE.render(
            year=CONFIG['COPYRIGHT_YEAR'],
            name=name,
            base_name=CONFIG['TEST_NAME'],
            test_func_name=CONFIG['CONTROLFILE_TEST_FUNCTION_NAME'],
            attributes=attributes,
            dependencies=get_dependencies(modules, abi, is_public,
                                          led_provision, camera_facing),
            extra_artifacts=get_extra_artifacts(modules),
            extra_artifacts_host=get_extra_artifacts_host(modules),
            job_retries=get_job_retries(modules, is_public, suites),
            max_result_size_kb=get_max_result_size_kb(modules, is_public),
            revision=revision,
            build=build,
            abi=abi,
            needs_push_media=needs_push_media(modules),
            needs_cts_helpers=needs_cts_helpers(modules),
            enable_default_apps=enable_default_apps(modules),
            tag=tag,
            uri=uri,
            DOC=get_doc(modules, abi, is_public),
            servo_support_needed=servo_support_needed(modules, is_public),
            max_retries=get_max_retries(modules, abi, suites, is_public),
            timeout=calculate_timeout(modules, suites),
            run_template=get_run_template(modules,
                                          is_public,
                                          abi_to_run=CONFIG.get(
                                                  'REPRESENTATIVE_ABI',
                                                  {}).get(abi, abi_to_run),
                                          whole_module_set=whole_module_set,
                                          is_hardware=hardware_suite),
            retry_template=get_retry_template(modules, is_public),
            target_module=target_module,
            target_plan=subplan,
            test_length=get_test_length(modules),
            priority=get_test_priority(modules, is_public),
            extra_args=get_extra_args(modules, is_public),
            authkey=get_authkey(is_public),
            sync_count=get_sync_count(modules, abi, is_public),
            camera_facing=camera_facing)


def get_tradefed_data(path, is_public, abi):
    """Queries tradefed to provide us with a list of modules.

    Notice that the parsing gets broken at times with major new CTS drops.
    """
    tradefed = os.path.join(path, CONFIG['TRADEFED_EXECUTABLE_PATH'])
    # Python's zipfle module does not set the executable bit.
    # tradefed and java command need chmod +x.
    os.chmod(tradefed, os.stat(tradefed).st_mode | stat.S_IEXEC)
    java = CONFIG.get('JAVA_EXECUTABLE_PATH', None)
    if java:
        java = os.path.join(path, java)
        os.chmod(java, os.stat(java).st_mode | stat.S_IEXEC)
    cmd_list = [tradefed, 'list', 'modules']
    logging.info('Calling tradefed for list of modules.')
    with open(os.devnull, 'w') as devnull:
        # tradefed terminates itself if stdin is not a tty.
        tradefed_output = subprocess.check_output(cmd_list,
                                                  stdin=devnull).decode()

    _ABI_PREFIXES = ('arm', 'x86')
    _MODULE_PREFIXES = ('Cts', 'cts-', 'signed-Cts', 'vm-tests-tf', 'Sts')

    # Some CTS/GTS versions insert extra linebreaks due to a bug b/196912758.
    # Below is a heurestical workaround for the situation.
    lines = []
    prev_line_abi_prefixed = False
    for line in tradefed_output.splitlines():
        abi_prefixed = line.startswith(_ABI_PREFIXES)
        end_of_modules = (len(line) == 0 or 'Saved log to' in line)
        if prev_line_abi_prefixed and not end_of_modules and not abi_prefixed:
            # Merge a line immediately following 'abi XtsModuleName'
            lines[-1] += line
        else:
            lines.append(line)
        prev_line_abi_prefixed = abi_prefixed

    modules = set()
    build = '<unknown>'
    revision = None
    for line in lines:
        # Android Compatibility Test Suite 7.0 (3423912)
        if (line.startswith('Android Compatibility Test Suite ')
                    or line.startswith('Android Google ')
                    or line.startswith('Android Vendor Test Suite')
                    or line.startswith('Android Security Test Suite')):
            logging.info('Unpacking: %s.', line)
            build = get_tradefed_build(line)
            revision = get_tradefed_revision(line)
        elif line.startswith(_ABI_PREFIXES):
            # Newer CTS shows ABI-module pairs like "arm64-v8a CtsNetTestCases"
            line = line.split()[1]
            if line not in CONFIG.get('EXCLUDE_MODULES', []):
                modules.add(line)
        elif line.startswith(_MODULE_PREFIXES):
            # Old CTS plainly lists up the module name
            modules.add(line)
        elif line.isspace() or line.startswith('Use "help"'):
            pass
        else:
            logging.warning('Ignoring "%s"', line)

    if not modules:
        raise Exception("no modules found.")
    return list(modules), build, revision


def download(uri, destination):
    """Download |uri| to local |destination|.

       |destination| must be a file path (not a directory path)."""
    if uri.startswith('http://') or uri.startswith('https://'):
        subprocess.check_call(['wget', uri, '-O', destination])
    elif uri.startswith('gs://'):
        subprocess.check_call(['gsutil', 'cp', uri, destination])
    else:
        raise Exception


@contextlib.contextmanager
def pushd(d):
    """Defines pushd."""
    current = os.getcwd()
    os.chdir(d)
    try:
        yield
    finally:
        os.chdir(current)


def unzip(filename, destination):
    """Unzips a zip file to the destination directory."""
    with pushd(destination):
        # We are trusting Android to have a valid zip file for us.
        with zipfile.ZipFile(filename) as zf:
            zf.extractall()


def get_collect_modules(is_public, is_hardware=False):
    if is_public:
        if is_hardware:
            return set([_PUBLIC_CTSHARDWARE_COLLECT])
        return set([_PUBLIC_COLLECT])
    else:
        if is_hardware:
            return set([_CTSHARDWARE_COLLECT])
        return set([_COLLECT])


@contextlib.contextmanager
def TemporaryDirectory(prefix):
    """Poor man's python 3.2 import."""
    tmp = tempfile.mkdtemp(prefix=prefix)
    try:
        yield tmp
    finally:
        shutil.rmtree(tmp)


def get_word_pattern(m, l=1):
    """Return the first few words of the CamelCase module name.

    Break after l+1 CamelCase word.
    Example: CtsDebugTestCases -> CtsDebug.
    """
    s = re.findall('^[a-z-]+|[A-Z]*[^A-Z0-9]*', m)[0:l + 1]
    # Ignore Test or TestCases at the end as they don't add anything.
    if len(s) > l:
        if s[l].startswith('Test') or s[l].startswith('['):
            return ''.join(s[0:l])
        if s[l - 1] == 'Test' and s[l].startswith('Cases'):
            return ''.join(s[0:l - 1])
    return ''.join(s[0:l + 1])


def combine_modules_by_common_word(modules):
    """Returns a dictionary of (combined name, set of module) pairs.

    This gives a mild compaction of control files (from about 320 to 135).
    Example:
    'CtsVoice' -> ['CtsVoiceInteractionTestCases', 'CtsVoiceSettingsTestCases']
    """
    d = dict()
    # On first pass group modules with common first word together.
    for module in modules:
        pattern = get_word_pattern(module)
        v = d.get(pattern, [])
        v.append(module)
        v.sort()
        d[pattern] = v
    # Second pass extend names to maximum common prefix. This keeps control file
    # names identical if they contain only one module and less ambiguous if they
    # contain multiple modules.
    combined = dict()
    for key in sorted(d):
        # Instead if a one syllable prefix use longest common prefix of modules.
        prefix = os.path.commonprefix(d[key])
        # Beautification: strip Tests/TestCases from end of prefix, but only if
        # there is more than one module in the control file. This avoids
        # slightly strange combination of having CtsDpiTestCases1/2 inside of
        # CtsDpiTestCases (now just CtsDpi to make it clearer there are several
        # modules in this control file).
        if len(d[key]) > 1:
            prefix = re.sub('TestCases$', '', prefix)
            prefix = re.sub('Tests$', '', prefix)
        # Beautification: CtsMedia files run very long and are unstable. Give
        # each module its own control file, even though this heuristic would
        # lump them together.
        if prefix.startswith('CtsMedia'):
            # Separate each CtsMedia* modules, but group extra modules with
            # optional parametrization (ex: secondary_user, instant) together.
            prev = ' '
            for media in sorted(d[key]):
                if media.startswith(prev):
                    combined[prev].add(media)
                else:
                    prev = media
                    combined[media] = set([media])

        else:
            combined[prefix] = set(d[key])
    print('Reduced number of control files from %d to %d.' % (len(modules),
                                                              len(combined)))
    return combined


def combine_modules_by_bookmark(modules):
    """Return a manually curated list of name, module pairs.

    Ideally we split "all" into a dictionary of maybe 10-20 equal runtime parts.
    (Say 2-5 hours each.) But it is ok to run problematic modules alone.
    """
    d = dict()
    # Figure out sets of modules between bookmarks. Not optimum time complexity.
    for bookmark in CONFIG['QUAL_BOOKMARKS']:
        if modules:
            for module in sorted(modules):
                if module < bookmark:
                    v = d.get(bookmark, set())
                    v.add(module)
                    d[bookmark] = v
            # Remove processed modules.
            if bookmark in d:
                modules = modules - d[bookmark]
    # Clean up names.
    combined = dict()
    for key in sorted(d):
        v = sorted(d[key])
        # New name is first element '_-_' last element.
        # Notice there is a bug in $ADB_VENDOR_KEYS path name preventing
        # arbitrary characters.
        prefix = re.sub(r'\[[^]]*\]', '', v[0] + '_-_' + v[-1])
        combined[prefix] = set(v)
    return combined


def write_controlfile(name,
                      modules,
                      abi,
                      revision,
                      build,
                      uri,
                      suites,
                      is_public,
                      is_latest=False,
                      whole_module_set=None,
                      hardware_suite=False,
                      abi_bits=None):
    """Write a single control file."""
    filename = get_controlfile_name(name,
                                    abi,
                                    revision,
                                    is_public,
                                    abi_bits=abi_bits)
    content = get_controlfile_content(name,
                                      modules,
                                      abi,
                                      revision,
                                      build,
                                      uri,
                                      suites,
                                      is_public,
                                      is_latest,
                                      hardware_suite=hardware_suite,
                                      whole_module_set=whole_module_set,
                                      abi_bits=abi_bits)
    with open(filename, 'w') as f:
        f.write(content)


def write_moblab_controlfiles(modules, abi, revision, build, uri, is_public):
    """Write all control files for moblab.

    Nothing gets combined.

    Moblab uses one module per job. In some cases like Deqp which can run super
    long it even creates several jobs per module. Moblab can do this as it has
    less relative overhead spinning up jobs than the lab.
    """
    for module in modules:
        # No need to generate control files with extra suffix, since --module
        # option will cover variants with optional parameters.
        if is_parameterized_module(module):
            continue
        if module in CONFIG.get('PUBLIC_SPLIT_BY_BITS_MODULES', []):
            # If |abi| is predefined (like CTS), splits the modules by
            # 32/64-bits. If not (like GTS) generate both arm and x86 jobs.
            for abi_arch in [abi] if abi else ['arm', 'x86']:
                for abi_bits in [32, 64]:
                    write_controlfile(module,
                                      set([module]),
                                      abi_arch,
                                      revision,
                                      build,
                                      uri,
                                      None,
                                      is_public,
                                      abi_bits=abi_bits)
        else:
            write_controlfile(module, set([module]), abi, revision, build, uri,
                              None, is_public)


def write_regression_controlfiles(modules, abi, revision, build, uri,
                                  is_public, is_latest):
    """Write all control files for stainless/ToT regression lab coverage.

    Regression coverage on tot currently relies heavily on watching stainless
    dashboard and sponge. So instead of running everything in a single run
    we split CTS into many jobs. It used to be one job per module, but that
    became too much in P (more than 300 per ABI). Instead we combine modules
    with similar names and run these in the same job (alphabetically).
    """

    if CONFIG.get('SINGLE_CONTROL_FILE'):
        module_set = set(modules)
        write_controlfile('all',
                          module_set,
                          abi,
                          revision,
                          build,
                          uri,
                          None,
                          is_public,
                          is_latest,
                          whole_module_set=module_set)
    else:
        combined = combine_modules_by_common_word(set(modules))
        for key in combined:
            if combined[key] & set(CONFIG.get('SPLIT_BY_BITS_MODULES', [])):
                # If |abi| is predefined (like CTS), splits the modules by
                # 32/64-bits. If not (like GTS) generate both arm and x86 jobs.
                for abi_arch in [abi] if abi else ['arm', 'x86']:
                    for abi_bits in [32, 64]:
                        write_controlfile(key,
                                          combined[key],
                                          abi_arch,
                                          revision,
                                          build,
                                          uri,
                                          None,
                                          is_public,
                                          is_latest,
                                          abi_bits=abi_bits)
            else:
                write_controlfile(key, combined[key], abi, revision, build,
                                  uri, None, is_public, is_latest)


def write_qualification_controlfiles(modules, abi, revision, build, uri,
                                     is_public, is_latest):
    """Write all control files to run "all" tests for qualification.

    Qualification was performed on N by running all tests using tradefed
    sharding (specifying SYNC_COUNT=2) in the control files. In skylab
    this is currently not implemented, so we fall back to autotest sharding
    all CTS tests into 10-20 hand chosen shards.
    """
    combined = combine_modules_by_bookmark(set(modules))
    for key in combined:
        if combined[key] & set(CONFIG.get('SPLIT_BY_BITS_MODULES', [])):
            # If |abi| is predefined (like CTS), splits the modules by
            # 32/64-bits. If not (like GTS) generate both arm and x86 jobs.
            for abi_arch in [abi] if abi else ['arm', 'x86']:
                for abi_bits in [32, 64]:
                    write_controlfile('all.' + key,
                                      combined[key],
                                      abi_arch,
                                      revision,
                                      build,
                                      uri,
                                      CONFIG.get('QUAL_SUITE_NAMES'),
                                      is_public,
                                      is_latest,
                                      abi_bits=abi_bits)
        else:
            write_controlfile('all.' + key, combined[key], abi,
                              revision, build, uri,
                              CONFIG.get('QUAL_SUITE_NAMES'), is_public,
                              is_latest)


def write_qualification_and_regression_controlfile(modules, abi, revision,
                                                   build, uri, is_public,
                                                   is_latest):
    """Write a control file to run "all" tests for qualification and regression.
    """
    # For cts-instant, qualication control files are expected to cover
    # regressions as well. Hence the 'suite:arc-cts' is added.
    suites = ['suite:arc-cts', 'suite:arc-cts-qual']
    module_set = set(modules)
    combined = combine_modules_by_bookmark(module_set)
    for key in combined:
        write_controlfile('all.' + key,
                          combined[key],
                          abi,
                          revision,
                          build,
                          uri,
                          suites,
                          is_public,
                          is_latest,
                          whole_module_set=module_set)


def write_collect_controlfiles(_modules, abi, revision, build, uri, is_public,
                               is_latest, is_hardware=False):
    """Write all control files for test collection used as reference to

    compute completeness (missing tests) on the CTS dashboard.
    """
    if is_public:
        if is_hardware:
            suites = [CONFIG['MOBLAB_HARDWARE_SUITE_NAME']]
        else:
            suites = [CONFIG['MOBLAB_SUITE_NAME']]
    else:
        if is_hardware:
            suites = [CONFIG['HARDWARE_SUITE_NAME']]
        else:
            suites = CONFIG['INTERNAL_SUITE_NAMES'] \
                   + CONFIG.get('QUAL_SUITE_NAMES', [])
    for module in get_collect_modules(is_public, is_hardware=is_hardware):
        write_controlfile(module,
                          set([module]),
                          abi,
                          revision,
                          build,
                          uri,
                          suites,
                          is_public,
                          is_latest,
                          hardware_suite=is_hardware)


def write_extra_controlfiles(_modules, abi, revision, build, uri, is_public,
                             is_latest):
    """Write all extra control files as specified in config.

    This is used by moblab to load balance large modules like Deqp, as well as
    making custom modules such as WM presubmit. A similar approach was also used
    during bringup of grunt to split media tests.
    """
    for module, config in get_extra_modules_dict(is_public, abi).items():
        for submodule, suites in config.items():
            write_controlfile(submodule, set([submodule]), abi, revision,
                              build, uri, suites, is_public,
                              is_latest)

def write_hardwaresuite_controlfiles(abi, revision, build, uri, is_public,
                                     is_latest):
    """Control files for Build variant hardware only tests."""
    cts_hardware_modules = set(CONFIG.get('HARDWARE_MODULES', []))
    for module in cts_hardware_modules:
        name = get_controlfile_name(module, abi, revision, is_public,
                                    hardware_suite=True)

        content = get_controlfile_content(module, set([module]), abi, revision,
                                    build, uri, None, is_public, is_latest,
                                    hardware_suite=True)

        with open(name, 'w') as f:
            f.write(content)

    for module, config in get_extra_hardware_modules_dict(is_public, abi).items():
        for submodule, suites in config.items():
            name = get_controlfile_name(submodule, abi, revision, is_public,
                                        hardware_suite=True)
            content = get_controlfile_content(submodule,
                                              set([submodule]),
                                              abi,
                                              revision,
                                              build,
                                              uri,
                                              None,
                                              is_public,
                                              is_latest,
                                              hardware_suite=True)
            with open(name, 'w') as f:
                f.write(content)


def write_extra_camera_controlfiles(abi, revision, build, uri, is_public,
                                    is_latest):
    """Control files for CtsCameraTestCases.camerabox.*"""
    module = 'CtsCameraTestCases'
    for facing in ['back', 'front']:
        led_provision = 'noled'
        name = get_controlfile_name(module, abi, revision, is_public,
                                    led_provision, facing)
        content = get_controlfile_content(module,
                                          set([module]),
                                          abi,
                                          revision,
                                          build,
                                          uri,
                                          None,
                                          is_public,
                                          is_latest,
                                          led_provision=led_provision,
                                          camera_facing=facing)
        with open(name, 'w') as f:
            f.write(content)


def run(uris, is_public, is_latest, cache_dir):
    """Downloads each bundle in |uris| and generates control files for each

    module as reported to us by tradefed.
    """
    for uri in uris:
        abi = get_bundle_abi(uri)
        # Get tradefed data by downloading & unzipping the files
        with TemporaryDirectory(prefix='cts-android_') as tmp:
            if cache_dir is not None:
                assert(os.path.isdir(cache_dir))
                bundle = os.path.join(cache_dir, os.path.basename(uri))
                if not os.path.exists(bundle):
                    logging.info('Downloading to %s.', cache_dir)
                    download(uri, bundle)
            else:
                bundle = os.path.join(tmp, os.path.basename(uri))
                logging.info('Downloading to %s.', tmp)
                download(uri, bundle)
            logging.info('Extracting %s.', bundle)
            unzip(bundle, tmp)
            modules, build, revision = get_tradefed_data(tmp, is_public, abi)
            if not revision:
                raise Exception('Could not determine revision.')

            logging.info('Writing all control files.')
            if is_public:
                write_moblab_controlfiles(modules, abi, revision, build, uri,
                                          is_public)
            else:
                if CONFIG['CONTROLFILE_WRITE_SIMPLE_QUAL_AND_REGRESS']:
                    write_qualification_and_regression_controlfile(
                            modules, abi, revision, build, uri, is_public,
                            is_latest)
                else:
                    write_regression_controlfiles(modules, abi, revision,
                                                  build, uri, is_public,
                                                  is_latest)
                    write_qualification_controlfiles(modules, abi, revision,
                                                     build, uri, is_public,
                                                     is_latest)

                if CONFIG['CONTROLFILE_WRITE_CAMERA']:
                    write_extra_camera_controlfiles(abi, revision, build, uri,
                                                    is_public, is_latest)

            if CONFIG.get('CONTROLFILE_WRITE_COLLECT', True):
                write_collect_controlfiles(modules, abi, revision, build, uri,
                                           is_public, is_latest,
                                           is_hardware=False)
                if 'HARDWARE_MODULES' in CONFIG:
                    write_collect_controlfiles(modules,
                                               abi,
                                               revision,
                                               build,
                                               uri,
                                               is_public,
                                               is_latest,
                                               is_hardware=True)

            if CONFIG['CONTROLFILE_WRITE_EXTRA']:
                write_extra_controlfiles(None, abi, revision, build, uri,
                                         is_public, is_latest)

            write_hardwaresuite_controlfiles(abi, revision, build, uri,
                                             is_public, is_latest)


def main(config):
    """ Entry method of generator """

    global CONFIG
    CONFIG = config

    logging.basicConfig(level=logging.INFO)
    parser = argparse.ArgumentParser(
        description='Create control files for a CTS bundle on GS.',
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument(
            'uris',
            nargs='+',
            help='List of Google Storage URIs to CTS bundles. Example:\n'
            'gs://chromeos-arc-images/cts/bundle/P/'
            'android-cts-9.0_r9-linux_x86-x86.zip')
    parser.add_argument(
            '--is_public',
            dest='is_public',
            default=False,
            action='store_true',
            help='Generate the public control files for CTS, default generate'
            ' the internal control files')
    parser.add_argument(
            '--is_latest',
            dest='is_latest',
            default=False,
            action='store_true',
            help='Generate the control files for CTS from the latest CTS bundle'
            ' stored in the internal storage')
    parser.add_argument(
            '--cache_dir',
            dest='cache_dir',
            default=None,
            action='store',
            help='Cache directory for downloaded bundle file. Uses the cached '
            'bundle file if exists, or caches a downloaded file to this '
            'directory if not.')
    args = parser.parse_args()
    run(args.uris, args.is_public, args.is_latest, args.cache_dir)
