#!/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 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 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)

  tear_down_options = {
    'previous_screen_off_timeout': previous_screen_off_timeout
  }
  return tear_down_options

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

def run_all(options, tmp_dir):
  # Launch app while collecting information.
  data_avg = {}
  for iteration in range(options.iterations):
    print('Starting iteration %i' % iteration)
    out_dir = os.path.join(options.out_dir, str(iteration))
    prepare_for_run(out_dir, options)
    data = run(out_dir, options, tmp_dir)
    add_data(data_avg, data)
    print("Result:")
    print(data)
    print("Done")
  for key, value in data_avg.items():
    if isinstance(value, int):
      data_avg[key] = value / options.iterations
  print("Average result:")
  print(data_avg)
  write_data(options.out_dir, data_avg)

def prepare_for_run(out_dir, options):
  adb_utils.root(options.device_id)
  adb_utils.uninstall(options.app_id, options.device_id)
  adb_utils.install(options.apk, options.device_id)
  adb_utils.clear_profile_data(options.app_id, options.device_id)
  if options.aot:
    adb_utils.force_compilation(options.app_id, options.device_id)
  elif options.aot_profile:
    adb_utils.launch_activity(
        options.app_id, options.main_activity, options.device_id)
    time.sleep(options.aot_profile_sleep)
    adb_utils.stop_app(options.app_id, options.device_id)
    adb_utils.force_profile_compilation(options.app_id, options.device_id)

  adb_utils.drop_caches(options.device_id)
  os.makedirs(out_dir, exist_ok=True)

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

  # Start perfetto trace collector.
  perfetto_process, perfetto_trace_path = perfetto_utils.record_android_trace(
      out_dir, tmp_dir)

  # Launch main activity.
  adb_utils.launch_activity(
      options.app_id, options.main_activity, options.device_id)

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

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

def add_data(sum_data, data):
  for key, value in data.items():
    if key == 'time':
      continue
    if hasattr(sum_data, key):
      if key == 'app_id':
        assert sum_data[key] == value
      else:
        existing_value = sum_data[key]
        assert isinstance(value, int)
        assert isinstance(existing_value, int)
        sum_data[key] = existing_value + value
    else:
      sum_data[key] = value

def compute_data(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(perfetto_trace_path, options)
  return data | startup_data

def compute_startup_data(perfetto_trace_path, options):
  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

  # 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

  return {
    'time_to_first_frame_ms': time_to_first_frame_ms,
    'time_to_first_choreographer_do_frame_ms':
        perfetto_utils.get_slice_end_since_start(
            first_do_frame_slice, bind_application_slice),
    'time_to_last_choreographer_do_frame_ms':
        perfetto_utils.get_slice_end_since_start(
            last_do_frame_slice, bind_application_slice)
  }

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('--aot-profile-sleep',
                      help='Duration in seconds before forcing compilation',
                      default=15,
                      type=int)
  result.add_argument('--apk',
                      help='Path to the APK',
                      required=True)
  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('--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('--out-dir',
                      help='Directory to store trace files in',
                      required=True)
  options, args = result.parse_known_args(argv)
  assert (not options.aot) or (not options.aot_profile)
  return options, args

def main(argv):
  (options, args) = parse_options(argv)
  with utils.TempDir() as tmp_dir:
    tear_down_options = adb_utils.prepare_for_interaction_with_device(
        options.device_id, options.device_pin)
    run_all(options, tmp_dir)
    adb_utils.tear_down_after_interaction_with_device(
        tear_down_options, options.device_id)

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