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

import argparse
import os
import sys
import time

def extend_startup_descriptors(startup_descriptors, iteration, options):
  (logcat, profile, profile_classes_and_methods) = \
      generate_startup_profile(options)
  if options.logcat:
    write_tmp_logcat(logcat, iteration, options)
    current_startup_descriptors = get_r8_startup_descriptors_from_logcat(
        logcat, options)
  else:
    write_tmp_profile(profile, iteration, options)
    write_tmp_profile_classes_and_methods(
        profile_classes_and_methods, iteration, options)
    current_startup_descriptors = \
        transform_classes_and_methods_to_r8_startup_descriptors(
            profile_classes_and_methods, options)
  write_tmp_startup_descriptors(current_startup_descriptors, iteration, options)
  number_of_new_startup_descriptors = add_r8_startup_descriptors(
      startup_descriptors, current_startup_descriptors)
  if options.out is not None:
    print(
        'Found %i new startup descriptors in iteration %i'
            % (number_of_new_startup_descriptors, iteration + 1))
  return number_of_new_startup_descriptors

def generate_startup_profile(options):
  logcat = None
  profile = None
  profile_classes_and_methods = None
  if options.use_existing_profile:
    # Verify presence of profile.
    adb_utils.check_app_has_profile_data(options.app_id, options.device_id)
    profile = adb_utils.get_profile_data(options.app_id, options.device_id)
    profile_classes_and_methods = \
        adb_utils.get_classes_and_methods_from_app_profile(
            options.app_id, options.device_id)
  else:
    # Unlock device.
    tear_down_options = adb_utils.prepare_for_interaction_with_device(
        options.device_id, options.device_pin)

    logcat_process = None
    if options.logcat:
      # Clear logcat and start capturing logcat.
      adb_utils.clear_logcat(options.device_id)
      logcat_process = adb_utils.start_logcat(
          options.device_id, format='tag', filter='r8:I ActivityTaskManager:I *:S')
    else:
      # Clear existing profile data.
      adb_utils.clear_profile_data(options.app_id, options.device_id)

    # Launch activity to generate startup profile on device.
    adb_utils.launch_activity(
        options.app_id, options.main_activity, options.device_id)

    # Wait for activity startup.
    time.sleep(options.startup_duration)

    if options.logcat:
      # Get startup descriptors from logcat.
      logcat = adb_utils.stop_logcat(logcat_process)
    else:
      # Capture startup profile.
      adb_utils.capture_app_profile_data(options.app_id, options.device_id)
      profile = adb_utils.get_profile_data(options.app_id, options.device_id)
      profile_classes_and_methods = \
          adb_utils.get_classes_and_methods_from_app_profile(
              options.app_id, options.device_id)

    # Shutdown app.
    adb_utils.stop_app(options.app_id, options.device_id)
    adb_utils.teardown_after_interaction_with_device(
        tear_down_options, options.device_id)

  return (logcat, profile, profile_classes_and_methods)

def get_r8_startup_descriptors_from_logcat(logcat, options):
  post_startup = False
  startup_descriptors = {}
  for line in logcat:
    line_elements = parse_logcat_line(line)
    if line_elements is None:
      continue
    (priority, tag, message) = line_elements
    if tag == 'ActivityTaskManager':
      if message.startswith('START') \
          or message.startswith('Activity pause timeout for') \
          or message.startswith('Activity top resumed state loss timeout for') \
          or message.startswith('Force removing')
          or message.startswith(
              'Launch timeout has expired, giving up wake lock!'):
        continue
      elif message.startswith('Displayed %s/' % options.app_id):
        print('Entering post startup: %s' % message)
        post_startup = True
        continue
    elif tag == 'r8':
      if is_startup_descriptor(message):
        startup_descriptors[message] = {
          'conditional_startup': False,
          'post_startup': post_startup
        }
        continue
    # Reaching here means we didn't expect this line.
    report_unrecognized_logcat_line(line)
  return startup_descriptors

