#!/usr/bin/env python3
# Copyright (c) 2022, 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 argparse
import os
import statistics
import sys
import time

try:
  from perfetto.trace_processor import TraceProcessor
except ImportError:
  sys.exit(
      'Unable to analyze perfetto trace without the perfetto library. '
      'Install instructions:\n'
      '    sudo apt install python3-pip\n'
      '    pip3 install perfetto')

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

import adb_utils
import apk_utils
import perfetto_utils
import utils

def setup(options):
  # Increase screen off timeout to avoid device screen turns off.
  twenty_four_hours_in_millis = 24 * 60 * 60 * 1000
  previous_screen_off_timeout = adb_utils.get_screen_off_timeout(
      options.device_id)
  adb_utils.set_screen_off_timeout(
      twenty_four_hours_in_millis, options.device_id)

  # Unlock device.
  adb_utils.unlock(options.device_id, options.device_pin)

  teardown_options = {
    'previous_screen_off_timeout': previous_screen_off_timeout
  }
  return teardown_options

def teardown(options, teardown_options):
  # Reset screen off timeout.
  adb_utils.set_screen_off_timeout(
      teardown_options['previous_screen_off_timeout'],
      options.device_id)

def run_all(apk_or_apks, options, tmp_dir):
  # Launch app while collecting information.
  data_total = {}
  for iteration in range(1, options.iterations + 1):
    print('Starting iteration %i' % iteration)
    out_dir = os.path.join(options.out_dir, str(iteration))
    teardown_options = setup_for_run(apk_or_apks, out_dir, options)
    data = run(out_dir, options, tmp_dir)
    teardown_for_run(out_dir, options, teardown_options)
    add_data(data_total, data)
    print('Result:')
    print(data)
    print(compute_data_summary(data_total))
    print('Done')
  print('Average result:')
  data_summary = compute_data_summary(data_total)
  print(data_summary)
  write_data(options.out_dir, data_summary)

def compute_data_summary(data_total):
  data_summary = {}
  for key, value in data_total.items():
    if not isinstance(value, list):
      data_summary[key] = value
      continue
    data_summary['%s_avg' % key] = round(statistics.mean(value), 1)
    data_summary['%s_med' % key] = statistics.median(value)
  return data_summary

def setup_for_run(apk_or_apks, out_dir, options):
  adb_utils.root(options.device_id)

  print('Installing')
  adb_utils.uninstall(options.app_id, options.device_id)
  if apk_or_apks['apk']:
    adb_utils.install(apk_or_apks['apk'], options.device_id)
  else:
    assert apk_or_apks['apks']
    adb_utils.install_apks(apk_or_apks['apks'], options.device_id)

  os.makedirs(out_dir, exist_ok=True)

  # AOT compile.
  if options.aot:
    print('AOT compiling')
    if options.baseline_profile:
      adb_utils.clear_profile_data(options.app_id, options.device_id)
      adb_utils.install_profile(options.app_id, options.device_id)
    else:
      adb_utils.force_compilation(options.app_id, options.device_id)

  # Cooldown and then unlock device.
  if options.cooldown > 0:
    print('Cooling down for %i seconds' % options.cooldown)
    assert adb_utils.get_screen_state(options.device_id).is_off()
    time.sleep(options.cooldown)
    teardown_options = adb_utils.prepare_for_interaction_with_device(
        options.device_id, options.device_pin)
  else:
    teardown_options = None

  # Prelaunch for hot startup.
  if options.hot_startup:
    print('Prelaunching')
    adb_utils.launch_activity(
        options.app_id,
        options.main_activity,
        options.device_id,
        wait_for_activity_to_launch=False)
    time.sleep(options.startup_duration)
    adb_utils.navigate_to_home_screen(options.device_id)
    time.sleep(1)

  # Drop caches before run.
  adb_utils.drop_caches(options.device_id)
  return teardown_options

