# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Stress test utility for repeating actions repeatedly on android devices.

Configures multiple devices to simultaneously run through the same set of
actions over and over, while keeping logs from various sources. Primarily
designed for playing audio to the devices and scanning their log output for
events, while running other adb commands in between.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import datetime
from email import encoders
from email.mime import text
import email.mime.base as base
import email.mime.multipart as multipart
import logging
import mimetypes
import os
import platform
import re
import shlex
import signal
import smtplib
import socket
import subprocess
import sys
import tempfile
import threading
import time
import uuid
import wave
from absl import app
from absl import flags
import pexpect
import queue
import stress_test_common
import stress_test_pb2
from google.protobuf import text_format

_SUMMARY_LINES = "-" * 73

if sys.platform.startswith("win"):
  pexpect = None

_SUMMARY_COLUMNS = (
    "|        Event Type       |      Event Count     | Consecutive no event |")
_SUMMARY_COL_FORMATT = "|%-25.25s|% 22d|% 22d|"

FLAGS = flags.FLAGS
flags.DEFINE_string("notification_address", "",
                    "Email address where to send notification events. Will "
                    "default to $USER@google.com if not provided. No emails "
                    "will be sent if suppress_notification_emails is True.")
flags.DEFINE_bool("suppress_notification_emails", False,
                  "Prevents emails from being sent as notifications if True.")
flags.DEFINE_string("test_name", None,
                    "Name of stress test to run. For example, if you set this "
                    "to 'dsp_trigger_sw_rejection', the stress test in "
                    "'stress_test.dsp_trigger_sw_rejection.ascii_proto' will "
                    "be loaded and executed.")
# flags.mark_flag_as_required("test_name")
flags.DEFINE_string("output_root", "./",
                    "Path where directory should be generated containing all "
                    "logs from devices and moved files.")
flags.DEFINE_integer("num_iterations", None,
                     "If set to a positive number, the number of iterations of "
                     "the stress test to run. Otherwise, the test runs "
                     "forever.")
flags.DEFINE_list("devices", [],
                  "Serial numbers of devices that should be included in the "
                  "stress test. If empty, all devices will be used.")
flags.DEFINE_integer("print_summary_every_n", 10,
                     "Prints the summary to the log file every n iterations.")

flags.DEFINE_string("email_sender_address", "",
                    "Account to use for sending notification emails.")
flags.DEFINE_string("email_sender_password", "",
                    "Password to use for notification email account.")
flags.DEFINE_string("email_smtp_server", "smtp.gmail.com",
                    "SMTP server to use for sending notification emails.")
flags.DEFINE_integer("email_smtp_port", 465,
                     "Port to use for the notification SMTP server.")
flags.DEFINE_integer("device_settle_time", 5,
                     "Time to wait for devices to settle.")
flags.DEFINE_bool("use_sox", platform.system() != "Windows",
                  "Use sox for playback, otherwise, attempt to use platform "
                  "specific features.")
flags.DEFINE_bool("attach_bugreport", True,
                  "Attach bugreport to email if test failed.")
flags.DEFINE_bool("delete_data_dir", False,
                  "If true, code will delete all the files generated by this "
                  "test at the end.")

if platform.system().startswith("CYGWIN"):
  FLAGS.device_settle_time = 30


def QueueWorker(worker_queue):
  while True:
    work = worker_queue.get()
    try:
      work()
    except:  # pylint:disable=bare-except
      logging.exception("Exception in worker queue - task remains uncompleted.")
    worker_queue.task_done()


def SendNotificationEmail(subject, body, bugreport=None):
  """Sends an email with the specified subject and body.

     Also attach bugreport if bugreport location is provided as argument

  Args:
    subject: Subject of the email.
    body: Body of the email.
    bugreport: If provided, it will be attach to the email.
  """
  if FLAGS.suppress_notification_emails:
    logging.info("Email with subject '%s' has been suppressed", subject)
    return
  try:
    # Assemble the message to send.
    recpient_address = FLAGS.notification_address
    message = multipart.MIMEMultipart("alternative")
    message["From"] = "Stress Test on %s" % socket.gethostname()
    message["To"] = recpient_address
    message["Subject"] = subject
    message.attach(text.MIMEText(body, "plain"))
    message.attach(text.MIMEText("<pre>%s</pre>" % body, "html"))

    if FLAGS.attach_bugreport and bugreport:
      # buildozer: disable=unused-variable
      ctype, _ = mimetypes.guess_type(bugreport)
      maintype, subtype = ctype.split("/", 1)
      with open(bugreport, "rb") as fp:
        att = base.MIMEBase(maintype, subtype)
        att.set_payload(fp.read())
        encoders.encode_base64(att)
        att.add_header("Content-Disposition", "attachment", filename=bugreport)
        message.attach(att)

    # Send the message from our special account.
    server = smtplib.SMTP_SSL(FLAGS.email_smtp_server, FLAGS.email_smtp_port)
    server.login(FLAGS.email_sender_address, FLAGS.email_sender_password)
    server.sendmail(FLAGS.email_sender_address, recpient_address,
                    message.as_string())
    server.quit()
    logging.info("Email with subject '%s' has been sent", subject)
  except:  # pylint:disable=bare-except
    logging.exception("Failed to send notification email")


