#!/usr/bin/env python3
# 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.

# Script for building sample apks using the sdk tools directly.

import apk_utils
import fnmatch
import glob
import jdk
import optparse
import os
import shutil
import subprocess
import sys
import time
import utils
import uuid

DEFAULT_AAPT = 'aapt'  # Assume in path.
DEFAULT_AAPT2 = 'aapt2'  # Assume in path.
DEFAULT_D8 = os.path.join(utils.REPO_ROOT, 'tools', 'd8.py')
DEFAULT_DEXSPLITTER = os.path.join(utils.REPO_ROOT, 'tools', 'dexsplitter.py')
DEFAULT_JAVAC = jdk.GetJavacExecutable()
SRC_LOCATION = 'src/com/android/tools/r8/sample/{app}/*.java'
DEFAULT_KEYSTORE = os.path.join(os.getenv('HOME'), '.android', 'debug.keystore')
PACKAGE_PREFIX = 'com.android.tools.r8.sample'
STANDARD_ACTIVITY = "R8Activity"
BENCHMARK_ITERATIONS = 30

SAMPLE_APKS = ['simple', 'split']


def parse_options():
    result = optparse.OptionParser()
    result.add_option('--aapt',
                      help='aapt executable to use',
                      default=DEFAULT_AAPT)
    result.add_option('--aapt2',
                      help='aapt2 executable to use',
                      default=DEFAULT_AAPT2)
    result.add_option(
        '--api',
        help='Android api level',
        default=21,
        choices=['14', '15', '19', '21', '22', '23', '24', '25', '26'])
    result.add_option('--keystore',
                      help='Keystore used for signing',
                      default=DEFAULT_KEYSTORE)
    result.add_option('--split',
                      help='Split the app using the split.spec file',
                      default=False,
                      action='store_true')
    result.add_option(
        '--generate-proto-apk',
        help='Use aapt2 to generate the proto version of the apk.',
        default=False,
        action='store_true')
    result.add_option('--install',
                      help='Install the app (including featuresplit)',
                      default=False,
                      action='store_true')
    result.add_option(
        '--benchmark',
        help='Benchmark the app on the phone with specialized markers',
        default=False,
        action='store_true')
    result.add_option('--benchmark-output-dir',
                      help='Store benchmark results here.',
                      default=None)
    result.add_option('--app',
                      help='Which app to build',
                      default='simple',
                      choices=SAMPLE_APKS)
    return result.parse_args()


def run_aapt(aapt, args):
    command = [aapt]
    command.extend(args)
    utils.PrintCmd(command)
    subprocess.check_call(command)


def get_build_dir(app):
    return os.path.join(utils.BUILD, 'sampleApks', app)


def get_gen_path(app):
    gen_path = os.path.join(get_build_dir(app), 'gen')
    utils.makedirs_if_needed(gen_path)
    return gen_path


def get_bin_path(app):
    bin_path = os.path.join(get_build_dir(app), 'bin')
    utils.makedirs_if_needed(bin_path)
    return bin_path


def get_guava_jar():
    return os.path.join(
        utils.REPO_ROOT,
        'third_party/gradle-plugin/com/google/guava/guava/22.0/guava-22.0.jar')


def get_sample_dir(app):
    return os.path.join(utils.REPO_ROOT, 'src', 'test', 'sampleApks', app)


def get_src_path(app):
    return os.path.join(get_sample_dir(app), 'src')


def get_dex_path(app):
    return os.path.join(get_bin_path(app), 'classes.dex')


def get_split_path(app, split):
    return os.path.join(get_bin_path(app), split, 'classes.dex')


def get_package_name(app):
    return '%s.%s' % (PACKAGE_PREFIX, app)


def get_qualified_activity(app):
    # The activity specified to adb start is PACKAGE_NAME/.ACTIVITY
    return '%s/.%s' % (get_package_name(app), STANDARD_ACTIVITY)