def is_startup_descriptor(string):
  # The descriptor should start with the holder (possibly prefixed with 'S').
  if not any(string.startswith('%sL' % flags) for flags in ['', 'S']):
    return False
  # The descriptor should end with ';', a primitive type, or void.
  if not string.endswith(';') \
      and not any(string.endswith(c) for c in get_primitive_descriptors()) \
      and not string.endswith('V'):
    return False
  return True

def get_primitive_descriptors():
  return ['Z', 'B', 'S', 'C', 'I', 'F', 'J', 'D']

def parse_logcat_line(line):
  if line == '--------- beginning of kernel':
    return None
  if line == '--------- beginning of main':
    return None
  if line == '--------- beginning of system':
    return None

  priority = None
  tag = None

  try:
    priority_end = line.index('/')
    priority = line[0:priority_end]
    line = line[priority_end + 1:]
  except ValueError:
    return report_unrecognized_logcat_line(line)

  try:
    tag_end = line.index(':')
    tag = line[0:tag_end].strip()
    line = line[tag_end + 1 :]
  except ValueError:
    return report_unrecognized_logcat_line(line)

  message = line.strip()
  return (priority, tag, message)

def report_unrecognized_logcat_line(line):
  print('Unrecognized line in logcat: %s' % line)

def transform_classes_and_methods_to_r8_startup_descriptors(
    classes_and_methods, options):
  startup_descriptors = []
  for class_or_method in classes_and_methods:
    descriptor = class_or_method.get('descriptor')
    flags = class_or_method.get('flags')
    if flags.get('conditional_startup') \
        and not options.include_conditional_startup:
      continue
    if flags.get('post_startup') \
        and not flags.get('startup') \
        and not options.include_post_startup:
      continue
    startup_descriptors.append(descriptor)
  return startup_descriptors

def add_r8_startup_descriptors(startup_descriptors, startup_descriptors_to_add):
  previous_number_of_startup_descriptors = len(startup_descriptors)
  if previous_number_of_startup_descriptors == 0:
    for startup_descriptor, flags in startup_descriptors_to_add.items():
      startup_descriptors[startup_descriptor] = flags.copy()
  else:
    for startup_descriptor, flags in startup_descriptors_to_add.items():
      if startup_descriptor in startup_descriptors:
        # Merge flags.
        existing_flags = startup_descriptors[startup_descriptor]
        assert not flags['conditional_startup']
        if flags['post_startup']:
          existing_flags['post_startup'] = True
      else:
        # Add new startup descriptor.
        new_flags = flags.copy()
        new_flags['conditional_startup'] = True
        startup_descriptors[startup_descriptor] = new_flags
  new_number_of_startup_descriptors = len(startup_descriptors)
  return new_number_of_startup_descriptors \
      - previous_number_of_startup_descriptors

def write_tmp_binary_artifact(artifact, iteration, options, name):
  if not options.tmp_dir:
    return
  out_dir = os.path.join(options.tmp_dir, str(iteration))
  os.makedirs(out_dir, exist_ok=True)
  path = os.path.join(out_dir, name)
  with open(path, 'wb') as f:
    f.write(artifact)

def write_tmp_textual_artifact(artifact, iteration, options, name, item_to_string=None):
  if not options.tmp_dir:
    return
  out_dir = os.path.join(options.tmp_dir, str(iteration))
  os.makedirs(out_dir, exist_ok=True)
  path = os.path.join(out_dir, name)
  with open(path, 'w') as f:
    for item in artifact:
      f.write(item if item_to_string is None else item_to_string(item))
      f.write('\n')

def write_tmp_logcat(logcat, iteration, options):
  write_tmp_textual_artifact(logcat, iteration, options, 'logcat.txt')

def write_tmp_profile(profile, iteration, options):
  write_tmp_binary_artifact(profile, iteration, options, 'primary.prof')