class ProcessLogger(threading.Thread):

  class EventScanner(object):

    def __init__(self, name, process_name, regexes):
      """Struct to store the data about an event.

      Args:
        name: Name of event.
        process_name: Name of the process that is being logged.
        regexes: An iteratable of regex strings that indicate an event has
            happened.
      """

      self.name = name
      self.process_name = process_name
      self.searches = [re.compile(regex).search for regex in regexes]
      self.count = 0

    def ScanForEvent(self, line, lock=None):
      """Checks the line for matches. If found, updates the internal counter."""

      for search in self.searches:
        if search(line.decode("utf-8")):
          # Grab the lock (if provided), update the counter, and release it.
          if lock: lock.acquire()
          self.count += 1
          if lock: lock.release()
          logging.info("Event '%s' detected on %s", self.name,
                       self.process_name)

  def __init__(self, name, command, output, events,
               restart_process, repeats_output_when_opened):
    """Threaded class that monitors processes for events, and logs output.

    Args:
      name: The name of the process being logged.
      command: A list of arguments to be passed to the subprocess to execute.
      output: Name of output file to write process stdout to. If blank or None,
          will not be generated.
      events: An iterable of LoggingEventConfigs to look for in the output.
      restart_process: Restart the process if it terminates by itself. This
          should typically be true, but false for processes that only should be
          run once and have their output logged.
      repeats_output_when_opened: Set to true if the process will repeat the
          output of a previous call when it is restarted. This will prevent
          duplicate lines from being logged.
    """
    super(ProcessLogger, self).__init__()
    self.name = name
    self.command = command
    self.restart_process = restart_process
    self.repeats_output_when_opened = repeats_output_when_opened
    self.process = None
    self.lock = threading.Lock()
    self.looking = False

    # Compile the list of regexes that we're supposed to be looking for.
    self.events = []
    for event in events:
      self.events.append(ProcessLogger.EventScanner(event.name, self.name,
                                                    event.regex))

    if output:
      stress_test_common.MakeDirsIfNeeded(os.path.dirname(output))
      self.output_fp = open(output, "w")
      logging.info("Logging device info to %s", output)
    else:
      self.output_fp = None

  def GetEventCountsSinceLastCall(self):
    """Returns the counts of all events since this method was last called."""
    event_map = {}
    self.lock.acquire()
    for event in self.events:
      event_map[event.name] = event.count
      event.count = 0
    self.lock.release()
    return event_map

  def run(self):
    last_line = None
    should_log = True
    first_run = True
    self.lock.acquire()
    last_run_time = 0
    while self.restart_process:
      self.lock.release()
      if not first_run:
        logging.info("Restarting process %s", "".join(str(self.command)))
        time_since_last_run = datetime.datetime.now() - last_run_time
        if time_since_last_run.total_seconds() < 1.0:
          needed_delay = 1.0 - time_since_last_run.total_seconds()
          logging.info("Delaying for %.2f seconds", needed_delay)
          time.sleep(needed_delay)
      else:
        first_run = False

      try:
        if pexpect:
          self.process = pexpect.spawn(" ".join(self.command), timeout=None)
          output_source = self.process
        else:
          self.process = subprocess.Popen(self.command, stdout=subprocess.PIPE)
          output_source = self.process.stdout
        last_run_time = datetime.datetime.now()
        for line in output_source:
          # If the process we're logging likes to repeat its output, we need to
          # look for the last line we saw before we start doing anything with
          # these lines anymore.
          if self.repeats_output_when_opened:
            if not should_log:
              if last_line == line:
                should_log = True
              continue

          if self.output_fp:
            self.output_fp.write(line.decode("utf-8").rstrip())
            self.output_fp.write("\n")

          # Loop through all events we're watching for, to see if they occur on
          # this line. If they do, update the fact that we've seen this event.
          for event in self.events:
            if self.looking:
              event.ScanForEvent(line, lock=self.lock)
          last_line = line
      except:  # pylint:disable=bare-except
        logging.exception("Exception encountered running process")
      finally:
        if pexpect:
          self.process.terminate()
        else:
          self.process.send_signal(signal.SIGTERM)
        should_log = False
      self.lock.acquire()
    self.lock.release()
    if pexpect:
      if self.process.exitstatus is not None:
        logging.info("Process finished - exit code %d", self.process.exitstatus)
      else:
        logging.info("Process finished - signal code %d",
                     self.process.signalstatus)
    else:
      if self.process.returncode is not None:
        logging.info("Process finished - return code %d",
                     self.process.returncode)
      else:
        logging.info("Process finished - no return code")

  def StopLogging(self):
    if self.process:
      self.lock.acquire()
      self.restart_process = False
      self.lock.release()

      if pexpect:
        self.process.kill(signal.SIGHUP)
        self.process.kill(signal.SIGINT)
      else:
        self.process.send_signal(signal.SIGTERM)