def teardown_for_run(out_dir, options, teardown_options):
  assert adb_utils.get_screen_state(options.device_id).is_on_and_unlocked()

  if options.capture_screen:
    target = os.path.join(out_dir, 'screen.png')
    adb_utils.capture_screen(target, options.device_id)

  if options.cooldown > 0:
    adb_utils.teardown_after_interaction_with_device(
        teardown_options, options.device_id)
    adb_utils.ensure_screen_off(options.device_id)
  else:
    assert teardown_options is None

def run(out_dir, options, tmp_dir):
  assert adb_utils.get_screen_state(options.device_id).is_on_and_unlocked()

  # Start perfetto trace collector.
  perfetto_process = None
  perfetto_trace_path = None
  if options.perfetto:
    perfetto_process, perfetto_trace_path = perfetto_utils.record_android_trace(
        out_dir, tmp_dir, options.device_id)

  # Launch main activity.
  launch_activity_result = adb_utils.launch_activity(
      options.app_id,
      options.main_activity,
      options.device_id,
      wait_for_activity_to_launch=True)

  # Wait for perfetto trace collector to stop.
  if options.perfetto:
    perfetto_utils.stop_record_android_trace(perfetto_process, out_dir)

  # Get minor and major page faults from app process.
  data = compute_data(launch_activity_result, perfetto_trace_path, options)
  write_data(out_dir, data)
  return data

def add_data(data_total, data):
  for key, value in data.items():
    if key == 'app_id':
      assert data_total.get(key, value) == value
      data_total[key] = value
    if key == 'time':
      continue
    if key in data_total:
      if key == 'app_id':
        assert data_total[key] == value
      else:
        existing_value = data_total[key]
        assert isinstance(value, int)
        assert isinstance(existing_value, list)
        existing_value.append(value)
    else:
      assert isinstance(value, int), key
      data_total[key] = [value]

def compute_data(launch_activity_result, perfetto_trace_path, options):
  minfl, majfl = adb_utils.get_minor_major_page_faults(
      options.app_id, options.device_id)
  data = {
    'app_id': options.app_id,
    'time': time.ctime(time.time()),
    'minfl': minfl,
    'majfl': majfl
  }
  startup_data = compute_startup_data(
      launch_activity_result, perfetto_trace_path, options)
  return data | startup_data

def compute_startup_data(launch_activity_result, perfetto_trace_path, options):
  startup_data = {
    'adb_startup': launch_activity_result.get('total_time')
  }
  perfetto_startup_data = {}
  if options.perfetto:
    trace_processor = TraceProcessor(file_path=perfetto_trace_path)

    # Compute time to first frame according to the builtin android_startup
    # metric.
    startup_metric = trace_processor.metric(['android_startup'])
    time_to_first_frame_ms = \
        startup_metric.android_startup.startup[0].to_first_frame.dur_ms
    perfetto_startup_data['perfetto_startup'] = round(time_to_first_frame_ms)

    if not options.hot_startup:
      # Compute time to first and last doFrame event.
      bind_application_slice = perfetto_utils.find_unique_slice_by_name(
          'bindApplication', options, trace_processor)
      activity_start_slice = perfetto_utils.find_unique_slice_by_name(
          'activityStart', options, trace_processor)
      do_frame_slices = perfetto_utils.find_slices_by_name(
          'Choreographer#doFrame', options, trace_processor)
      first_do_frame_slice = next(do_frame_slices)
      *_, last_do_frame_slice = do_frame_slices

      perfetto_startup_data.update({
        'time_to_first_choreographer_do_frame_ms':
            round(perfetto_utils.get_slice_end_since_start(
                first_do_frame_slice, bind_application_slice)),
        'time_to_last_choreographer_do_frame_ms':
            round(perfetto_utils.get_slice_end_since_start(
                last_do_frame_slice, bind_application_slice))
      })

  # Return combined startup data.
  return startup_data | perfetto_startup_data

