#!/usr/bin/env python
# Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

import apk_masseur
import apk_utils
import golem
import gradle
import jdk
import json
import os
import optparse
import shutil
import subprocess
import sys
import time
import utils
import zipfile
from xml.dom import minidom

import as_utils
import update_prebuilds_in_android

SHRINKERS = ['r8', 'r8-full', 'r8-nolib', 'r8-nolib-full', 'pg']
WORKING_DIR = os.path.join(utils.BUILD, 'opensource_apps')

if ('R8_BENCHMARK_DIR' in os.environ
    and os.path.isdir(os.environ['R8_BENCHMARK_DIR'])):
  WORKING_DIR = os.environ['R8_BENCHMARK_DIR']

class Repo(object):
  def __init__(self, fields):
    self.__dict__ = fields

    # If there is only one app in this repository, then give the app the same
    # name as the repository, if it does not already have one.
    if len(self.apps) == 1:
      app = self.apps[0]
      if not app.name:
        app.name = self.name

class App(object):
  def __init__(self, fields):
    module = fields.get('module', 'app')
    defaults = {
      'archives_base_name': module,
      'build_dir': 'build',
      'compile_sdk': None,
      'dir': '.',
      'flavor': None,
      'has_instrumentation_tests': False,
      'main_dex_rules': None,
      'module': module,
      'min_sdk': None,
      'name': None,
      'releaseTarget': None,
      'signed_apk_name': None,
      'skip': False
    }
    self.__dict__ = dict(defaults.items() + fields.items())