class Device(object):

  SECONDS_TO_SLEEP_DURING_ROOT = 0.5

  def __init__(self, serial_number, output_root, test_events, expected_result):
    """Responsible for monitoring a specific device, and pulling files from it.

    The actual work of the constructor will be handled asynchronously, you must
    call WaitForTasks() before using the device.

    Args:
      serial_number: The device serial number.
      output_root: The directory where to output log files/anything pulled from
          the device.
      test_events: The events (with conditions) that come from the StressTest
          that should be evaluated at every iteration, along with a list of
          actions to take when one of these events occur. For example, if there
          have not been any detected hotword triggers, a bugreport can be
          generated.
      expected_result: Expected event count to pass the test.
    """
    self.serial_number = serial_number
    self.output_root = output_root
    self.cmd_string_replacements = {}
    self.iteration = 0
    self.cmd_string_replacements["iteration"] = 0
    self.cmd_string_replacements["serial_number"] = serial_number
    self.cmd_string_replacements["output_root"] = output_root
    self.name = None
    self.process_loggers = []
    self.event_log = stress_test_pb2.EventLog()
    self.cnt_per_iteration = expected_result

    # Prepare the work queue, and offload the rest of the init into it.
    self.work_queue = queue.Queue()
    self.worker = threading.Thread(target=QueueWorker, args=[self.work_queue])
    self.worker.daemon = True
    self.worker.name = self.name
    self.worker.start()
    self.abort_requested = False
    self.remove_device = False
    self.test_events = test_events

    self.work_queue.put(self.__init_async__)

  def __init_async__(self):
    # Get the device type, and append it to the serial number.
    self.device_type = self.Command(["shell", "getprop",
                                     "ro.product.name"]).strip().decode("utf-8")
    self.name = "%s_%s" % (self.device_type, self.serial_number)
    self.worker.name = self.name
    self.cmd_string_replacements["device"] = self.name
    logging.info("Setting up device %s", self.name)

    config = stress_test_common.LoadDeviceConfig(self.device_type,
                                                 self.serial_number)

    # Get the device ready.
    self.Root()

    # Run any setup commands.
    for cmd in config.setup_command:
      result = self.Command(
          shlex.split(cmd % self.cmd_string_replacements)).strip()
      if result:
        for line in result.splitlines():
          logging.info(line)

    self.files_to_move = config.file_to_move

    self.event_names = set([event.name for event in config.event])
    self.event_counter = {name: 0 for name in self.event_names}
    self.iterations_since_event = {name: 0 for name in self.event_names}

    for file_to_watch in config.file_to_watch:
      # Are there any events that match up with this file?
      events = [x for x in config.event if x.source == file_to_watch.source]

      if file_to_watch.source == "LOGCAT":
        command = [
            "adb", "-s", self.serial_number, "logcat", "-v", "usec", ""
        ]
        command.extend(["%s:S" % tag for tag in config.tag_to_suppress])
        name = "logcat_" + self.serial_number
      else:
        command = [
            "adb", "-s", self.serial_number, "shell",
            "while : ; do cat %s 2>&1; done" % file_to_watch.source
        ]
        name = "%s_%s" % (os.path.basename(
            file_to_watch.source), self.serial_number)

      process_logger = ProcessLogger(
          name, command, os.path.join(
              self.output_root,
              file_to_watch.destination % self.cmd_string_replacements),
          events, True, file_to_watch.repeats_output_on_open)
      self.process_loggers.append(process_logger)
      process_logger.start()

    # Add any of the background processes.
    for daemon_process in config.daemon_process:
      # Are there any events that match up with this file?
      events = [x for x in config.event if x.source == daemon_process.name]
      command = shlex.split(
          daemon_process.command % self.cmd_string_replacements)
      if daemon_process.destination:
        output = os.path.join(
            self.output_root,
            daemon_process.destination % self.cmd_string_replacements)
      else:
        output = None
      name = "%s_%s" % (daemon_process.name, self.serial_number)
      process_logger = ProcessLogger(name, command, output, events,
                                     daemon_process.restart,
                                     daemon_process.repeats_output_on_open)
      self.process_loggers.append(process_logger)
      process_logger.start()

    # Build up the list of events we can actually process.
    self.__UpdateEventCounters(number_of_iterations=0)
    test_events = self.test_events
    self.test_events = []
    for event in test_events:
      try:
        eval(event.condition,  # pylint:disable=eval-used
             {"__builtins__": None}, self.__ValuesInEval())
        self.test_events.append(event)
      except Exception as err:  # pylint:disable=broad-except
        logging.error("Test event %s is not compatible with %s", event.name,
                      self.name)
        logging.error(str(err))
    # Make sure that device specific events don't have conditions.
    self.device_events = []
    for event in config.test_event:
      if not event.name:
        logging.error("Device %s test event is missing a name", self.name)
        continue
      if event.condition:
        self.test_events.append(event)
      else:
        self.device_events.append(event)

  def StartLookingForEvents(self):
    """Starts all child ProcessLoggers to start looking for events."""
    for process_logger in self.process_loggers:
      process_logger.looking = True

  def __ValuesInEval(self):
    values_in_eval = {key: value for key, value
                      in list(self.event_counter.items())}
    for key, value in list(self.iterations_since_event.items()):
      values_in_eval["iterations_since_%s" % key] = value
    return values_in_eval

  def __GetExpectedEventCount(self, event):
    if event == "logcat_iteration":
      return -1
    try:
      event_cnt = getattr(self.cnt_per_iteration, event)
    except AttributeError:
      event_cnt = -1
      logging.exception("%s is not an attribute of expected_result", event)
    return event_cnt

  def __UpdateEventCounters(self, number_of_iterations=1):
    # Update the event counters
    visited_events = set()
    error_log = []
    for process_logger in self.process_loggers:
      events = process_logger.GetEventCountsSinceLastCall()
      for event, count in list(events.items()):
        # Print log when there is any missed event
        expected_count = self.__GetExpectedEventCount(event)

        if expected_count > 0:
          if count > expected_count * number_of_iterations:
            logging.info(
                "[STRESS_TEST] In iteration %d, got duplicated %s : %d",
                self.iteration, self.name, count)
            logging.info("[STRESS_TEST] Will count only : %d",
                         expected_count * number_of_iterations)
            count = expected_count * number_of_iterations

        if count:
          self.event_counter[event] += count
          visited_events.add(event)

        if expected_count >= 0:
          if expected_count * number_of_iterations != count:
            error_log.append(
                _SUMMARY_COL_FORMATT %
                (event, count, expected_count * number_of_iterations))

    # Go clear all the events that weren't consecutive.
    for event in self.iterations_since_event:
      if event in visited_events:
        self.iterations_since_event[event] = 0
      else:
        self.iterations_since_event[event] += number_of_iterations

    if error_log:
      logging.info(_SUMMARY_LINES)
      logging.info(" iteration %d : Something wrong in %s.",
                   self.iteration, self.name)
      logging.info(_SUMMARY_LINES)
      logging.info(_SUMMARY_COLUMNS)
      logging.info(_SUMMARY_LINES)
      for line in error_log:
        logging.info(line)
      logging.info(_SUMMARY_LINES)

  def ProcessEvents(self):
    """Updates the event_counter and iterations_since_event maps."""
    self.work_queue.put(self.__ProcessEventsAsync)

  def __ProcessEventsAsync(self):
    # Move any files to the local machine that should be moved.
    if self.files_to_move:
      for file_to_move in self.files_to_move:
        try:
          self.Command(["pull", file_to_move.source, file_to_move.destination])
        except:  # pylint:disable=bare-except
          logging.exception("Failed to pull %s", file_to_move.source)

    self.__UpdateEventCounters()

    for event in self.test_events:
      if eval(event.condition,  # pylint:disable=eval-used
              {"__builtins__": None}, self.__ValuesInEval()):
        logging.info("Condition has been met for event '%s'", event.name)
        # Write the updated event log.
        event_log_details = self.event_log.event.add()
        event_log_details.iteration = self.iteration
        event_log_details.name = event.name
        with open(os.path.join(self.output_root,
                               "%s_event_log.ascii_proto" % self.name),
                  "w") as fp:
          text_format.PrintMessage(self.event_log, fp)

        # Do whatever other actions that are part of the event.
        self.__ProcessEventActionQueue(event)

        # Run any device specific actions for this event.
        for device_event in self.device_events:
          if device_event.name == event.name:
            self.__ProcessEventActionQueue(device_event)

    # Set up the next iteration.
    self.iteration += 1
    self.cmd_string_replacements["iteration"] = self.iteration

  def __ProcessEventActionQueue(self, event):
    bugreport = None
    for action in event.action:
      if action == "BUGREPORT":
        bugreport = self.TakeBugReport()
      elif action.startswith("DUMPSYS "):
        self.CaptureDumpsys(action[action.find(" ") + 1:])
      elif action == "NOTIFY":
        SendNotificationEmail(
            "%s had event '%s' occur" % (self.name, event.name),
            "\n".join(["Current Summary:"] + self.GetSummaryLines()), bugreport)
      elif action == "REMOVE_DEVICE":
        logging.info("Removing %s from the test", self.serial_number)
        self.remove_device = True
      elif action == "ABORT":
        logging.info("Abort requested")
        self.abort_requested = True
      else:
        action %= self.cmd_string_replacements
        logging.info("Running command %s on %s", action, self.name)
        result = self.Command(shlex.split(action)).strip()
        if result:
          for line in result.splitlines():
            logging.info(line)

  def Root(self):
    self.Command(["root"])
    time.sleep(Device.SECONDS_TO_SLEEP_DURING_ROOT)
    self.Command(["wait-for-device"])
    time.sleep(Device.SECONDS_TO_SLEEP_DURING_ROOT)

  def Stop(self):
    """Stops all file loggers attached to this device."""
    for process_logger in self.process_loggers:
      process_logger.StopLogging()
    self.process_loggers = []

  def Join(self):
    for process_logger in self.process_loggers:
      process_logger.join()
    self.WaitForTasks()

  def AsyncCommand(self, command, log_output=False):
    self.work_queue.put(
        lambda: self.__AsyncCommand(command, log_output=log_output))

  def __AsyncCommand(self, command, log_output=False):
    result = self.Command(command).strip()
    if result and log_output:
      for line in result.splitlines():
        logging.info(line.decode("utf-8"))

  def Command(self, command):
    """Runs the provided command on this device."""
    if command[0] in {"bugreport", "root", "wait-for-device", "shell",
                      "logcat"}:
      return subprocess.check_output(
          ["adb", "-s", self.serial_number] + command)
    elif command[0] == "DUMPSYS":
      self.CaptureDumpsys(command[1])
      return ""
    elif command[0] == "pull":
      try:
        files = subprocess.check_output(
            ["adb", "-s", self.serial_number, "shell", "ls", command[1]]
        ).strip().splitlines()
      except subprocess.CalledProcessError:
        return ""
      if len(files) == 1 and "No such file or directory" in files[0]:
        return ""
      for source_file in files:
        destination = os.path.join(self.output_root,
                                   command[2] % self.cmd_string_replacements)
        stress_test_common.MakeDirsIfNeeded(os.path.dirname(destination))
        logging.info("Moving %s from %s to %s", source_file, self.name,
                     destination)
        subprocess.check_output(["adb", "-s", self.serial_number, "pull",
                                 source_file, destination])
        if FLAGS.delete_data_dir:
          subprocess.check_output([
              "adb", "-s", self.serial_number, "shell", "rm", "-rf", source_file
          ])
        return ""
    else:
      return subprocess.check_output(command)

  def TakeBugReport(self):
    logging.info("Capturing bugreport on %s", self.name)
    bugreport = os.path.join(self.output_root,
                             "%s_bugreport_iteration_%06d.zip" %
                             (self.name, self.iteration))
    sdk = int(self.Command(
        ["shell", "getprop", "ro.build.version.sdk"]).strip())
    if sdk >= 24:  # SDK 24 = Android N
      with open(bugreport, "w") as bugreport_fp:
        bugreport_fp.write(self.Command(["bugreport", bugreport]))
    else:
      bugreport_txt = os.path.join(self.output_root,
                                   "%s_bugreport_iteration_%06d.txt" %
                                   (self.name, self.iteration))
      with open(bugreport_txt, "w") as bugreport_fp:
        bugreport_fp.write(self.Command(["bugreport"]))
      self.Command(["zip", bugreport, bugreport_txt])

    self.Command(["pull", "/data/anr/traces.txt",
                  "%s_traces_iteration_%06d.txt" % (self.name, self.iteration)])
    self.Command(["pull", "/data/anr/traces.txt.bugreport",
                  "%s_traces_iteration_%06d.txt.bugreport" % (self.name,
                                                              self.iteration)])
    return bugreport

  def CaptureDumpsys(self, dumpsys_unit):
    logging.info("Taking dumpsys %s on %s", dumpsys_unit, self.name)
    stress_test_common.MakeDirsIfNeeded(os.path.join(self.output_root,
                                                     self.name))
    with open(os.path.join(self.output_root, self.name,
                           "%s_%06d.txt" % (dumpsys_unit, self.iteration)),
              "w") as dumpsys_fp:
      dumpsys_fp.write(self.Command(["shell", "dumpsys", dumpsys_unit]))

  def WaitForTasks(self):
    self.work_queue.join()

  def GetSummaryLines(self):
    lines = [
        "Device {}".format(self.name),
        _SUMMARY_LINES, _SUMMARY_COLUMNS, _SUMMARY_LINES
    ]
    for event, count in sorted(self.event_counter.items()):
      lines.append(_SUMMARY_COL_FORMATT % (
          event, count, self.iterations_since_event[event]))
    lines.append(_SUMMARY_LINES)
    return lines