def write_data(out_dir, data):
  data_path = os.path.join(out_dir, 'data.txt')
  with open(data_path, 'w') as f:
    for key, value in data.items():
      f.write('%s=%s\n' % (key, str(value)))

def parse_options(argv):
  result = argparse.ArgumentParser(
      description='Generate a perfetto trace file.')
  result.add_argument('--app-id',
                      help='The application ID of interest',
                      required=True)
  result.add_argument('--aot',
                      help='Enable force compilation',
                      default=False,
                      action='store_true')
  result.add_argument('--aot-profile',
                      help='Enable force compilation using profiles',
                      default=False,
                      action='store_true')
  result.add_argument('--apk',
                      help='Path to the .apk')
  result.add_argument('--apks',
                      help='Path to the .apks')
  result.add_argument('--bundle',
                      help='Path to the .aab')
  result.add_argument('--capture-screen',
                      help='Take a screenshot after each test',
                      default=False,
                      action='store_true')
  result.add_argument('--cooldown',
                      help='Seconds to wait before running each iteration',
                      default=0,
                      type=int)
  result.add_argument('--device-id',
                      help='Device id (e.g., emulator-5554).')
  result.add_argument('--device-pin',
                      help='Device pin code (e.g., 1234)')
  result.add_argument('--hot-startup',
                      help='Measure hot startup instead of cold startup',
                      default=False,
                      action='store_true')
  result.add_argument('--iterations',
                      help='Number of traces to generate',
                      default=1,
                      type=int)
  result.add_argument('--main-activity',
                      help='Main activity class name',
                      required=True)
  result.add_argument('--no-perfetto',
                      help='Disables perfetto trace generation',
                      action='store_true',
                      default=False)
  result.add_argument('--out-dir',
                      help='Directory to store trace files in',
                      required=True)
  result.add_argument('--baseline-profile',
                      help='Baseline profile to install')
  result.add_argument('--startup-duration',
                      help='Duration in seconds before shutting down app',
                      default=15,
                      type=int)
  options, args = result.parse_known_args(argv)
  setattr(options, 'perfetto', not options.no_perfetto)

  paths = [
      path for path in [options.apk, options.apks, options.bundle]
      if path is not None]
  assert len(paths) == 1, 'Expected exactly one .apk, .apks, or .aab file.'

  # Build .apks file up front to avoid building the bundle upon each install.
  if options.bundle:
    os.makedirs(options.out_dir, exist_ok=True)
    options.apks = os.path.join(options.out_dir, 'Bundle.apks')
    adb_utils.build_apks_from_bundle(
        options.bundle, options.apks, overwrite=True)
    del options.bundle

  # Profile is only used with --aot.
  assert options.aot or not options.baseline_profile

  return options, args

def global_setup(options):
  # If there is no cooldown then unlock the screen once. Otherwise we turn off
  # the screen during the cooldown and unlock the screen before each iteration.
  teardown_options = None
  if options.cooldown == 0:
    teardown_options = adb_utils.prepare_for_interaction_with_device(
        options.device_id, options.device_pin)
    assert adb_utils.get_screen_state(options.device_id).is_on()
  else:
    adb_utils.ensure_screen_off(options.device_id)
  return teardown_options

def global_teardown(options, teardown_options):
  if options.cooldown == 0:
    adb_utils.teardown_after_interaction_with_device(
        teardown_options, options.device_id)
  else:
    assert teardown_options is None

def main(argv):
  (options, args) = parse_options(argv)
  with utils.TempDir() as tmp_dir:
    apk_or_apks = { 'apk': options.apk, 'apks': options.apks }
    if options.baseline_profile:
      assert not options.apks, 'Unimplemented'
      apk_or_apks['apk'] = apk_utils.add_baseline_profile_to_apk(
          options.apk, options.baseline_profile, tmp_dir)
    teardown_options = global_setup(options)
    run_all(apk_or_apks, options, tmp_dir)
    global_teardown(options, teardown_options)

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