# For running on Golem all third-party repositories are bundled as an x20-
# dependency and then copied to WORKING_DIR. To update the app-bundle use
# 'run_on_as_app_x20_packager.py'.
APP_REPOSITORIES = [
  # ...
  # Repo({
  #     'name': ...,
  #     'url': ...,
  #     'revision': ...,
  #     'apps': [
  #         {
  #             'id': ...,
  #             'dir': ...,
  #             'module': ... (default app)
  #             'name': ...,
  #             'archives_base_name': ... (default same as module)
  #             'flavor': ... (default no flavor)
  #             'releaseTarget': ... (default <module>:assemble<flavor>Release
  #         },
  #         ...
  #     ]
  # }),
  # ...
  Repo({
      'name': 'android-suite',
      'url': 'https://github.com/christofferqa/android-suite',
      'revision': '46c96f214711cf6cdcb72cc0c94520ef418e3739',
      'apps': [
          App({
              'id': 'com.numix.calculator',
              'dir': 'Calculator',
              'name': 'numix-calculator',
              'has_instrumentation_tests': True
          })
      ]
  }),
  Repo({
      'name': 'AnExplorer',
      'url': 'https://github.com/christofferqa/AnExplorer',
      'revision': '365927477b8eab4052a1882d5e358057ae3dee4d',
      'apps': [
          App({
              'id': 'dev.dworks.apps.anexplorer.pro',
              'flavor': 'googleMobilePro',
              'signed_apk_name': 'AnExplorer-googleMobileProRelease-4.0.3.apk',
              'min_sdk': 17
          })
      ]
  }),
  Repo({
      'name': 'AntennaPod',
      'url': 'https://github.com/christofferqa/AntennaPod.git',
      'revision': '77e94f4783a16abe9cc5b78dc2d2b2b1867d8c06',
      'apps': [
          App({
              'id': 'de.danoeh.antennapod',
              'flavor': 'play',
              'min_sdk': 14,
              'compile_sdk': 26
          })
      ]
  }),
  Repo({
    'name': 'applymapping',
    'url': 'https://github.com/mkj-gram/applymapping',
    'revision': 'e3ae14b8c16fa4718e5dea8f7ad00937701b3c48',
    'apps': [
      App({
        'id': 'com.example.applymapping',
        'has_instrumentation_tests': True
      })
    ]
  }),
  Repo({
      'name': 'apps-android-wikipedia',
      'url': 'https://github.com/christofferqa/apps-android-wikipedia',
      'revision': '686e8aa5682af8e6a905054b935dd2daa57e63ee',
      'apps': [
          App({
              'id': 'org.wikipedia',
              'flavor': 'prod',
              'signed_apk_name': 'app-prod-universal-release.apk'
          })
      ]
  }),
  Repo({
      'name': 'chanu',
      'url': 'https://github.com/mkj-gram/chanu.git',
      'revision': '6e53458f167b6d78398da60c20fd0da01a232617',
      'apps': [
          App({
              'id': 'com.chanapps.four.activity'
          })
      ]
  }),
  Repo({
      'name': 'friendlyeats-android',
      'url': 'https://github.com/christofferqa/friendlyeats-android.git',
      'revision': '10091fa0ec37da12e66286559ad1b6098976b07b',
      'apps': [
          App({
              'id': 'com.google.firebase.example.fireeats'
          })
      ]
  }),
  Repo({
      'name': 'Instabug-Android',
      'url': 'https://github.com/christofferqa/Instabug-Android.git',
      'revision': 'b8df78c96630a6537fbc07787b4990afc030cc0f',
      'apps': [
          App({
             'id': 'com.example.instabug'
          })
      ]
  }),
  Repo({
      'name': 'KISS',
      'url': 'https://github.com/christofferqa/KISS',
      'revision': '093da9ee0512e67192f62951c45a07a616fc3224',
      'apps': [
          App({
              'id': 'fr.neamar.kiss'
          })
      ]
  }),
  Repo({
      'name': 'materialistic',
      'url': 'https://github.com/christofferqa/materialistic',
      'revision': '2b2b2ee25ce9e672d5aab1dc90a354af1522b1d9',
      'apps': [
          App({
              'id': 'io.github.hidroh.materialistic'
          })
      ]
  }),
  Repo({
      'name': 'Minimal-Todo',
      'url': 'https://github.com/christofferqa/Minimal-Todo',
      'revision': '9d8c73746762cd376b718858ec1e8783ca07ba7c',
      'apps': [
          App({
              'id': 'com.avjindersinghsekhon.minimaltodo'
          })
      ]
  }),
  Repo({
      'name': 'muzei',
      'url': 'https://github.com/sgjesse/muzei.git',
      'revision': 'e7e4ab1039bb18009254b94831b17676bc3b8bc1',
      'apps': [
          App({
              'id': 'net.nurik.roman.muzei',
              'module': 'main',
              'archives_base_name': 'muzei',
              'compile_sdk': 28
          })
      ]
  }),
  Repo({
      'name': 'NewPipe',
      'url': 'https://github.com/christofferqa/NewPipe',
      'revision': 'ed543099c7823be00f15d9340f94bdb7cb37d1e6',
      'apps': [
          App({
              'id': 'org.schabi.newpipe'
          })
      ]
  }),
  Repo({
      'name': 'rover-android',
      'url': 'https://github.com/mkj-gram/rover-android.git',
      'revision': 'a5e155a1ed7d19b1cecd9a7b075e2852623a06bf',
      'apps': [
          App({
              'id': 'io.rover.app.debug',
              'module': 'debug-app'
          })
      ]
  }),
  Repo({
      'name': 'Signal-Android',
      'url': 'https://github.com/mkj-gram/Signal-Android.git',
      'revision': 'cd542cab9bf860e71504ecb1caaf0a8476ba3989',
      'apps': [
          App({
              'id': 'org.thoughtcrime.securesms',
              'module': '',
              'flavor': 'play',
              'main_dex_rules': 'multidex-config.pro',
              'signed_apk_name': 'Signal-play-release-4.32.7.apk'
          })
      ]
  }),
  Repo({
      'name': 'Simple-Calendar',
      'url': 'https://github.com/christofferqa/Simple-Calendar',
      'revision': '82dad8c203eea5a0f0ddb513506d8f1de986ef2b',
      'apps': [
          App({
              'id': 'com.simplemobiletools.calendar.pro',
              'signed_apk_name': 'calendar-release.apk'
          })
      ]
  }),
  Repo({
      'name': 'sqldelight',
      'url': 'https://github.com/christofferqa/sqldelight.git',
      'revision': '2e67a1126b6df05e4119d1e3a432fde51d76cdc8',
      'apps': [
          App({
              'id': 'com.example.sqldelight.hockey',
              'module': 'sample/android',
              'archives_base_name': 'android',
              'min_sdk': 14,
              'compile_sdk': 28
          })
      ]
  }),
  Repo({
      'name': 'tachiyomi',
      'url': 'https://github.com/sgjesse/tachiyomi.git',
      'revision': 'b15d2fe16864645055af6a745a62cc5566629798',
      'apps': [
          App({
              'id': 'eu.kanade.tachiyomi',
              'flavor': 'dev',
              'min_sdk': 16
          })
      ]
  }),
  Repo({
      'name': 'tivi',
      'url': 'https://github.com/sgjesse/tivi.git',
      'revision': '25c52e3593e7c98da4e537b49b29f6f67f88754d',
      'apps': [
          App({
              'id': 'app.tivi',
              'min_sdk': 23,
              'compile_sdk': 28
          })
      ]
  }),
  Repo({
      'name': 'Tusky',
      'url': 'https://github.com/mkj-gram/Tusky.git',
      'revision': 'e7fbd190fb53bf9fde72253b816920cb6fe34518',
      'apps': [
          App({
              'id': 'com.keylesspalace.tusky',
              'flavor': 'blue'
          })
      ]
  }),
  Repo({
      'name': 'Vungle-Android-SDK',
      'url': 'https://github.com/mkj-gram/Vungle-Android-SDK.git',
      'revision': '138d3f18c027b61b195c98911f1c5ab7d87ad18b',
      'apps': [
          App({
              'id': 'com.publisher.vungle.sample'
          })
      ]
  })
]

def GetAllApps():
  apps = []
  for repo in APP_REPOSITORIES:
    for app in repo.apps:
      apps.append((app, repo))
  return apps

def GetAllAppNames():
  return [app.name for (app, repo) in GetAllApps()]