def RunAsyncCommand(devices, command):
  """Helper function for running async commands on many devices."""
  for device in devices:
    device.AsyncCommand(command)
  for device in devices:
    device.WaitForTasks()


class StressTest(object):
  """Manages dispatching commands to devices/playing audio and events."""

  def __init__(self, output_root, test_name):
    self.output_root = output_root
    self.devices = []
    self.test_name = test_name
    config = stress_test_pb2.StressTestConfig()
    config_contents = stress_test_common.GetResourceContents(
        os.path.join(stress_test_common.RESOURCE_DIR,
                     "stress_test.%s.ascii_proto" % test_name))
    text_format.Merge(config_contents, config)
    self.events = config.event
    self.setup_commands = config.setup_command
    self.steps = config.step
    self.audio_tempfiles = {}
    self.uuid = str(uuid.uuid4())
    self.expected_result = None
    self.iteration = 0
    if config.expected_result:
      self.expected_result = config.expected_result[0]

    # Place all the audio files into temp files.
    for step in self.steps:
      if step.audio_file and step.audio_file not in self.audio_tempfiles:
        # We can't delete the temp file on windows, since it gets nuked too
        # early.
        audio_tempfile = tempfile.NamedTemporaryFile(
            delete=(platform.system() != "Windows"),
            dir="." if platform.system().startswith("CYGWIN") else None
        )
        if platform.system().startswith("CYGWIN"):
          audio_tempfile.name = os.path.basename(audio_tempfile.name)
        self.audio_tempfiles[step.audio_file] = audio_tempfile
        if FLAGS.use_sox:
          # Write out the raw PCM samples as a wave file.
          audio_tempfile.write(
              stress_test_common.GetResourceContents(step.audio_file))
        else:
          # Make a temporary wave file for playout if we can't use sox.
          wavefile = wave.open(audio_tempfile, "wb")
          if step.audio_file_sample_rate <= 0:
            step.audio_file_sample_rate = 16000
          wavefile.setframerate(step.audio_file_sample_rate)
          if step.audio_file_num_channels <= 0:
            step.audio_file_num_channels = 1
          wavefile.setnchannels(step.audio_file_num_channels)
          if not step.audio_file_format:
            wavefile.setsampwidth(2)
          elif step.audio_file_format == "s8":
            wavefile.setsampwidth(1)
          elif step.audio_file_format == "s16":
            wavefile.setsampwidth(2)
          elif step.audio_file_format == "s32":
            wavefile.setsampwidth(4)
          else:
            raise RuntimeError(
                "Unsupported wave file format for %s" % step.audio_file)
          wavefile.writeframes(stress_test_common.GetResourceContents(
              step.audio_file))
          wavefile.close()
        audio_tempfile.flush()

        if platform.system() == "Windows":
          audio_tempfile.close()

    # Create all the devices that are attached to this machine.
    for serial_number in self.GetActiveSerialNumbers():
      self.devices.append(
          Device(serial_number, output_root, self.events, self.expected_result))
    if not self.devices:
      raise app.UsageError("No devices connected")

    self.devices.sort(key=lambda x: x.name)

    # Make sure every device is done with their work for setup.
    for device in self.devices:
      device.WaitForTasks()

    # Write out the info meta-data proto. Useful for doing analysis of the logs
    # after the stress test has completed.
    stress_test_info = stress_test_pb2.StressTestInfo()
    stress_test_info.test_name = self.test_name
    stress_test_info.test_description = config.description
    stress_test_info.uuid = self.uuid
    for device in self.devices:
      device_pb = stress_test_info.device.add()
      device_pb.device_type = device.device_type
      device_pb.serial_number = device.serial_number

    text_format.PrintMessage(stress_test_info, open(os.path.join(
        self.output_root, "stress_test_info.ascii_proto"), "w"))

  def GetActiveSerialNumbers(self):
    serial_numbers = []
    for line in sorted(
        subprocess.check_output(["adb", "devices"]).splitlines()):
      if line.endswith(b"device"):
        serial_number = line.split()[0].strip()
        if FLAGS.devices and serial_number not in FLAGS.devices:
          continue
        serial_numbers.append(serial_number.decode("utf-8"))
    return serial_numbers

  def Start(self):
    logging.info("Waiting for devices to settle")
    time.sleep(5)
    # Make a copy of the device list, as we'll be modifying this actual list.
    devices = list(self.devices)
    dropped_devices = []

    # If we have any setup commands, run them.
    for command in self.setup_commands:
      logging.info("Running command %s", command)
      # Can't use the async command helper function since we need to get at
      # the device cmd_string_replacements.
      for device in devices:
        device.AsyncCommand(
            shlex.split(command % device.cmd_string_replacements),
            log_output=True)
      for device in devices:
        device.WaitForTasks()

    for device in devices:
      device.StartLookingForEvents()
      device.AsyncCommand(["shell", "log", "-t", "STRESS_TEST",
                           "Starting {%s} TZ=$(getprop persist.sys.timezone) "
                           "YEAR=$(date +%%Y)" % self.uuid], True)
    self.iteration = 0
    while True:
      logging.info("Starting iteration %d", self.iteration)
      # Perform all the actions specified in the test.
      RunAsyncCommand(devices, [
          "shell", "log", "-t", "STRESS_TEST",
          "Performing iteration %d $(head -n 3 "
          "/proc/timer_list | tail -n 1)" % self.iteration
      ])

      for step in self.steps:
        if step.delay_before:
          logging.info("Waiting for %.2f seconds", step.delay_before)
          time.sleep(step.delay_before)

        if step.audio_file:
          logging.info("Playing %s", step.audio_file)
          RunAsyncCommand(devices, ["shell", "log", "-t", "STRESS_TEST",
                                    "Playing %s" % step.audio_file])

          if FLAGS.use_sox:
            subprocess.check_call(["sox", "-q",
                                   self.audio_tempfiles[step.audio_file].name,
                                   "-d"])
          elif platform.system() == "Windows":
            import winsound  # pylint:disable=g-import-not-at-top
            winsound.PlaySound(self.audio_tempfiles[step.audio_file].name,
                               winsound.SND_FILENAME | winsound.SND_NODEFAULT)
          else:
            raise app.RuntimeError("Unsupported platform for audio playback")

        if step.command:
          logging.info("Running command %s", step.command)
          # Can't use the async command helper function since we need to get at
          # the device cmd_string_replacements.
          for device in devices:
            device.AsyncCommand(
                shlex.split(step.command % device.cmd_string_replacements),
                log_output=True)
          for device in devices:
            device.WaitForTasks()

        if step.delay_after:
          logging.info("Waiting for %.2f seconds", step.delay_after)
          time.sleep(step.delay_after)

      RunAsyncCommand(devices, [
          "shell", "log", "-t", "STRESS_TEST",
          "Iteration %d complete $(head -n 3 "
          "/proc/timer_list | tail -n 1)" % self.iteration
      ])
      self.iteration += 1

      # TODO(somebody): Sometimes the logcat seems to get stuck and buffers for
      # a bit. This throws off the event counts, so we should probably add some
      # synchronization rules before we trigger any events.

      # Go through each device, update the event counter, and see if we need to
      # trigger any events.
      devices_to_remove = []
      abort_requested = False
      active_devices = self.GetActiveSerialNumbers()
      for device in devices:
        if device.serial_number in active_devices:
          device.ProcessEvents()
        else:
          logging.error("Dropped device %s", device.name)
          SendNotificationEmail(
              "Dropped device %s" % device.name,
              "Device %s is not longer present in the system" % device.name)
          dropped_devices.append(device)
          devices_to_remove.append(device)

      # Check to see if any of the dropped devices have come back. If yes, grab
      # a bug report.
      for device in dropped_devices:
        if device.serial_number in active_devices:
          logging.info("Device %s reappeared", device.name)
          device.Root()
          device.TakeBugReport()

      dropped_devices = [d for d in dropped_devices
                         if d.serial_number not in active_devices]

      for device in devices:
        device.WaitForTasks()
        if device.remove_device:
          devices_to_remove.append(device)
        if device.abort_requested:
          abort_requested = True

      # Remove devices from our list of things to monitor if they've been marked
      # for deletion.
      if devices_to_remove:
        for device in devices_to_remove:
          device.Stop()
        devices = [d for d in devices if d not in devices_to_remove]

      # Print out the iteration summary.
      if self.iteration % FLAGS.print_summary_every_n == 0:
        for line in self.GetSummaryLines():
          logging.info(line)

      # See if we need to break out of the outer loop.
      if abort_requested or not devices:
        break
      if FLAGS.num_iterations:
        if self.iteration >= FLAGS.num_iterations:
          logging.info("Completed full iteration : %d", self.iteration)
          break
    SendNotificationEmail(
        "Stress test %s completed" % (FLAGS.test_name),
        "\n".join(["Summary:"] + self.GetSummaryLines()))

  def Stop(self):
    logging.debug("Stopping devices")
    for device in self.devices:
      device.Stop()
    for device in self.devices:
      device.Join()

  def GetSummaryLines(self):
    lines = [
        _SUMMARY_LINES,
        "Conducted %d iterations out of %d" %
        (self.iteration, FLAGS.num_iterations),
        _SUMMARY_LINES
    ]
    for device in self.devices:
      lines.extend(device.GetSummaryLines())
    lines.append(_SUMMARY_LINES)
    return lines