def run_aapt_pack(aapt, api, app):
    with utils.ChangedWorkingDirectory(get_sample_dir(app)):
        args = [
            'package', '-v', '-f', '-I',
            utils.get_android_jar(api), '-M', 'AndroidManifest.xml', '-A',
            'assets', '-S', 'res', '-m', '-J',
            get_gen_path(app), '-F',
            os.path.join(get_bin_path(app), 'resources.ap_'), '-G',
            os.path.join(get_build_dir(app), 'proguard_options')
        ]
        run_aapt(aapt, args)


def run_aapt_split_pack(aapt, api, app):
    with utils.ChangedWorkingDirectory(get_sample_dir(app)):
        args = [
            'package', '-v', '-f', '-I',
            utils.get_android_jar(api), '-M',
            'split_manifest/AndroidManifest.xml', '-S', 'res', '-F',
            os.path.join(get_bin_path(app), 'split_resources.ap_')
        ]
        run_aapt(aapt, args)


def compile_with_javac(api, app):
    with utils.ChangedWorkingDirectory(get_sample_dir(app)):
        files = glob.glob(SRC_LOCATION.format(app=app))
        classpath = '%s:%s' % (utils.get_android_jar(api), get_guava_jar())
        command = [
            DEFAULT_JAVAC, '-classpath', classpath, '-sourcepath',
            '%s:%s:%s' %
            (get_src_path(app), get_gen_path(app), get_guava_jar()), '-d',
            get_bin_path(app)
        ]
        command.extend(files)
        utils.PrintCmd(command)
        subprocess.check_call(command)


def dex(app, api):
    files = []
    for root, dirnames, filenames in os.walk(get_bin_path(app)):
        for filename in fnmatch.filter(filenames, '*.class'):
            files.append(os.path.join(root, filename))
    command = [
        DEFAULT_D8, '--', '--output',
        get_bin_path(app), '--classpath',
        utils.get_android_jar(api), '--min-api',
        str(api)
    ]
    command.extend(files)
    if app != 'simple':
        command.append(get_guava_jar())

    utils.PrintCmd(command)
    subprocess.check_call(command)


def split(app):
    split_spec = os.path.join(get_sample_dir(app), 'split.spec')
    command = [
        DEFAULT_DEXSPLITTER, '--input',
        get_dex_path(app), '--output',
        get_bin_path(app), '--feature-splits', split_spec
    ]
    utils.PrintCmd(command)
    subprocess.check_call(command)


def run_adb(args, ignore_exit=False):
    command = ['adb']
    command.extend(args)
    utils.PrintCmd(command)
    # On M adb install-multiple exits 1 but succeed in installing.
    if ignore_exit:
        subprocess.call(command)
    else:
        subprocess.check_call(command)


def adb_install(apks):
    args = ['install-multiple' if len(apks) > 1 else 'install', '-r', '-d']
    args.extend(apks)
    run_adb(args, ignore_exit=True)


def create_temp_apk(app, prefix):
    temp_apk_path = os.path.join(get_bin_path(app), '%s.ap_' % app)
    shutil.copyfile(os.path.join(get_bin_path(app), '%sresources.ap_' % prefix),
                    temp_apk_path)
    return temp_apk_path


def aapt_add_dex(aapt, dex, temp_apk_path):
    args = ['add', '-k', temp_apk_path, dex]
    run_aapt(aapt, args)


def kill(app):
    args = ['shell', 'am', 'force-stop', get_package_name(app)]
    run_adb(args)


def start_logcat():
    return subprocess.Popen(['adb', 'logcat'],
                            bufsize=1024 * 1024,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)


def start(app):
    args = ['shell', 'am', 'start', '-n', get_qualified_activity(app)]
    run_adb(args)


def clear_logcat():
    args = ['logcat', '-c']
    run_adb(args)


def stop_logcat(popen):
    popen.terminate()
    lines = []
    for l in popen.stdout:
        if 'System.out' in l:
            lines.append(l)
    return lines