def GetAppWithName(query):
  for (app, repo) in GetAllApps():
    if app.name == query:
      return (app, repo)
  assert False

def ComputeSizeOfDexFilesInApk(apk):
  dex_size = 0
  z = zipfile.ZipFile(apk, 'r')
  for filename in z.namelist():
    if filename.endswith('.dex'):
      dex_size += z.getinfo(filename).file_size
  return dex_size

def ExtractMarker(apk, temp_dir, options):
  r8_jar = os.path.join(temp_dir, 'r8.jar')
  r8lib_jar = os.path.join(temp_dir, 'r8lib.jar')

  # Use the copy of r8.jar or r8lib.jar if one is there.
  if os.path.isfile(r8_jar):
    cmd = [jdk.GetJavaExecutable(), '-ea', '-jar', r8_jar, 'extractmarker', apk]
  elif os.path.isfile(r8lib_jar):
    cmd = [jdk.GetJavaExecutable(), '-ea', '-cp', r8lib_jar,
        'com.android.tools.r8.ExtractMarker', apk]
  else:
    script = os.path.join(utils.TOOLS_DIR, 'extractmarker.py')
    cmd = ['python', script, apk]

  utils.PrintCmd(cmd, quiet=options.quiet)
  stdout = subprocess.check_output(cmd)

  # Return the last line.
  lines = stdout.strip().splitlines()
  assert len(lines) >= 1
  return lines[-1]

def CheckIsBuiltWithExpectedR8(apk, temp_dir, shrinker, options):
  marker = ExtractMarker(apk, temp_dir, options)
  expected_version = (
      options.version
      if options.version
      else utils.getR8Version(
          os.path.join(
              temp_dir,
              'r8lib.jar' if IsMinifiedR8(shrinker) else 'r8.jar')))
  if marker.startswith('~~R8'):
    actual_version = json.loads(marker[4:]).get('version')
    if actual_version == expected_version:
      return True
  raise Exception(
      'Expected APK to be built with R8 version {} (was: {})'.format(
          expected_version, marker))

def isR8(shrinker):
  return 'r8' in shrinker

def isR8FullMode(shrinker):
  return shrinker == 'r8-full' or shrinker == 'r8-nolib-full'

def IsMinifiedR8(shrinker):
  return 'nolib' not in shrinker

def IsTrackedByGit(file):
  return subprocess.check_output(['git', 'ls-files', file]).strip() != ''

def GitClone(repo, checkout_dir, quiet):
  result = subprocess.check_output(
      ['git', 'clone', repo.url, checkout_dir]).strip()
  head_rev = utils.get_HEAD_sha1_for_checkout(checkout_dir)
  if repo.revision == head_rev:
    return result
  warn('Target revision is not head in {}.'.format(checkout_dir))
  with utils.ChangedWorkingDirectory(checkout_dir, quiet=quiet):
    subprocess.check_output(['git', 'reset', '--hard', repo.revision])
  return result

def GitCheckout(file):
  return subprocess.check_output(['git', 'checkout', file]).strip()

def InstallApkOnEmulator(apk_dest, options):
  cmd = ['adb', '-s', options.emulator_id, 'install', '-r', '-d', apk_dest]
  if options.quiet:
    with open(os.devnull, 'w') as devnull:
      subprocess.check_call(cmd, stdout=devnull)
  else:
    subprocess.check_call(cmd)

def PercentageDiffAsString(before, after):
  if after < before:
    return '-' + str(round((1.0 - after / before) * 100)) + '%'
  else:
    return '+' + str(round((after - before) / before * 100)) + '%'