def main(unused_argv):
  # Check to make sure that there are no other instances of ADB running - if
  # there are, print a warning and wait a bit for them to see it and decide if
  # they want to keep running, knowing that logs may be invalid.
  try:
    if "adb" in subprocess.check_output(["ps", "-ale"]).decode("utf-8"):
      print("It looks like there are other instances of adb running. If these "
            "other instances are also cating log files, you will not be "
            "capturing everything in this stress test (so logs will be "
            "invalid).")
      print("Continuing in 3...", end=" ")
      sys.stdout.flush()
      for i in [2, 1, 0]:
        time.sleep(1)
        if i:
          print("%d..." % i, end=" ")
        else:
          print("")
        sys.stdout.flush()
  except OSError:
    print("Unexpected error:", sys.exc_info()[0])
    if sys.platform.startswith("win"):
      pass
    else:
      raise

  # Make the base output directory.
  output_root = os.path.join(FLAGS.output_root, "%s_%s" % (
      FLAGS.test_name, datetime.datetime.now().strftime("%Y%m%d_%H%M%S")))
  # output_root = os.path.join(FLAGS.output_root, FLAGS.test_name)
  stress_test_common.MakeDirsIfNeeded(output_root)

  # Set up logging.
  formatter = logging.Formatter(
      "%(levelname)-1.1s %(asctime)s [%(threadName)-16.16s] %(message)s")
  root_logger = logging.getLogger()
  root_logger.setLevel(logging.INFO)
  root_logger.setLevel(logging.DEBUG)

  file_handler = logging.FileHandler(os.path.join(output_root,
                                                  "stress_test.log"))
  file_handler.setFormatter(formatter)
  root_logger.addHandler(file_handler)

  console_handler = logging.StreamHandler()
  console_handler.setFormatter(formatter)
  root_logger.addHandler(console_handler)

  stress_test = StressTest(output_root, FLAGS.test_name)
  try:
    stress_test.Start()
  finally:
    logging.info("Stopping device logging threads")
    stress_test.Stop()
    for line in stress_test.GetSummaryLines():
      logging.info(line)
    if FLAGS.delete_data_dir:
      print("Deleting Data Dir")
      subprocess.check_output(["rm", "-r", "-f", output_root])


if __name__ == "__main__":
  app.run(main)