def store_or_print_benchmarks(lines, output):
    results = {}
    overall_total = 0
    # We assume that the total times are
    # prefixed with 'NAME Total: '. The logcat lines looks like:
    # 06-28 12:22:00.991 13698 13698 I System.out: Call Total: 61614
    for l in lines:
        if 'Total: ' in l:
            split = l.split('Total: ')
            time = split[1]
            name = split[0].split()[-1]
            overall_total += int(time)
            print('%s: %s' % (name, time))
            results[name] = time

    print('Total: %s' % overall_total)
    if not output:
        return overall_total
    results['total'] = str(overall_total)
    output_dir = os.path.join(output, str(uuid.uuid4()))
    os.makedirs(output_dir)
    written_files = []
    for name, time in results.iteritems():
        total_file = os.path.join(output_dir, name)
        written_files.append(total_file)
        with open(total_file, 'w') as f:
            f.write(time)

    print('Result stored in: \n%s' % ('\n'.join(written_files)))
    return overall_total


def benchmark(app, output_dir):
    # Ensure app is not running
    kill(app)
    clear_logcat()
    logcat = start_logcat()
    start(app)
    # We could do better here by continiously parsing the logcat for a marker, but
    # this works nicely with the current setup.
    time.sleep(12)
    kill(app)
    return float(store_or_print_benchmarks(stop_logcat(logcat), output_dir))


def ensure_no_logcat():
    output = subprocess.check_output(['ps', 'aux'])
    if 'adb logcat' in output:
        raise Exception(
            'You have adb logcat running, please close it and rerun')


def generate_proto_apks(apks, options):
    proto_apks = []
    for apk in apks:
        proto_apk = apk + '.proto'
        cmd = [
            options.aapt2, 'convert', '-o', proto_apk, '--output-format',
            'proto', apk
        ]
        utils.PrintCmd(cmd)
        subprocess.check_call(cmd)
        proto_apks.append(proto_apk)
    return proto_apks


def Main():
    (options, args) = parse_options()
    apks = []
    is_split = options.split
    run_aapt_pack(options.aapt, options.api, options.app)
    if is_split:
        run_aapt_split_pack(options.aapt, options.api, options.app)
    compile_with_javac(options.api, options.app)
    dex(options.app, options.api)
    dex_files = {options.app: get_dex_path(options.app)}
    dex_path = get_dex_path(options.app)
    if is_split:
        split(options.app)
        dex_path = get_split_path(options.app, 'base')
    temp_apk_path = create_temp_apk(options.app, '')
    aapt_add_dex(options.aapt, dex_path, temp_apk_path)
    apk_path = os.path.join(get_bin_path(options.app), '%s.apk' % options.app)
    apk_utils.sign(temp_apk_path, apk_path, options.keystore)
    apks.append(apk_path)
    if is_split:
        split_temp_apk_path = create_temp_apk(options.app, 'split_')
        aapt_add_dex(options.aapt, get_split_path(options.app, 'split'),
                     temp_apk_path)
        split_apk_path = os.path.join(get_bin_path(options.app),
                                      'featuresplit.apk')
        apk_utils.sign(temp_apk_path, split_apk_path, options.keystore)
        apks.append(split_apk_path)
    if options.generate_proto_apk:
        proto_apks = generate_proto_apks(apks, options)
        print('Generated proto apks available at: %s' % ' '.join(proto_apks))
    print('Generated apks available at: %s' % ' '.join(apks))
    if options.install or options.benchmark:
        adb_install(apks)
    grand_total = 0
    if options.benchmark:
        ensure_no_logcat()
        for _ in range(BENCHMARK_ITERATIONS):
            grand_total += benchmark(options.app, options.benchmark_output_dir)
    print('Combined average: %s' % (grand_total / BENCHMARK_ITERATIONS))


if __name__ == '__main__':
    sys.exit(Main())