def write_tmp_profile_classes_and_methods(
    profile_classes_and_methods, iteration, options):
  def item_to_string(item):
    descriptor = item.get('descriptor')
    flags = item.get('flags')
    return '%s%s%s%s' % (
        'H' if flags.get('hot') else '',
        'S' if flags.get('startup') else '',
        'P' if flags.get('post_startup') else '',
        descriptor)
  write_tmp_textual_artifact(
      profile_classes_and_methods,
      iteration,
      options,
      'profile.txt',
      item_to_string)

def write_tmp_startup_descriptors(startup_descriptors, iteration, options):
  lines = [
      startup_descriptor_to_string(startup_descriptor, flags)
      for startup_descriptor, flags in startup_descriptors.items()]
  write_tmp_textual_artifact(
      lines, iteration, options, 'startup-descriptors.txt')

def startup_descriptor_to_string(startup_descriptor, flags):
  result = ''
  if flags['conditional_startup']:
    pass # result += 'C'
  if flags['post_startup']:
    pass # result += 'P'
  result += startup_descriptor
  return result

def parse_options(argv):
  result = argparse.ArgumentParser(
      description='Generate a perfetto trace file.')
  result.add_argument('--apk',
                      help='Path to the APK')
  result.add_argument('--app-id',
                      help='The application ID of interest',
                      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('--logcat',
                      action='store_true',
                      default=False)
  result.add_argument('--include-conditional-startup',
                      help='Include conditional startup classes and methods in '
                           'the R8 startup descriptors',
                      action='store_true',
                      default=False)
  result.add_argument('--include-post-startup',
                      help='Include post startup classes and methods in the R8 '
                           'startup descriptors',
                      action='store_true',
                      default=False)
  result.add_argument('--iterations',
                      help='Number of profiles to generate',
                      default=1,
                      type=int)
  result.add_argument('--main-activity',
                      help='Main activity class name')
  result.add_argument('--out',
                      help='File where to store startup descriptors (defaults '
                           'to stdout)')
  result.add_argument('--startup-duration',
                      help='Duration in seconds before shutting down app',
                      default=15,
                      type=int)
  result.add_argument('--tmp-dir',
                      help='Directory where to store intermediate artifacts'
                            ' (by default these are not emitted)')
  result.add_argument('--until-stable',
                      help='Repeat profile generation until no new startup '
                           'descriptors are found',
                      action='store_true',
                      default=False)
  result.add_argument('--until-stable-iterations',
                      help='Number of times that profile generation must must '
                           'not find new startup descriptors before exiting',
                      default=1,
                      type=int)
  result.add_argument('--use-existing-profile',
                      help='Do not launch app to generate startup profile',
                      action='store_true',
                      default=False)
  options, args = result.parse_known_args(argv)
  assert options.main_activity is not None or options.use_existing_profile, \
      'Argument --main-activity is required except when running with ' \
      '--use-existing-profile.'
  return options, args

def main(argv):
  (options, args) = parse_options(argv)
  adb_utils.root(options.device_id)
  if options.apk:
    adb_utils.uninstall(options.app_id, options.device_id)
    adb_utils.install(options.apk, options.device_id)
  startup_descriptors = {}
  if options.until_stable:
    iteration = 0
    stable_iterations = 0
    while True:
      diff = extend_startup_descriptors(startup_descriptors, iteration, options)
      if diff == 0:
        stable_iterations = stable_iterations + 1
        if stable_iterations == options.until_stable_iterations:
          break
      else:
        stable_iterations = 0
      iteration = iteration + 1
  else:
    for iteration in range(options.iterations):
      extend_startup_descriptors(startup_descriptors, iteration, options)
  if options.out is not None:
    with open(options.out, 'w') as f:
      for startup_descriptor, flags in startup_descriptors.items():
        f.write(startup_descriptor_to_string(startup_descriptor, flags))
        f.write('\n')
  else:
    for startup_descriptor, flags in startup_descriptors.items():
      print(startup_descriptor_to_string(startup_descriptor, flags))

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