def UninstallApkOnEmulator(app, options):
  process = subprocess.Popen(
      ['adb', '-s', options.emulator_id, 'uninstall', app.id],
      stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  stdout, stderr = process.communicate()

  if stdout.strip() == 'Success':
    # Successfully uninstalled
    return

  if 'Unknown package: {}'.format(app.id) in stderr:
    # Application not installed
    return

  raise Exception(
      'Unexpected result from `adb uninstall {}\nStdout: {}\nStderr: {}'.format(
          app.id, stdout, stderr))

def WaitForEmulator(options):
  stdout = subprocess.check_output(['adb', 'devices'])
  if '{}\tdevice'.format(options.emulator_id) in stdout:
    return True

  print('Emulator \'{}\' not connected; waiting for connection'.format(
      options.emulator_id))

  time_waited = 0
  while True:
    time.sleep(10)
    time_waited += 10
    stdout = subprocess.check_output(['adb', 'devices'])
    if '{}\tdevice'.format(options.emulator_id) not in stdout:
      print('... still waiting for connection')
      if time_waited >= 5 * 60:
        return False
    else:
      return True

def GetResultsForApp(app, repo, options, temp_dir):
  # Checkout and build in the build directory.
  repo_name = repo.name
  repo_checkout_dir = os.path.join(WORKING_DIR, repo_name)

  result = {}

  if not os.path.exists(repo_checkout_dir) and not options.golem:
    with utils.ChangedWorkingDirectory(WORKING_DIR, quiet=options.quiet):
      GitClone(repo, repo_checkout_dir, options.quiet)

  checkout_rev = utils.get_HEAD_sha1_for_checkout(repo_checkout_dir)
  if repo.revision != checkout_rev:
    msg = 'Checkout is not target revision for {} in {}.'.format(
        app.name, repo_checkout_dir)
    if options.ignore_versions:
      warn(msg)
    else:
      raise Exception(msg)

  result['status'] = 'success'

  app_checkout_dir = os.path.join(repo_checkout_dir, app.dir)
  result_per_shrinker = BuildAppWithSelectedShrinkers(
      app, repo, options, app_checkout_dir, temp_dir)
  for shrinker, shrinker_result in result_per_shrinker.iteritems():
    result[shrinker] = shrinker_result

  return result

def BuildAppWithSelectedShrinkers(
    app, repo, options, checkout_dir, temp_dir):
  result_per_shrinker = {}

  with utils.ChangedWorkingDirectory(checkout_dir, quiet=options.quiet):
    for shrinker in options.shrinker:
      apk_dest = None

      result = {}
      try:
        out_dir = os.path.join(checkout_dir, 'out', shrinker)
        (apk_dest, profile_dest_dir, proguard_config_file) = \
            BuildAppWithShrinker(
                app, repo, shrinker, checkout_dir, out_dir, temp_dir,
                options)
        dex_size = ComputeSizeOfDexFilesInApk(apk_dest)
        result['apk_dest'] = apk_dest
        result['build_status'] = 'success'
        result['dex_size'] = dex_size
        result['profile_dest_dir'] = profile_dest_dir

        profile = as_utils.ParseProfileReport(profile_dest_dir)
        result['profile'] = {
            task_name:duration for task_name, duration in profile.iteritems()
            if as_utils.IsGradleCompilerTask(task_name, shrinker)}
      except Exception as e:
        warn('Failed to build {} with {}'.format(app.name, shrinker))
        if e:
          print('Error: ' + str(e))
        result['build_status'] = 'failed'

      if result.get('build_status') == 'success':
        if options.monkey:
          result['monkey_status'] = 'success' if RunMonkey(
              app, options, apk_dest) else 'failed'

        if 'r8' in shrinker and options.r8_compilation_steps > 1:
          result['recompilation_results'] = \
              ComputeRecompilationResults(
                  app, repo, options, checkout_dir, temp_dir, shrinker,
                  proguard_config_file)

        if options.run_tests and app.has_instrumentation_tests:
          result['instrumentation_test_results'] = \
              ComputeInstrumentationTestResults(
                  app, options, checkout_dir, out_dir, shrinker)

      result_per_shrinker[shrinker] = result

  if len(options.apps) > 1:
    print('')
    LogResultsForApp(app, result_per_shrinker, options)
    print('')

  return result_per_shrinker

def BuildAppWithShrinker(
    app, repo, shrinker, checkout_dir, out_dir, temp_dir, options,
    keepRuleSynthesisForRecompilation=False):
  print('Building {} with {}{}'.format(
      app.name,
      shrinker,
      ' for recompilation' if keepRuleSynthesisForRecompilation else ''))

  # Add settings.gradle file if it is not present to prevent gradle from finding
  # the settings.gradle file in the r8 root when apps are placed under
  # $R8/build.
  as_utils.add_settings_gradle(checkout_dir, app.name)

  # Add 'r8.jar' to top-level build.gradle.
  as_utils.add_r8_dependency(checkout_dir, temp_dir, IsMinifiedR8(shrinker))

  archives_base_name = app.archives_base_name

  if not os.path.exists(out_dir):
    os.makedirs(out_dir)

  # Set -printconfiguration in Proguard rules.
  proguard_config_dest = os.path.abspath(
      os.path.join(out_dir, 'proguard-rules.pro'))
  as_utils.SetPrintConfigurationDirective(
      app, checkout_dir, proguard_config_dest)

  env_vars = {}
  env_vars['ANDROID_HOME'] = utils.getAndroidHome()
  if not options.disable_assertions:
    env_vars['JAVA_OPTS'] = '-ea:com.android.tools.r8...'

  releaseTarget = app.releaseTarget
  if not releaseTarget:
    releaseTarget = app.module.replace('/', ':') + ':' + 'assemble' + (
        app.flavor.capitalize() if app.flavor else '') + 'Release'

  # Build using gradle.
  args = [releaseTarget,
          '-Pandroid.enableR8=' + str(isR8(shrinker)).lower(),
          '-Pandroid.enableR8.fullMode=' + str(isR8FullMode(shrinker)).lower()]

  # Warm up gradle if pre_runs > 0. For posterity we generate the same sequence
  # as the benchmarking at https://github.com/madsager/santa-tracker-android.
  for i in range(0, options.gradle_pre_runs):
    if i == 0:
      utils.RunGradlew(
          ["--stop"],
          env_vars=env_vars,
          quiet=options.quiet,
          logging=not options.golem,
          use_daemon=options.use_daemon)
    utils.RunGradlew(
        args,
        env_vars=env_vars,
        quiet=options.quiet,
        clean=i > 0,
        use_daemon=options.use_daemon,
        logging=not options.golem)

  if keepRuleSynthesisForRecompilation:
    args.append('-Dcom.android.tools.r8.keepRuleSynthesisForRecompilation=true')
  if options.gradle_flags:
    args.extend(options.gradle_flags.split(' '))

  args.append('--profile')

  stdout = utils.RunGradlew(
      args,
      env_vars=env_vars,
      quiet=options.quiet,
      use_daemon=options.use_daemon,
      logging=not options.golem)

  apk_base_name = (archives_base_name
      + (('-' + app.flavor) if app.flavor else '') + '-release')
  signed_apk_name = (
      app.signed_apk_name
      if app.signed_apk_name
      else apk_base_name + '.apk')
  unsigned_apk_name = apk_base_name + '-unsigned.apk'

  build_dir = app.build_dir
  build_output_apks = os.path.join(app.module, build_dir, 'outputs', 'apk')
  if app.flavor:
    build_output_apks = os.path.join(build_output_apks, app.flavor, 'release')
  else:
    build_output_apks = os.path.join(build_output_apks, 'release')

  signed_apk = os.path.join(build_output_apks, signed_apk_name)
  unsigned_apk = os.path.join(build_output_apks, unsigned_apk_name)

  if options.sign_apks and not os.path.isfile(signed_apk):
    assert os.path.isfile(unsigned_apk)
    if options.sign_apks:
      apk_utils.sign_with_apksigner(
          unsigned_apk,
          signed_apk,
          options.keystore,
          options.keystore_password,
          quiet=options.quiet)

  if os.path.isfile(signed_apk):
    apk_dest = os.path.join(out_dir, signed_apk_name)
    as_utils.MoveFile(signed_apk, apk_dest, quiet=options.quiet)
  else:
    apk_dest = os.path.join(out_dir, unsigned_apk_name)
    as_utils.MoveFile(unsigned_apk, apk_dest, quiet=options.quiet)

  assert ('r8' not in shrinker
      or CheckIsBuiltWithExpectedR8(apk_dest, temp_dir, shrinker, options))

  profile_dest_dir = os.path.join(out_dir, 'profile')
  as_utils.MoveProfileReportTo(profile_dest_dir, stdout, quiet=options.quiet)

  return (apk_dest, profile_dest_dir, proguard_config_dest)

def ComputeInstrumentationTestResults(
    app, options, checkout_dir, out_dir, shrinker):
  args = ['connectedAndroidTest',
         '-Pandroid.enableR8=' + str(isR8(shrinker)).lower(),
         '-Pandroid.enableR8.fullMode=' + str(isR8FullMode(shrinker)).lower()]
  env_vars = { 'ANDROID_SERIAL': options.emulator_id }
  stdout = utils.RunGradlew(
      args,
      env_vars=env_vars,
      quiet=options.quiet,
      fail=False,
      logging=not options.golem,
      use_daemon=options.use_daemon)

  xml_test_result_dest = os.path.join(out_dir, 'test_result')
  as_utils.MoveXMLTestResultFileTo(
      xml_test_result_dest, stdout, quiet=options.quiet)

  with open(xml_test_result_dest, 'r') as f:
    xml_test_result_contents = f.read()

  xml_document = minidom.parseString(xml_test_result_contents)
  testsuite_element = xml_document.documentElement

  return {
    'xml_test_result_dest': xml_test_result_dest,
    'tests': int(testsuite_element.getAttribute('tests')),
    'failures': int(testsuite_element.getAttribute('failures')),
    'errors': int(testsuite_element.getAttribute('errors')),
    'skipped': int(testsuite_element.getAttribute('skipped'))
  }

def ComputeRecompilationResults(
    app, repo, options, checkout_dir, temp_dir, shrinker, proguard_config_file):
  recompilation_results = []

  # Build app with gradle using -D...keepRuleSynthesisForRecompilation=true.
  out_dir = os.path.join(checkout_dir, 'out', shrinker + '-1')
  (apk_dest, profile_dest_dir, ext_proguard_config_file) = \
      BuildAppWithShrinker(
          app, repo, shrinker, checkout_dir, out_dir,
          temp_dir, options, keepRuleSynthesisForRecompilation=True)
  recompilation_result = {
    'apk_dest': apk_dest,
    'build_status': 'success',
    'dex_size': ComputeSizeOfDexFilesInApk(apk_dest),
    'monkey_status': 'skipped'
  }
  recompilation_results.append(recompilation_result)

  # Sanity check that keep rules have changed.
  with open(ext_proguard_config_file) as new:
    with open(proguard_config_file) as old:
      assert(
          sum(1 for line in new
              if line.strip() and '-printconfiguration' not in line)
          >
          sum(1 for line in old
              if line.strip() and '-printconfiguration' not in line))

  # Extract min-sdk and target-sdk
  (min_sdk, compile_sdk) = \
      as_utils.GetMinAndCompileSdk(app, checkout_dir, apk_dest)

  # Now rebuild generated apk.
  previous_apk = apk_dest

  # We may need main dex rules when re-compiling with R8 as standalone.
  main_dex_rules = None
  if app.main_dex_rules:
    main_dex_rules = os.path.join(checkout_dir, app.main_dex_rules)

  for i in range(1, options.r8_compilation_steps):
    try:
      recompiled_apk_dest = os.path.join(
          checkout_dir, 'out', shrinker, 'app-release-{}.apk'.format(i))
      RebuildAppWithShrinker(
          app, previous_apk, recompiled_apk_dest,
          ext_proguard_config_file, shrinker, min_sdk, compile_sdk,
          options, temp_dir, main_dex_rules)
      recompilation_result = {
        'apk_dest': recompiled_apk_dest,
        'build_status': 'success',
        'dex_size': ComputeSizeOfDexFilesInApk(recompiled_apk_dest)
      }
      if options.monkey:
        recompilation_result['monkey_status'] = 'success' if RunMonkey(
            app, options, recompiled_apk_dest) else 'failed'
      recompilation_results.append(recompilation_result)
      previous_apk = recompiled_apk_dest
    except Exception as e:
      warn('Failed to recompile {} with {}'.format(
          app.name, shrinker))
      recompilation_results.append({ 'build_status': 'failed' })
      break
  return recompilation_results

def RebuildAppWithShrinker(
    app, apk, apk_dest, proguard_config_file, shrinker, min_sdk, compile_sdk,
    options, temp_dir, main_dex_rules):
  assert 'r8' in shrinker
  assert apk_dest.endswith('.apk')

  print('Rebuilding {} with {}'.format(app.name, shrinker))

  # Compile given APK with shrinker to temporary zip file.
  android_jar = utils.get_android_jar(compile_sdk)
  r8_jar = os.path.join(
      temp_dir, 'r8lib.jar' if IsMinifiedR8(shrinker) else 'r8.jar')
  zip_dest = apk_dest[:-4] + '.zip'

  # TODO(christofferqa): Entry point should be CompatProguard if the shrinker
  # is 'r8'.
  entry_point = 'com.android.tools.r8.R8'

  cmd = ([jdk.GetJavaExecutable()] +
         (['-ea:com.android.tools.r8...']
          if not options.disable_assertions
          else []) +
         ['-cp', r8_jar, entry_point,
         '--release', '--min-api', str(min_sdk),
         '--pg-conf', proguard_config_file,
         '--lib', android_jar,
         '--output', zip_dest,
         apk])

  for android_optional_jar in utils.get_android_optional_jars(compile_sdk):
    cmd.append('--lib')
    cmd.append(android_optional_jar)

  if main_dex_rules:
    cmd.append('--main-dex-rules')
    cmd.append(main_dex_rules)

  utils.RunCmd(cmd, quiet=options.quiet)

  # Make a copy of the given APK, move the newly generated dex files into the
  # copied APK, and then sign the APK.
  apk_masseur.masseur(
      apk, dex=zip_dest, resources='META-INF/services/*', out=apk_dest,
      quiet=options.quiet)

def RunMonkey(app, options, apk_dest):
  if not WaitForEmulator(options):
    return False

  UninstallApkOnEmulator(app, options)
  InstallApkOnEmulator(apk_dest, options)

  number_of_events_to_generate = options.monkey_events

  # Intentionally using a constant seed such that the monkey generates the same
  # event sequence for each shrinker.
  random_seed = 42

  cmd = ['adb', '-s', options.emulator_id, 'shell', 'monkey', '-p', app.id,
      '-s', str(random_seed), str(number_of_events_to_generate)]

  try:
    stdout = utils.RunCmd(cmd, quiet=options.quiet)
    succeeded = (
        'Events injected: {}'.format(number_of_events_to_generate) in stdout)
  except subprocess.CalledProcessError as e:
    succeeded = False

  UninstallApkOnEmulator(app, options)

  return succeeded

def LogResultsForApps(result_per_shrinker_per_app, options):
  print('')
  for (app, result_per_shrinker) in result_per_shrinker_per_app:
    LogResultsForApp(app, result_per_shrinker, options)

def LogResultsForApp(app, result_per_shrinker, options):
  if options.print_dexsegments:
    LogSegmentsForApp(app, result_per_shrinker, options)
  else:
    LogComparisonResultsForApp(app, result_per_shrinker, options)

def LogSegmentsForApp(app, result_per_shrinker, options):
  for shrinker in SHRINKERS:
    if shrinker not in result_per_shrinker:
      continue
    result = result_per_shrinker[shrinker];
    benchmark_name = '{}-{}'.format(options.print_dexsegments, app.name)
    utils.print_dexsegments(benchmark_name, [result.get('apk_dest')])
    duration = sum(result.get('profile').values())
    print('%s-Total(RunTimeRaw): %s ms' % (benchmark_name, duration * 1000))
    print('%s-Total(CodeSize): %s' % (benchmark_name, result.get('dex_size')))


def LogComparisonResultsForApp(app, result_per_shrinker, options):
  print(app.name + ':')

  if result_per_shrinker.get('status', 'success') != 'success':
    error_message = result_per_shrinker.get('error_message')
    print('  skipped ({})'.format(error_message))
    return

  proguard_result = result_per_shrinker.get('pg', {})
  proguard_dex_size = float(proguard_result.get('dex_size', -1))
  proguard_duration = sum(proguard_result.get('profile', {}).values())

  for shrinker in SHRINKERS:
    if shrinker not in result_per_shrinker:
      continue
    result = result_per_shrinker.get(shrinker)
    build_status = result.get('build_status')
    if build_status != 'success':
      warn('  {}: {}'.format(shrinker, build_status))
    else:
      print('  {}:'.format(shrinker))
      dex_size = result.get('dex_size')
      msg = '    dex size: {}'.format(dex_size)
      if dex_size != proguard_dex_size and proguard_dex_size >= 0:
        msg = '{} ({}, {})'.format(
            msg, dex_size - proguard_dex_size,
            PercentageDiffAsString(proguard_dex_size, dex_size))
        success(msg) if dex_size < proguard_dex_size else warn(msg)
      else:
        print(msg)

      profile = result.get('profile')
      duration = sum(profile.values())
      msg = '    performance: {}s'.format(duration)
      if duration != proguard_duration and proguard_duration > 0:
        msg = '{} ({}s, {})'.format(
            msg, duration - proguard_duration,
            PercentageDiffAsString(proguard_duration, duration))
        success(msg) if duration < proguard_duration else warn(msg)
      else:
        print(msg)
      if len(profile) >= 2:
        for task_name, task_duration in profile.iteritems():
          print('      {}: {}s'.format(task_name, task_duration))

      if options.monkey:
        monkey_status = result.get('monkey_status')
        if monkey_status != 'success':
          warn('    monkey: {}'.format(monkey_status))
        else:
          success('    monkey: {}'.format(monkey_status))

      recompilation_results = result.get('recompilation_results', [])
      i = 0
      for recompilation_result in recompilation_results:
        build_status = recompilation_result.get('build_status')
        if build_status != 'success':
          print('    recompilation #{}: {}'.format(i, build_status))
        else:
          dex_size = recompilation_result.get('dex_size')
          print('    recompilation #{}'.format(i))
          print('      dex size: {}'.format(dex_size))
          if options.monkey:
            monkey_status = recompilation_result.get('monkey_status')
            msg = '      monkey: {}'.format(monkey_status)
            if monkey_status == 'success':
              success(msg)
            elif monkey_status == 'skipped':
              print(msg)
            else:
              warn(msg)
        i += 1

      if options.run_tests and 'instrumentation_test_results' in result:
        instrumentation_test_results = \
            result.get('instrumentation_test_results')
        succeeded = (
            instrumentation_test_results.get('failures')
                + instrumentation_test_results.get('errors')
                + instrumentation_test_results.get('skipped')) == 0
        if succeeded:
          success('    tests: succeeded')
        else:
          warn(
              '    tests: failed (failures: {}, errors: {}, skipped: {})'
              .format(
                  instrumentation_test_results.get('failures'),
                  instrumentation_test_results.get('errors'),
                  instrumentation_test_results.get('skipped')))

def ParseOptions(argv):
  result = optparse.OptionParser()
  result.add_option('--app',
                    help='What app to run on',
                    choices=GetAllAppNames())
  result.add_option('--disable-assertions',
                    help='Disable assertions when compiling',
                    default=False,
                    action='store_true')
  result.add_option('--download-only', '--download_only',
                    help='Whether to download apps without any compilation',
                    default=False,
                    action='store_true')
  result.add_option('--emulator-id', '--emulator_id',
                    help='Id of the emulator to use',
                    default='emulator-5554')
  result.add_option('--golem',
                    help='Running on golem, do not download',
                    default=False,
                    action='store_true')
  result.add_option('--gradle-flags', '--gradle_flags',
                    help='Flags to pass in to gradle')
  result.add_option('--gradle-pre-runs', '--gradle_pre_runs',
                    help='Do rounds of compilations to warm up gradle',
                    default=0,
                    type=int)
  result.add_option('--ignore-versions', '--ignore_versions',
                    help='Allow checked-out app to differ in revision from '
                         'pinned',
                    default=False,
                    action='store_true')
  result.add_option('--keystore',
                    help='Path to app.keystore',
                    default='app.keystore')
  result.add_option('--keystore-password', '--keystore_password',
                    help='Password for app.keystore',
                    default='android')
  result.add_option('--monkey',
                    help='Whether to install and run app(s) with monkey',
                    default=False,
                    action='store_true')
  result.add_option('--monkey_events',
                    help='Number of events that the monkey should trigger',
                    default=250,
                    type=int)
  result.add_option('--no-build', '--no_build',
                    help='Run without building ToT first (only when using ToT)',
                    default=False,
                    action='store_true')
  result.add_option('--quiet',
                    help='Disable verbose logging',
                    default=False,
                    action='store_true')
  result.add_option('--print-dexsegments',
                    metavar='BENCHMARKNAME',
                    help='Print the sizes of individual dex segments as ' +
                         '\'<BENCHMARKNAME>-<APP>-<segment>(CodeSize): '
                         '<bytes>\'')
  result.add_option('--r8-compilation-steps', '--r8_compilation_steps',
                    help='Number of times R8 should be run on each app',
                    default=2,
                    type=int)
  result.add_option('--run-tests', '--run_tests',
                    help='Whether to run instrumentation tests',
                    default=False,
                    action='store_true')
  result.add_option('--sign-apks', '--sign_apks',
                    help='Whether the APKs should be signed',
                    default=False,
                    action='store_true')
  result.add_option('--shrinker',
                    help='The shrinkers to use (by default, all are run)',
                    action='append')
  result.add_option('--use-daemon', '--use_daemon',
                    help='Whether to use a gradle daemon',
                    default=False,
                    action='store_true')
  result.add_option('--version',
                    help='The version of R8 to use (e.g., 1.4.51)')
  (options, args) = result.parse_args(argv)
  if options.app:
    options.apps = [GetAppWithName(options.app)]
    del options.app
  else:
    options.apps = GetAllApps()
  if options.shrinker:
    for shrinker in options.shrinker:
      assert shrinker in SHRINKERS
  else:
    options.shrinker = [shrinker for shrinker in SHRINKERS]
  if options.version:
    # No need to build R8 if a specific release version should be used.
    options.no_build = True
    if 'r8-nolib' in options.shrinker:
      warn('Skipping shrinker r8-nolib because a specific release version '
          + 'of r8 was specified')
      options.shrinker.remove('r8-nolib')
    if 'r8-nolib-full' in options.shrinker:
      warn('Skipping shrinker r8-nolib-full because a specific release version '
          + 'of r8 was specified')
      options.shrinker.remove('r8-nolib-full')
  return (options, args)

def clone_repositories(quiet):
  # Clone repositories into WORKING_DIR.
  with utils.ChangedWorkingDirectory(WORKING_DIR):
    for repo in APP_REPOSITORIES:
      repo_dir = os.path.join(WORKING_DIR, repo.name)
      if not os.path.exists(repo_dir):
        GitClone(repo, repo_dir, quiet)


def main(argv):
  (options, args) = ParseOptions(argv)

  if options.golem:
    golem.link_third_party()
    if os.path.exists(WORKING_DIR):
      shutil.rmtree(WORKING_DIR)
    shutil.copytree(utils.OPENSOURCE_APPS_FOLDER, WORKING_DIR)
    os.environ[utils.ANDROID_HOME_ENVIROMENT_NAME] = os.path.join(
        utils.ANDROID_SDK)
    os.environ[utils.ANDROID_TOOLS_VERSION_ENVIRONMENT_NAME] = '28.0.3'
    options.disable_assertions = True
    options.ignore_versions = True
    options.no_build = True
    options.r8_compilation_steps = 1
    options.quiet = True
    options.gradle_pre_runs = 2
    options.use_daemon = True

  if not os.path.exists(WORKING_DIR):
    os.makedirs(WORKING_DIR)

  if options.download_only:
    clone_repositories(options.quiet)
    return

  with utils.TempDir() as temp_dir:
    if not (options.no_build or options.golem):
      gradle.RunGradle(['r8', 'r8lib'])

    if options.version:
      # Download r8-<version>.jar from
      # http://storage.googleapis.com/r8-releases/raw/.
      target = 'r8-{}.jar'.format(options.version)
      update_prebuilds_in_android.download_version(
          temp_dir, 'com/android/tools/r8/' + options.version, target)
      as_utils.MoveFile(
          os.path.join(temp_dir, target), os.path.join(temp_dir, 'r8lib.jar'),
          quiet=options.quiet)
    else:
      # Make a copy of r8.jar and r8lib.jar such that they stay the same for
      # the entire execution of this script.
      if 'r8-nolib' in options.shrinker or 'r8-nolib-full' in options.shrinker:
        assert os.path.isfile(utils.R8_JAR), 'Cannot build without r8.jar'
        shutil.copyfile(utils.R8_JAR, os.path.join(temp_dir, 'r8.jar'))
      if 'r8' in options.shrinker or 'r8-full' in options.shrinker:
        assert os.path.isfile(utils.R8LIB_JAR), 'Cannot build without r8lib.jar'
        shutil.copyfile(utils.R8LIB_JAR, os.path.join(temp_dir, 'r8lib.jar'))

    result_per_shrinker_per_app = []

    for (app, repo) in options.apps:
      if app.skip:
        continue
      result_per_shrinker_per_app.append(
          (app, GetResultsForApp(app, repo, options, temp_dir)))

    LogResultsForApps(result_per_shrinker_per_app, options)

def success(message):
  CGREEN = '\033[32m'
  CEND = '\033[0m'
  print(CGREEN + message + CEND)

def warn(message):
  CRED = '\033[91m'
  CEND = '\033[0m'
  print(CRED + message + CEND)

if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
