# Copyright 2015 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.


import collections
import contextlib
import hashlib
import json
import logging
import os
import pickle
import posixpath
import re
import shutil
import sys
import tempfile
import time

from devil import base_error
from devil.android import apk_helper
from devil.android import crash_handler
from devil.android import device_errors
from devil.android import device_temp_file
from devil.android import flag_changer
from devil.android.sdk import version_codes
from devil.android import logcat_monitor
from devil.android.tools import system_app
from devil.android.tools import webview_app
from devil.utils import reraiser_thread
from incremental_install import installer
from pylib import constants
from pylib import valgrind_tools
from pylib.base import base_test_result
from pylib.base import output_manager
from pylib.constants import host_paths
from pylib.instrumentation import instrumentation_parser
from pylib.instrumentation import instrumentation_test_instance
from pylib.local.device import local_device_environment
from pylib.local.device import local_device_test_run
from pylib.output import remote_output_manager
from pylib.symbols import stack_symbolizer
from pylib.utils import chrome_proxy_utils
from pylib.utils import code_coverage_utils
from pylib.utils import gold_utils
from pylib.utils import instrumentation_tracing
from pylib.utils.device_dependencies import DevicePathComponentsFor
from py_trace_event import trace_event
from py_trace_event import trace_time
from py_utils import contextlib_ext
from py_utils import tempfile_ext
import tombstones

with host_paths.SysPath(
    os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party'), 0):
  import jinja2  # pylint: disable=import-error
  import markupsafe  # pylint: disable=import-error,unused-import

_CHROMIUM_TESTS_ROOT = 'chromium_tests_root'
_DEVICE_TEMP_DIR_DATA_ROOT = posixpath.join('/data/local/tmp',
                                            _CHROMIUM_TESTS_ROOT)
_JINJA_TEMPLATE_DIR = os.path.join(
    host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'pylib', 'instrumentation')
_JINJA_TEMPLATE_FILENAME = 'render_test.html.jinja'

_WPR_GO_LINUX_X86_64_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT,
                                         'third_party', 'webpagereplay', 'bin',
                                         'linux', 'x86_64', 'wpr')

_TAG = 'test_runner_py'

TIMEOUT_ANNOTATIONS = [
    ('Manual', 10 * 60 * 60),
    ('IntegrationTest', 10 * 60),
    ('External', 10 * 60),
    ('EnormousTest', 5 * 60),
    ('LargeTest', 2 * 60),
    ('MediumTest', 30),
    ('SmallTest', 10),
]

# Account for Instrumentation and process init overhead.
FIXED_TEST_TIMEOUT_OVERHEAD = 60

# 30 minute max timeout for an instrumentation invocation to avoid shard
# timeouts when tests never finish. The shard timeout is currently 60 minutes,
# so this needs to be less than that.
MAX_BATCH_TEST_TIMEOUT = 30 * 60

LOGCAT_FILTERS = ['*:e', 'chromium:v', 'cr_*:v', 'DEBUG:I',
                  'StrictMode:D', '%s:I' % _TAG]

EXTRA_CLANG_COVERAGE_DEVICE_FILE = (
    'BaseChromiumAndroidJUnitRunner.ClangCoverageDeviceFile')

EXTRA_SCREENSHOT_FILE = (
    'org.chromium.base.test.ScreenshotOnFailureStatement.ScreenshotFile')

EXTRA_UI_CAPTURE_DIR = (
    'org.chromium.base.test.util.Screenshooter.ScreenshotDir')

EXTRA_TRACE_FILE = 'BaseChromiumAndroidJUnitRunner.TraceFile'

_EXTRA_RUN_DISABLED_TEST = (
    'org.chromium.base.test.util.DisableIfSkipCheck.RunDisabledTest')

_EXTRA_TEST_IS_UNIT = 'BaseChromiumAndroidJUnitRunner.IsUnitTest'

_EXTRA_PACKAGE_UNDER_TEST = ('org.chromium.chrome.test.pagecontroller.rules.'
                             'ChromeUiApplicationTestRule.PackageUnderTest')

FEATURE_ANNOTATION = 'Feature'
RENDER_TEST_FEATURE_ANNOTATION = 'RenderTest'
WPR_ARCHIVE_FILE_PATH_ANNOTATION = 'WPRArchiveDirectory'
WPR_ARCHIVE_NAME_ANNOTATION = 'WPRArchiveDirectory$ArchiveName'
WPR_RECORD_REPLAY_TEST_FEATURE_ANNOTATION = 'WPRRecordReplayTest'

_DEVICE_GOLD_DIR = 'skia_gold'
# A map of Android product models to SDK ints.
RENDER_TEST_MODEL_SDK_CONFIGS = {
    # Android x86 emulator.
    'Android SDK built for x86': [24, 26],
    # We would like this to be supported, but it is currently too prone to
    # introducing flakiness due to a combination of Gold and Chromium issues.
    # See crbug.com/1233700 and skbug.com/12149 for more information.
    # 'Pixel 2': [28],
}

_BATCH_SUFFIX = '_batch'
# If the batch is too big it starts to fail for command line length reasons.
_LOCAL_TEST_BATCH_MAX_GROUP_SIZE = 200

_PICKLE_FORMAT_VERSION = 12


class _TestListPickleException(Exception):
  pass


def _LoadTestsFromPickle(pickle_path, test_mtime, pickle_extras):
  if not os.path.exists(pickle_path):
    raise _TestListPickleException('%s does not exist.' % pickle_path)
  if os.path.getmtime(pickle_path) <= test_mtime:
    raise _TestListPickleException('File is stale: %s' % pickle_path)

  with open(pickle_path, 'rb') as f:
    pickle_data = pickle.load(f)
  if pickle_data['VERSION'] != _PICKLE_FORMAT_VERSION:
    raise _TestListPickleException('PICKLE_FORMAT_VERSION has changed.')
  if pickle_data.get('EXTRAS') != pickle_extras:
    raise _TestListPickleException('PICKLE EXTRAS has changed.')
  return pickle_data['TEST_METHODS']


def _SaveTestsToPickle(pickle_path, tests, pickle_extras):
  pickle_data = {
      'VERSION': _PICKLE_FORMAT_VERSION,
      'EXTRAS': pickle_extras,
      'TEST_METHODS': tests,
  }
  with open(pickle_path, 'wb') as pickle_file:
    pickle.dump(pickle_data, pickle_file)


@contextlib.contextmanager
def _LogTestEndpoints(device, test_name):
  device.RunShellCommand(
      ['log', '-p', 'i', '-t', _TAG, 'START %s' % test_name],
      check_return=True)
  try:
    yield
  finally:
    device.RunShellCommand(
        ['log', '-p', 'i', '-t', _TAG, 'END %s' % test_name],
        check_return=True)


@contextlib.contextmanager
def _VoiceInteractionService(device, use_voice_interaction_service):
  def set_voice_interaction_service(service):
    device.RunShellCommand(
        ['settings', 'put', 'secure', 'voice_interaction_service', service])

  default_voice_interaction_service = None
  try:
    default_voice_interaction_service = device.RunShellCommand(
        ['settings', 'get', 'secure', 'voice_interaction_service'],
        single_line=True)

    set_voice_interaction_service(use_voice_interaction_service)
    yield
  finally:
    set_voice_interaction_service(default_voice_interaction_service)


def DismissCrashDialogs(device):
  # Dismiss any error dialogs. Limit the number in case we have an error
  # loop or we are failing to dismiss.
  packages = set()
  try:
    for _ in range(10):
      package = device.DismissCrashDialogIfNeeded(timeout=10, retries=1)
      if not package:
        break
      packages.add(package)
  except device_errors.CommandFailedError:
    logging.exception('Error while attempting to dismiss crash dialog.')
  return packages


_CURRENT_FOCUS_CRASH_RE = re.compile(
    r'\s*mCurrentFocus.*Application (Error|Not Responding): (\S+)}')


def _GetTargetPackageName(test_apk):
  # apk_under_test does not work for smoke tests, where it is set to an
  # apk that is not listed as the targetPackage in the test apk's manifest.
  return test_apk.GetAllInstrumentations()[0]['android:targetPackage']


def _ParseTestListOutputFromChromiumListener(output):
  parser = instrumentation_parser.InstrumentationParser(output)
  tests_by_class = collections.defaultdict(list)
  annotations_by_class = {}
  for code, bundle in parser.IterStatus():
    # Code used only by TestListInstrumentationRunListener.
    if code == 5:
      if 'class' in bundle:
        cur_class = bundle['class']
        annotations_by_class[cur_class] = json.loads(
            bundle['class_annotations'])
      tests_by_class[cur_class].append({
          'method':
          bundle['method'],
          'annotations':
          json.loads(bundle['method_annotations']),
      })
    elif 'class' in bundle and 'current' in bundle:
      # From AndroidX Listener.
      # Both listeners are active for APKs built in chromium that do not use
      # BaseChromiumAndroidJUnitRunner for instrumentation (e.g. to be
      # compatible with other build systems).
      continue
    elif code == -1:
      # RESULT_OK
      continue
    else:
      logging.warning('Unexpected code=%s output: %r', code, bundle)

  # GetResult() cannot be called before IterStatus().
  code, result = parser.GetResult()
  if code != instrumentation_parser.RESULT_CODE_OK:
    raise Exception('Test listing failed: %s' % result.get('stream', result))
  return [{
      'class': class_name,
      'methods': methods,
      'annotations': annotations_by_class[class_name],
  } for class_name, methods in tests_by_class.items()]


def _ParseTestListOutputFromAndroidxListener(output):
  parser = instrumentation_parser.InstrumentationParser(output)
  tests_by_class = collections.defaultdict(list)
  for code, bundle in parser.IterStatus():
    if 'class' in bundle and 'current' in bundle:
      # AndroidX's InstrumentationResultPrinter uses:
      # code=0 for start
      # code=1 for finished
      # code=-3 for ignored.
      if code == 1:
        class_name = bundle.get('class')
        method_name = bundle.get('test')
        # TODO(crbug.com/326260748): Handle spaces in names.
        if any(c in method_name for c in ' *-:'):
          logging.warning('Ignoring method with invalid chars: %s.%s',
                          class_name, method_name)
          continue
        if class_name and method_name:
          tests_by_class[class_name].append({
              'method': method_name,
              'annotations': {},
          })
    elif code == -1:
      # RESULT_OK
      continue
    else:
      logging.warning('Unexpected code=%s output: %r', code, bundle)
  # GetResult() cannot be called before IterStatus().
  code, result = parser.GetResult()
  if code != instrumentation_parser.RESULT_CODE_OK:
    raise Exception('Test listing failed: %s' % result.get('stream', result))
  return [{
      'class': class_name,
      'methods': methods,
      'annotations': {}
  } for class_name, methods in tests_by_class.items()]


class LocalDeviceInstrumentationTestRun(
    local_device_test_run.LocalDeviceTestRun):
  def __init__(self, env, test_instance):
    super().__init__(env, test_instance)
    self._chrome_proxy = None
    self._context_managers = collections.defaultdict(list)
    self._flag_changers = {}
    self._webview_flag_changers = {}
    self._render_tests_device_output_dir = None
    self._skia_gold_session_manager = None
    self._skia_gold_work_dir = None

  #override
  def TestPackage(self):
    return self._test_instance.suite

  #override
  def SetUp(self):
    target_package = _GetTargetPackageName(self._test_instance.test_apk)

    @local_device_environment.handle_shard_failures_with(
        self._env.DenylistDevice)
    @trace_event.traced
    def individual_device_set_up(device, host_device_tuples):
      # Functions to run concurrerntly when --concurrent-adb is enabled.
      install_steps = []
      post_install_steps = []

      test_data_root_dir = posixpath.join(device.GetExternalStoragePath(),
                                          _CHROMIUM_TESTS_ROOT)
      if self._test_instance.store_data_dependencies_in_temp:
        test_data_root_dir = _DEVICE_TEMP_DIR_DATA_ROOT

      if self._test_instance.replace_system_package:
        @trace_event.traced
        def replace_package(dev):
          # We need the context manager to be applied before modifying any
          # shared preference files in case the replacement APK needs to be
          # set up, and it needs to be applied while the test is running.
          # Thus, it needs to be applied early during setup, but must still be
          # applied during _RunTest, which isn't possible using 'with' without
          # applying the context manager up in test_runner. Instead, we
          # manually invoke its __enter__ and __exit__ methods in setup and
          # teardown.
          system_app_context = system_app.ReplaceSystemApp(
              dev, self._test_instance.replace_system_package)
          # Pylint is not smart enough to realize that this field has
          # an __enter__ method, and will complain loudly.
          # pylint: disable=no-member
          system_app_context.__enter__()
          # pylint: enable=no-member
          self._context_managers[str(dev)].append(system_app_context)

        install_steps.append(replace_package)

      if self._test_instance.system_packages_to_remove:

        @trace_event.traced
        def remove_packages(dev):
          logging.info('Attempting to remove system packages %s',
                       self._test_instance.system_packages_to_remove)
          system_app.RemoveSystemApps(
              dev, self._test_instance.system_packages_to_remove)
          logging.info('Done removing system packages')

        # This should be at the front in case we're removing the package to make
        # room for another APK installation later on. Since we disallow
        # concurrent adb with this option specified, this should be safe.
        install_steps.insert(0, remove_packages)

      def install_helper(apk,
                         modules=None,
                         fake_modules=None,
                         permissions=None,
                         additional_locales=None,
                         instant_app=False):

        @instrumentation_tracing.no_tracing
        @trace_event.traced
        def install_helper_internal(d, apk_path=None):
          # pylint: disable=unused-argument
          d.Install(
              apk,
              modules=modules,
              fake_modules=fake_modules,
              permissions=permissions,
              additional_locales=additional_locales,
              instant_app=instant_app,
              force_queryable=self._test_instance.IsApkForceQueryable(apk))

        return install_helper_internal

      def install_apex_helper(apex):
        @instrumentation_tracing.no_tracing
        @trace_event.traced
        def install_helper_internal(d, apk_path=None):
          # pylint: disable=unused-argument
          d.InstallApex(apex)

        return install_helper_internal

      def incremental_install_helper(apk, json_path, permissions):

        @trace_event.traced
        def incremental_install_helper_internal(d, apk_path=None):
          # pylint: disable=unused-argument
          installer.Install(d, json_path, apk=apk, permissions=permissions)

        return incremental_install_helper_internal

      install_steps.extend(
          install_apex_helper(apex)
          for apex in self._test_instance.additional_apexs)

      install_steps.extend(
          install_helper(apk, instant_app=self._test_instance.IsApkInstant(apk))
          for apk in self._test_instance.additional_apks)

      permissions = self._test_instance.test_apk.GetPermissions()
      if self._test_instance.test_apk_incremental_install_json:
        if self._test_instance.test_apk_as_instant:
          raise Exception('Test APK cannot be installed as an instant '
                          'app if it is incremental')

        install_steps.append(
            incremental_install_helper(
                self._test_instance.test_apk,
                self._test_instance.test_apk_incremental_install_json,
                permissions))
      else:
        install_steps.append(
            install_helper(self._test_instance.test_apk,
                           permissions=permissions,
                           instant_app=self._test_instance.test_apk_as_instant))

      # We'll potentially need the package names later for setting app
      # compatibility workarounds.
      for apk in (self._test_instance.additional_apks +
                  [self._test_instance.test_apk]):
        self._installed_packages.append(apk_helper.GetPackageName(apk))

      if self._test_instance.use_webview_provider:

        @trace_event.traced
        def use_webview_provider(dev):
          # We need the context manager to be applied before modifying any
          # shared preference files in case the replacement APK needs to be
          # set up, and it needs to be applied while the test is running.
          # Thus, it needs to be applied early during setup, but must still be
          # applied during _RunTest, which isn't possible using 'with' without
          # applying the context manager up in test_runner. Instead, we
          # manually invoke its __enter__ and __exit__ methods in setup and
          # teardown.
          # We do this after installing additional APKs so that
          # we can install trichrome library before installing the webview
          # provider
          webview_context = webview_app.UseWebViewProvider(
              dev, self._test_instance.use_webview_provider)
          # Pylint is not smart enough to realize that this field has
          # an __enter__ method, and will complain loudly.
          # pylint: disable=no-member
          webview_context.__enter__()
          # pylint: enable=no-member
          self._context_managers[str(dev)].append(webview_context)

        install_steps.append(use_webview_provider)

      if self._test_instance.use_voice_interaction_service:

        @trace_event.traced
        def use_voice_interaction_service(device):
          voice_interaction_service_context = _VoiceInteractionService(
              device, self._test_instance.use_voice_interaction_service)
          # Pylint is not smart enough to realize that this field has
          # an __enter__ method, and will complain loudly.
          # pylint: disable=no-member
          voice_interaction_service_context.__enter__()
          # pylint: enable=no-member
          self._context_managers[str(device)].append(
              voice_interaction_service_context)

        post_install_steps.append(use_voice_interaction_service)

      # The apk under test needs to be installed last since installing other
      # apks after will unintentionally clear the fake module directory.
      # TODO(wnwen): Make this more robust, fix crbug.com/1010954.
      if self._test_instance.apk_under_test:
        self._installed_packages.append(
            apk_helper.GetPackageName(self._test_instance.apk_under_test))
        permissions = self._test_instance.apk_under_test.GetPermissions()
        if self._test_instance.apk_under_test_incremental_install_json:
          install_steps.append(
              incremental_install_helper(
                  self._test_instance.apk_under_test,
                  self._test_instance.apk_under_test_incremental_install_json,
                  permissions))
        else:
          install_steps.append(
              install_helper(self._test_instance.apk_under_test,
                             self._test_instance.modules,
                             self._test_instance.fake_modules, permissions,
                             self._test_instance.additional_locales))

      # Execute any custom setup shell commands
      if self._test_instance.run_setup_commands:

        @trace_event.traced
        def run_setup_commands(dev):
          for cmd in self._test_instance.run_setup_commands:
            logging.info('Running custom setup shell command: %s', cmd)
            dev.RunShellCommand(cmd, shell=True, check_return=True)

        post_install_steps.append(run_setup_commands)

      @trace_event.traced
      def set_debug_app(dev):
        # Set debug app in order to enable reading command line flags on user
        # builds
        cmd = ['am', 'set-debug-app', '--persistent']
        if self._test_instance.wait_for_java_debugger:
          cmd.append('-w')
        cmd.append(target_package)
        dev.RunShellCommand(cmd, check_return=True)

      @trace_event.traced
      def approve_app_links(dev):
        self._ToggleAppLinks(dev, 'STATE_APPROVED')

      @trace_event.traced
      def set_vega_permissions(dev):
        # Normally, installation of VrCore automatically grants storage
        # permissions. However, since VrCore is part of the system image on
        # the Vega standalone headset, we don't install the APK as part of test
        # setup. Instead, grant the permissions here so that it can take
        # screenshots.
        if dev.product_name == 'vega':
          dev.GrantPermissions('com.google.vr.vrcore', [
              'android.permission.WRITE_EXTERNAL_STORAGE',
              'android.permission.READ_EXTERNAL_STORAGE'
          ])

      @instrumentation_tracing.no_tracing
      def push_test_data(dev):
        device_root = test_data_root_dir
        # Resolve the path only when need to manipulate data through adb shell
        # commands. Don't resolve if the path is passed to app through flags.
        if self._env.force_main_user:
          device_root = device.ResolveSpecialPath(device_root)
        host_device_tuples_substituted = [
            (h, local_device_test_run.SubstituteDeviceRoot(d, device_root))
            for h, d in host_device_tuples
        ]
        logging.info('Pushing data dependencies.')
        for h, d in host_device_tuples_substituted:
          logging.debug('  %r -> %r', h, d)
        dev.PlaceNomediaFile(device_root)
        dev.PushChangedFiles(host_device_tuples_substituted,
                             delete_device_stale=True,
                             as_root=self._env.force_main_user)
        if not host_device_tuples_substituted:
          dev.RunShellCommand(['rm', '-rf', device_root],
                              check_return=True,
                              as_root=self._env.force_main_user)
          dev.RunShellCommand(['mkdir', '-p', device_root],
                              check_return=True,
                              as_root=self._env.force_main_user)

      @trace_event.traced
      def create_flag_changer(dev):
        flags = self._test_instance.flags
        webview_flags = self._test_instance.webview_flags

        if '--webview-verbose-logging' not in webview_flags:
          webview_flags.append('--webview-verbose-logging')

        def _get_variations_seed_path_arg(seed_path):
          seed_path_components = DevicePathComponentsFor(seed_path)
          test_seed_path = local_device_test_run.SubstituteDeviceRoot(
              seed_path_components, test_data_root_dir)
          return '--variations-test-seed-path={0}'.format(test_seed_path)

        if self._test_instance.variations_test_seed_path:
          flags.append(
              _get_variations_seed_path_arg(
                  self._test_instance.variations_test_seed_path))

        if self._test_instance.webview_variations_test_seed_path:
          webview_flags.append(
              _get_variations_seed_path_arg(
                  self._test_instance.webview_variations_test_seed_path))

        if flags or webview_flags:
          self._CreateFlagChangersIfNeeded(dev)

        if flags:
          logging.debug('Attempting to set flags: %r', flags)
          self._flag_changers[str(dev)].AddFlags(flags)

        if webview_flags:
          logging.debug('Attempting to set WebView flags: %r', webview_flags)
          self._webview_flag_changers[str(dev)].AddFlags(webview_flags)

        valgrind_tools.SetChromeTimeoutScale(
            dev, self._test_instance.timeout_scale)

      install_steps += [push_test_data, create_flag_changer]
      post_install_steps += [
          set_debug_app, approve_app_links, set_vega_permissions,
          DismissCrashDialogs
      ]

      def bind_crash_handler(step, dev):
        return lambda: crash_handler.RetryOnSystemCrash(step, dev)

      install_steps = [bind_crash_handler(s, device) for s in install_steps]
      post_install_steps = [
          bind_crash_handler(s, device) for s in post_install_steps
      ]

      try:
        if self._env.concurrent_adb:
          reraiser_thread.RunAsync(install_steps)
          reraiser_thread.RunAsync(post_install_steps)
        else:
          for step in install_steps + post_install_steps:
            step()
        if self._test_instance.store_tombstones:
          tombstones.ClearAllTombstones(device)
      except device_errors.CommandFailedError:
        if not device.IsOnline():
          raise

        # A bugreport can be large and take a while to generate, so only capture
        # one if we're using a remote manager.
        if isinstance(
            self._env.output_manager,
            remote_output_manager.RemoteOutputManager):
          logging.error(
              'Error when setting up device for tests. Taking a bugreport for '
              'investigation. This may take a while...')
          report_name = '%s.bugreport' % device.serial
          with self._env.output_manager.ArchivedTempfile(
              report_name, 'bug_reports') as report_file:
            device.TakeBugReport(report_file.name)
          logging.error('Bug report saved to %s', report_file.Link())
        raise

    self._env.parallel_devices.pMap(
        individual_device_set_up,
        self._test_instance.GetDataDependencies())
    # Created here instead of on a per-test basis so that the downloaded
    # expectations can be re-used between tests, saving a significant amount
    # of time.
    self._skia_gold_work_dir = tempfile.mkdtemp()
    self._skia_gold_session_manager = gold_utils.AndroidSkiaGoldSessionManager(
        self._skia_gold_work_dir, self._test_instance.skia_gold_properties)
    if self._test_instance.wait_for_java_debugger:
      logging.warning('*' * 80)
      logging.warning('Waiting for debugger to attach to process: %s',
                      target_package)
      logging.warning('*' * 80)

  #override
  def TearDown(self):
    shutil.rmtree(self._skia_gold_work_dir)
    self._skia_gold_work_dir = None
    self._skia_gold_session_manager = None
    # By default, teardown will invoke ADB. When receiving SIGTERM due to a
    # timeout, there's a high probability that ADB is non-responsive. In these
    # cases, sending an ADB command will potentially take a long time to time
    # out. Before this happens, the process will be hard-killed for not
    # responding to SIGTERM fast enough.
    if self._received_sigterm:
      return

    @local_device_environment.handle_shard_failures_with(
        self._env.DenylistDevice)
    @trace_event.traced
    def individual_device_tear_down(dev):
      if str(dev) in self._flag_changers:
        self._flag_changers[str(dev)].Restore()

      if self._webview_flag_changers[str(dev)].GetCurrentFlags():
        self._webview_flag_changers[str(dev)].Restore()

      # Remove package-specific configuration
      dev.RunShellCommand(['am', 'clear-debug-app'], check_return=True)

      # Execute any custom teardown shell commands
      for cmd in self._test_instance.run_teardown_commands:
        logging.info('Running custom teardown shell command: %s', cmd)
        dev.RunShellCommand(cmd, shell=True, check_return=True)

      valgrind_tools.SetChromeTimeoutScale(dev, None)

      # If we've force approved app links for a package, undo that now.
      self._ToggleAppLinks(dev, 'STATE_NO_RESPONSE')

      # Context manager exit handlers are applied in reverse order
      # of the enter handlers.
      for context in reversed(self._context_managers[str(dev)]):
        # See pylint-related comment above with __enter__()
        # pylint: disable=no-member
        context.__exit__(*sys.exc_info())
        # pylint: enable=no-member

    self._env.parallel_devices.pMap(individual_device_tear_down)

  def _ToggleAppLinks(self, dev, state):
    # The set-app-links command was added in Android 12 (sdk = 31). The
    # restrictions that require us to set the app links were also added in
    # Android 12, so doing nothing on earlier Android versions is fine.
    if dev.build_version_sdk < version_codes.S:
      return

    package = self._test_instance.approve_app_links_package
    domain = self._test_instance.approve_app_links_domain

    if not package or not domain:
      return

    cmd = [
        'pm', 'set-app-links', '--package', package, state, domain
    ]
    dev.RunShellCommand(cmd, check_return=True)

  def _CreateFlagChangersIfNeeded(self, device):
    self._webview_flag_changers.setdefault(
        str(device), flag_changer.FlagChanger(device, 'webview-command-line'))

    if str(device) not in self._flag_changers:
      cmdline_file = 'test-cmdline-file'
      if self._test_instance.use_apk_under_test_flags_file:
        if self._test_instance.package_info:
          cmdline_file = self._test_instance.package_info.cmdline_file
        else:
          raise Exception('No PackageInfo found but'
                          '--use-apk-under-test-flags-file is specified.')
      self._flag_changers[str(device)] = flag_changer.FlagChanger(
          device, cmdline_file)

  #override
  def _CreateShardsForDevices(self, tests):
    """Create shards of tests to run on devices.

    Args:
      tests: List containing tests or test batches.

    Returns:
      List of tests or batches.
    """
    # Each test or test batch will be a single shard.
    return tests

  def _GetTestsFromPickle(self, pickle_extras):
    test_apk_path = self._test_instance.test_apk.path
    pickle_path = '%s-testlist.pickle' % test_apk_path
    # For incremental APKs, the code doesn't live in the apk, so instead check
    # the timestamp of the target's .dex files.
    if self._test_instance.test_apk_incremental_install_json:
      with open(self._test_instance.test_apk_incremental_install_json) as f:
        data = json.load(f)
      out_dir = constants.GetOutDirectory()
      test_mtime = max(
          os.path.getmtime(os.path.join(out_dir, p)) for p in data['dex_files'])
    else:
      test_mtime = os.path.getmtime(test_apk_path)

    try:
      raw_tests = _LoadTestsFromPickle(pickle_path, test_mtime, pickle_extras)
      logging.info('Using cached test list.')
    except _TestListPickleException as e:
      logging.info('Not using cached test list: %s', e)
      raw_tests = None
    return raw_tests, pickle_path

  #override
  def _GetTests(self):
    ti = self._test_instance
    use_dexdump = (not ti.has_chromium_test_listener
                   and ti.has_external_annotation_filters)
    run_disabled = ti.GetRunDisabledFlag()
    # run_disabled effects test listing only when using AndroidJUnitRunner.
    use_androidx_runner = not use_dexdump and not ti.has_chromium_test_listener
    pickle_extras = (use_dexdump, use_androidx_runner and run_disabled)
    raw_tests, pickle_path = self._GetTestsFromPickle(pickle_extras)

    if raw_tests is None:
      if use_dexdump:
        # This path is hit by CTS tests.
        # Dexdump is not able to find parameterized tests, so some tests might
        # be missed.
        # We should consider using AndroidJunitRunner's "-e annotation Foo,Bar"
        # and "-e notAnnotation Foo,Bar" to list tests when annotation filters
        # exist instead.
        logging.info('Getting tests from dexdump (due to annotation filters)')
        raw_tests = instrumentation_test_instance.GetTestsFromDexdump(
            ti.test_apk.path)
      else:
        logging.info('Getting tests by having %s list them.',
                     ti.junit4_runner_class)
        raw_tests = self._GetTestsFromRunner(run_disabled=run_disabled)
      _SaveTestsToPickle(pickle_path, raw_tests, pickle_extras)

    tests = ti.ProcessRawTests(raw_tests)
    tests = self._ApplyExternalSharding(tests, ti.external_shard_index,
                                        ti.total_external_shards)
    return tests

  #override
  def GetTestsForListing(self):
    # Parent class implementation assumes _GetTests() returns strings rather
    # than dicts.
    test_dicts = self._GetTests()
    test_dicts = local_device_test_run.FlattenTestList(test_dicts)
    return sorted('{}#{}'.format(d['class'], d['method']) for d in test_dicts)

  #override
  def _GroupTests(self, tests):
    batched_tests = dict()
    other_tests = []
    for test in tests:
      annotations = test['annotations']
      if 'Batch' in annotations and 'RequiresRestart' not in annotations:
        batch_name = annotations['Batch']['value']
        if not batch_name:
          batch_name = test['class']

        # Feature flags won't work in instrumentation tests unless the activity
        # is restarted.
        # Tests with identical features are grouped to minimize restarts.
        # UnitTests that specify flags always use Features.JUnitProcessor, so
        # they don't need to be split.
        if batch_name != 'UnitTests':
          if 'Features$EnableFeatures' in annotations:
            batch_name += '|enabled:' + ','.join(
                sorted(annotations['Features$EnableFeatures']['value']))
          if 'Features$DisableFeatures' in annotations:
            batch_name += '|disabled:' + ','.join(
                sorted(annotations['Features$DisableFeatures']['value']))
          if 'CommandLineFlags$Add' in annotations:
            batch_name += '|cmd_line_add:' + ','.join(
                sorted(annotations['CommandLineFlags$Add']['value']))
          if 'CommandLineFlags$Remove' in annotations:
            batch_name += '|cmd_line_remove:' + ','.join(
                sorted(annotations['CommandLineFlags$Remove']['value']))

        # WebView tests run in 2 process modes (single and multi). We must
        # restart the process for each mode, so this means singleprocess tests
        # and multiprocess tests must not be in the same batch.
        webview_multiprocess_mode = (
          base_test_result.MULTIPROCESS_SUFFIX in test['method'])
        if webview_multiprocess_mode:
          batch_name += '|multiprocess_mode'

        batched_tests.setdefault(batch_name, []).append(test)
      else:
        other_tests.append(test)

    def dict2list(d):
      if isinstance(d, dict):
        return sorted([(k, dict2list(v)) for k, v in d.items()])
      if isinstance(d, list):
        return [dict2list(v) for v in d]
      if isinstance(d, tuple):
        return tuple(dict2list(v) for v in d)
      return d

    test_count = sum(
        [len(test) - 1 for test in tests if self._CountTestsIndividually(test)])
    test_count += len(tests)
    if self._test_instance.total_external_shards > 1:
      # Calculate suitable test batch max group size based on average partition
      # size. The batch size should be below partition size to balance between
      # shards. Choose to divide by 3 as it works fine with most of test suite
      # without increasing too much setup/teardown time for batch tests.
      test_batch_max_group_size = \
        max(1, test_count // self._test_instance.total_external_shards // 3)
    else:
      test_batch_max_group_size = _LOCAL_TEST_BATCH_MAX_GROUP_SIZE

    all_tests = []
    for _, btests in list(batched_tests.items()):
      # Ensure a consistent ordering across external shards.
      btests.sort(key=dict2list)
      all_tests.extend([
          btests[i:i + test_batch_max_group_size]
          for i in range(0, len(btests), test_batch_max_group_size)
      ])
    all_tests.extend(other_tests)
    # Sort all tests by hash.
    # TODO(crbug.com/1257820): Add sorting logic back to _PartitionTests.
    return self._SortTests(all_tests)

  #override
  def _GetUniqueTestName(self, test):
    return instrumentation_test_instance.GetUniqueTestName(test)

  #override
  def _RunTest(self, device, test):
    extras = {}

    if self._test_instance.GetRunDisabledFlag():
      extras[_EXTRA_RUN_DISABLED_TEST] = 'true'

    if self._test_instance.is_unit_test:
      extras[_EXTRA_TEST_IS_UNIT] = 'true'

    # Provide package name under test for apk_under_test.
    if self._test_instance.apk_under_test:
      package_name = self._test_instance.apk_under_test.GetPackageName()
      extras[_EXTRA_PACKAGE_UNDER_TEST] = package_name

    flags_to_add = []
    test_timeout_scale = None
    if self._test_instance.coverage_directory:
      coverage_basename = '%s' % ('%s_%s_group' %
                                  (test[0]['class'], test[0]['method'])
                                  if isinstance(test, list) else '%s_%s' %
                                  (test['class'], test['method']))
      # Note for multi-user: when the main user is a secondary user, the path
      # like "/sdcard/chrome" can be still used as it is when used by commands
      # like "am instrument". But it needs to be converted when used by commands
      # like "mkdir", "ls", "rm", with the method ResolveSpecialPath, and root
      # permission.
      coverage_directory = os.path.join(
          device.GetExternalStoragePath(), 'chrome', 'test', 'coverage')
      # Setting up for jacoco coverage.
      extras['coverage'] = 'true'
      jacoco_coverage_device_file = os.path.join(coverage_directory,
                                                 coverage_basename)
      jacoco_coverage_device_file += '.exec'
      extras['coverageFile'] = jacoco_coverage_device_file

      if self._env.force_main_user:
        coverage_directory = device.ResolveSpecialPath(coverage_directory)
      if not device.PathExists(coverage_directory,
                               as_root=self._env.force_main_user):
        # Root permission is needed when accessing a secondary user's path.
        device.RunShellCommand(['mkdir', '-p', coverage_directory],
                               check_return=True,
                               as_root=self._env.force_main_user)

      # Setting up for clang coverage.
      device_clang_profile_dir = code_coverage_utils.GetDeviceClangCoverageDir(
          device)
      # "%2m" is used to expand to 2 raw profiles at runtime. "%p" writes
      # process ID.
      # "%c" enables continuous mode. See crbug.com/1468343, crbug.com/1518474
      # For more details, refer to:
      #   https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
      clang_profile_filename = ('%s_%s.profraw' %
                                (coverage_basename, '%2m_%p%c'))
      extras[EXTRA_CLANG_COVERAGE_DEVICE_FILE] = posixpath.join(
          device_clang_profile_dir, clang_profile_filename)

    if self._test_instance.enable_breakpad_dump:
      # Use external storage directory so that the breakpad dump can be accessed
      # by the test APK in addition to the apk_under_test.
      breakpad_dump_directory = os.path.join(device.GetExternalStoragePath(),
                                             'chromium_dumps')
      flags_to_add.append('--breakpad-dump-location=' + breakpad_dump_directory)
      if self._env.force_main_user:
        breakpad_dump_directory = device.ResolveSpecialPath(
            breakpad_dump_directory)
      if device.PathExists(breakpad_dump_directory,
                           as_root=self._env.force_main_user):
        device.RemovePath(breakpad_dump_directory,
                          recursive=True,
                          as_root=self._env.force_main_user)

    # Save screenshot if screenshot dir is specified (save locally) or if
    # a GS bucket is passed (save in cloud).
    screenshot_device_file = device_temp_file.DeviceTempFile(
        device.adb,
        suffix='.png',
        dir=device.GetExternalStoragePath(),
        device_utils=device)
    extras[EXTRA_SCREENSHOT_FILE] = screenshot_device_file.name

    # Set up the screenshot directory. This needs to be done for each test so
    # that we only get screenshots created by that test. It has to be on
    # external storage since the default location doesn't allow file creation
    # from the instrumentation test app on Android L and M.
    ui_capture_dir = device_temp_file.NamedDeviceTemporaryDirectory(
        device.adb, dir=device.GetExternalStoragePath(), device_utils=device)
    extras[EXTRA_UI_CAPTURE_DIR] = ui_capture_dir.name

    if self._env.trace_output:
      trace_device_file = device_temp_file.DeviceTempFile(
          device.adb,
          suffix='.json',
          dir=device.GetExternalStoragePath(),
          device_utils=device)
      extras[EXTRA_TRACE_FILE] = trace_device_file.name

    target = '%s/%s' % (self._test_instance.test_package,
                        self._test_instance.junit4_runner_class)
    if isinstance(test, list):

      def name_and_timeout(t):
        n = instrumentation_test_instance.GetTestName(t)
        i = self._GetTimeoutFromAnnotations(t['annotations'], n)
        return (n, i)

      test_names, timeouts = list(zip(*(name_and_timeout(t) for t in test)))

      test_name = instrumentation_test_instance.GetTestName(
          test[0]) + _BATCH_SUFFIX
      extras['class'] = ','.join(test_names)
      test_display_name = test_name
      timeout = min(MAX_BATCH_TEST_TIMEOUT,
                    FIXED_TEST_TIMEOUT_OVERHEAD + sum(timeouts))
    else:
      test_name = instrumentation_test_instance.GetTestName(test)
      test_display_name = self._GetUniqueTestName(test)

      extras['class'] = test_name
      if 'flags' in test and test['flags']:
        flags_to_add.extend(test['flags'])
      timeout = FIXED_TEST_TIMEOUT_OVERHEAD + self._GetTimeoutFromAnnotations(
          test['annotations'], test_display_name)

      test_timeout_scale = self._GetTimeoutScaleFromAnnotations(
          test['annotations'])
      if test_timeout_scale and test_timeout_scale != 1:
        valgrind_tools.SetChromeTimeoutScale(
            device, test_timeout_scale * self._test_instance.timeout_scale)

    if self._test_instance.wait_for_java_debugger:
      timeout = None
    logging.info('preparing to run %s: %s', test_display_name, test)

    if _IsRenderTest(test):
      self._render_tests_device_output_dir = (
          device_temp_file.NamedDeviceTemporaryDirectory(
              device.adb,
              dir=device.GetExternalStoragePath(),
              device_utils=device))
      flags_to_add.append('--render-test-output-dir=%s' %
                          self._render_tests_device_output_dir.name)

    if _IsWPRRecordReplayTest(test):
      wpr_archive_relative_path = _GetWPRArchivePath(test)
      if not wpr_archive_relative_path:
        raise RuntimeError('Could not find the WPR archive file path '
                           'from annotation.')
      wpr_archive_path = os.path.join(host_paths.DIR_SOURCE_ROOT,
                                      wpr_archive_relative_path)
      if not os.path.isdir(wpr_archive_path):
        raise RuntimeError('WPRArchiveDirectory annotation should point '
                           'to a directory only. '
                           '{0} exist: {1}'.format(
                               wpr_archive_path,
                               os.path.exists(wpr_archive_path)))

      file_name = _GetWPRArchiveFileName(
          test) or self._GetUniqueTestName(test) + '.wprgo'

      # Some linux version does not like # in the name. Replaces it with __.
      archive_path = os.path.join(wpr_archive_path,
                                  _ReplaceUncommonChars(file_name))

      if not os.path.exists(_WPR_GO_LINUX_X86_64_PATH):
        # If we got to this stage, then we should have
        # checkout_android set.
        raise RuntimeError(
            'WPR Go binary not found at {}'.format(_WPR_GO_LINUX_X86_64_PATH))
      # Tells the server to use the binaries retrieved from CIPD.
      chrome_proxy_utils.ChromeProxySession.SetWPRServerBinary(
          _WPR_GO_LINUX_X86_64_PATH)
      self._chrome_proxy = chrome_proxy_utils.ChromeProxySession()
      self._chrome_proxy.wpr_record_mode = self._test_instance.wpr_record_mode
      self._chrome_proxy.Start(device, archive_path)
      flags_to_add.extend(self._chrome_proxy.GetFlags())

    if flags_to_add:
      self._CreateFlagChangersIfNeeded(device)
      self._flag_changers[str(device)].PushFlags(add=flags_to_add)

    time_ms = lambda: int(time.time() * 1e3)
    start_ms = time_ms()

    with ui_capture_dir:
      with self._ArchiveLogcat(device, test_name) as logcat_file:
        output = device.StartInstrumentation(
            target, raw=True, extras=extras, timeout=timeout, retries=0)

      duration_ms = time_ms() - start_ms

      with contextlib_ext.Optional(
          trace_event.trace('ProcessResults'),
          self._env.trace_output):
        output = self._test_instance.MaybeDeobfuscateLines(output)
        # TODO(jbudorick): Make instrumentation tests output a JSON so this
        # doesn't have to parse the output.
        parser = instrumentation_parser.InstrumentationParser(output)
        statuses = list(parser.IterStatus())
        result_code, result_bundle = parser.GetResult()
        results = self._test_instance.GenerateTestResults(
            result_code, result_bundle, statuses, duration_ms,
            device.product_cpu_abi, self._test_instance.symbolizer)

      if self._env.trace_output:
        self._SaveTraceData(trace_device_file, device, test['class'])

      def restore_flags():
        if flags_to_add:
          self._flag_changers[str(device)].Restore()

      def restore_timeout_scale():
        if test_timeout_scale:
          valgrind_tools.SetChromeTimeoutScale(
              device, self._test_instance.timeout_scale)

      def handle_coverage_data():
        if self._test_instance.coverage_directory:
          try:
            if not os.path.exists(self._test_instance.coverage_directory):
              os.makedirs(self._test_instance.coverage_directory)

            # Handling Jacoco coverage data.
            # Retries add time to test execution.
            if device.PathExists(jacoco_coverage_device_file, retries=0):
              device.PullFile(jacoco_coverage_device_file,
                              self._test_instance.coverage_directory)
              device.RemovePath(jacoco_coverage_device_file, True)
            else:
              logging.warning('Jacoco coverage file does not exist: %s',
                              jacoco_coverage_device_file)

            # Handling Clang coverage data.
            # TODO(b/293175593): Use device.ResolveSpecialPath for multi-user
            code_coverage_utils.PullAndMaybeMergeClangCoverageFiles(
                device, device_clang_profile_dir,
                self._test_instance.coverage_directory, coverage_basename)

          except (OSError, base_error.BaseError) as e:
            logging.warning('Failed to handle coverage data after tests: %s', e)

      def handle_render_test_data():
        if _IsRenderTest(test):
          # Render tests do not cause test failure by default. So we have to
          # check to see if any failure images were generated even if the test
          # does not fail.
          try:
            self._ProcessRenderTestResults(device, results)
          finally:
            device_output_dir_path = self._render_tests_device_output_dir.name
            if self._env.force_main_user:
              device_output_dir_path = device.ResolveSpecialPath(
                  device_output_dir_path)
            device.RemovePath(device_output_dir_path,
                              recursive=True,
                              force=True,
                              as_root=self._env.force_main_user)
            self._render_tests_device_output_dir = None

      def pull_ui_screen_captures():
        screenshots = []
        source_dir = ui_capture_dir.name
        if self._env.force_main_user:
          source_dir = device.ResolveSpecialPath(source_dir)
        for filename in device.ListDirectory(source_dir,
                                             as_root=self._env.force_main_user):
          if filename.endswith('.json'):
            screenshots.append(pull_ui_screenshot(filename))
        if screenshots:
          json_archive_name = 'ui_capture_%s_%s.json' % (
              test_name.replace('#', '.'),
              time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()))
          with self._env.output_manager.ArchivedTempfile(
              json_archive_name, 'ui_capture', output_manager.Datatype.JSON
              ) as json_archive:
            json.dump(screenshots, json_archive)
          _SetLinkOnResults(results, test_name, 'ui screenshot',
                            json_archive.Link())

      def pull_ui_screenshot(filename):
        source_dir = ui_capture_dir.name
        if self._env.force_main_user:
          source_dir = device.ResolveSpecialPath(source_dir)
        json_path = posixpath.join(source_dir, filename)
        json_data = json.loads(
            device.ReadFile(json_path, as_root=self._env.force_main_user))
        image_file_path = posixpath.join(source_dir, json_data['location'])
        with self._env.output_manager.ArchivedTempfile(
            json_data['location'], 'ui_capture', output_manager.Datatype.PNG
            ) as image_archive:
          device.PullFile(image_file_path,
                          image_archive.name,
                          as_root=self._env.force_main_user)
        json_data['image_link'] = image_archive.Link()
        return json_data

      def stop_chrome_proxy():
        # Removes the port forwarding
        if self._chrome_proxy:
          self._chrome_proxy.Stop(device)
          if not self._chrome_proxy.wpr_replay_mode:
            logging.info('WPR Record test generated archive file %s',
                         self._chrome_proxy.wpr_archive_path)
          self._chrome_proxy = None

      def pull_baseline_profile():
        # Search though status responses for the one with the key we are
        # looking for.
        for _, bundle in statuses:
          baseline_profile_path = bundle.get(
              'additionalTestOutputFile_baseline-profile-ts')
          if baseline_profile_path:
            # Found it.
            break
        else:
          # This test does not generate a baseline profile.
          return
        with self._env.output_manager.ArchivedTempfile(
            'baseline_profile.txt', 'baseline_profile') as baseline_profile:
          device.PullFile(baseline_profile_path, baseline_profile.name)
        _SetLinkOnResults(results, test_name, 'baseline_profile',
                          baseline_profile.Link())
        logging.warning('Baseline Profile Location %s', baseline_profile.Link())


      # While constructing the TestResult objects, we can parallelize several
      # steps that involve ADB. These steps should NOT depend on any info in
      # the results! Things such as whether the test CRASHED have not yet been
      # determined.
      post_test_steps = [
          restore_flags, restore_timeout_scale, stop_chrome_proxy,
          handle_coverage_data, handle_render_test_data,
          pull_ui_screen_captures, pull_baseline_profile
      ]
      if self._env.concurrent_adb:
        reraiser_thread.RunAsync(post_test_steps)
      else:
        for step in post_test_steps:
          step()

    if logcat_file:
      _SetLinkOnResults(results, test_name, 'logcat', logcat_file.Link())

    # Update the result name if the test used flags.
    if flags_to_add:
      for r in results:
        if r.GetName() == test_name:
          r.SetName(test_display_name)

    # Add NOTRUN results for any missing tests.
    iterable_test = test if isinstance(test, list) else [test]
    test_names = set(self._GetUniqueTestName(t) for t in iterable_test)
    results_names = set(r.GetName() for r in results)
    results.extend(
        base_test_result.BaseTestResult(u, base_test_result.ResultType.NOTRUN)
        for u in test_names.difference(results_names))

    # Update the result type if we detect a crash.
    try:
      crashed_packages = DismissCrashDialogs(device)
      # Assume test package convention of ".test" suffix
      if any(p in self._test_instance.test_package for p in crashed_packages):
        for r in results:
          if r.GetType() == base_test_result.ResultType.UNKNOWN:
            r.SetType(base_test_result.ResultType.CRASH)
      elif (crashed_packages and len(results) == 1
            and results[0].GetType() != base_test_result.ResultType.PASS):
        # Add log message and set failure reason if:
        #   1) The app crash was likely not caused by the test.
        #   AND
        #   2) The app crash possibly caused the test to fail.
        # Crashes of the package under test are assumed to be the test's fault.
        _AppendToLogForResult(
            results[0], 'OS displayed error dialogs for {}'.format(
                ', '.join(crashed_packages)))
        results[0].SetFailureReason('{} Crashed'.format(
            ','.join(crashed_packages)))
    except device_errors.CommandTimeoutError:
      logging.warning('timed out when detecting/dismissing error dialogs')
      # Attach screenshot to the test to help with debugging the dialog boxes.
      self._SaveScreenshot(device, screenshot_device_file, test_display_name,
                           results, 'dialog_box_screenshot')

    # The crash result can be set above or in
    # InstrumentationTestRun.GenerateTestResults. If a test crashes,
    # subprocesses such as the one used by EmbeddedTestServerRule can be left
    # alive in a bad state, so kill them now.
    for r in results:
      if r.GetType() == base_test_result.ResultType.CRASH:
        for apk in self._test_instance.additional_apks:
          device.ForceStop(apk.GetPackageName())

    # Handle failures by:
    #   - optionally taking a screenshot
    #   - logging the raw output at ERROR level
    #   - clearing the application state while persisting permissions
    if any(r.GetType() not in (base_test_result.ResultType.PASS,
                               base_test_result.ResultType.SKIP)
           for r in results):
      self._SaveScreenshot(device, screenshot_device_file, test_display_name,
                           results, 'post_test_screenshot')

      logging.error('detected failure in %s. raw output:', test_display_name)
      for l in output:
        logging.error('  %s', l)
      if not self._env.skip_clear_data:
        if self._test_instance.package_info:
          permissions = (self._test_instance.apk_under_test.GetPermissions()
                         if self._test_instance.apk_under_test else None)
          device.ClearApplicationState(self._test_instance.package_info.package,
                                       permissions=permissions)
        if self._test_instance.enable_breakpad_dump:
          device.RemovePath(breakpad_dump_directory,
                            recursive=True,
                            as_root=self._env.force_main_user)
    else:
      logging.debug('raw output from %s:', test_display_name)
      for l in output:
        logging.debug('  %s', l)

    if self._test_instance.store_tombstones:
      resolved_tombstones = tombstones.ResolveTombstones(
          device,
          resolve_all_tombstones=True,
          include_stack_symbols=False,
          wipe_tombstones=True,
          tombstone_symbolizer=self._test_instance.symbolizer)
      if resolved_tombstones:
        tombstone_filename = 'tombstones_%s_%s' % (time.strftime(
            '%Y%m%dT%H%M%S-UTC', time.gmtime()), device.serial)
        with self._env.output_manager.ArchivedTempfile(
            tombstone_filename, 'tombstones') as tombstone_file:
          tombstone_file.write('\n'.join(resolved_tombstones))

        # Associate tombstones with first crashing test.
        for result in results:
          if result.GetType() == base_test_result.ResultType.CRASH:
            result.SetLink('tombstones', tombstone_file.Link())
            break
        else:
          # We don't always detect crashes correctly. In this case,
          # associate with the first test.
          results[0].SetLink('tombstones', tombstone_file.Link())

    notrun_tests = set(r.GetName() for r in results
                       if r.GetType() == base_test_result.ResultType.NOTRUN)

    # If a test that is batched crashes, the rest of the tests in that batch
    # won't be ran and will have their status left as NOTRUN in results,
    # so rerun the tests. (see crbug/1127935)
    # Need to "unbatch" the tests, so that on subsequent tries, the tests can
    # get ran individually. This prevents an unrecognized crash from preventing
    # the tests in the batch from being ran. Running the test as unbatched does
    # not happen until a retry happens at the local_device_test_run/environment
    # level.
    tests_to_rerun = []
    for t in iterable_test:
      if self._GetUniqueTestName(t) in notrun_tests:
        prior_attempts = t.get('run_attempts', 0)
        t['run_attempts'] = prior_attempts + 1
        # It's possible every test in the batch could crash, so need to
        # try up to as many times as tests that there are.
        if prior_attempts < len(results):
          if t['annotations']:
            t['annotations'].pop('Batch', None)
          tests_to_rerun.append(t)

    # If we have a crash that isn't recognized as a crash in a batch, the tests
    # will be marked as NOTRUN. Sometimes a test failure causes a crash, but
    # the crash isn't recorded because the failure was detected first.
    # To avoid useless reruns, don't try rerunning. They will
    # get rerun individually at the local_device_test_run/environment level.
    # as the "Batch" annotation was removed.
    found_crash_or_fail = False
    for r in results:
      if (r.GetType() == base_test_result.ResultType.CRASH
          or r.GetType() == base_test_result.ResultType.FAIL):
        found_crash_or_fail = True
        break
    if not found_crash_or_fail:
      # Don't bother rerunning since the unrecognized crashes in
      # the batch will keep failing.
      tests_to_rerun = None

    return results, tests_to_rerun if tests_to_rerun else None

  def _GetTestsFromRunner(self, run_disabled):
    def list_tests(d):
      def _run(dev):
        junit4_runner_class = self._test_instance.junit4_runner_class
        test_package = self._test_instance.test_package
        extras = {
            'log': 'true',
            # Workaround for https://github.com/mockito/mockito/issues/922
            'notPackage': 'net.bytebuddy',
        }
        # BaseChromiumAndroidJUnitRunner ignores this bundle value (and always
        # adds the listener). This is needed to enable the the listener when
        # using AndroidJUnitRunner directly.
        if self._test_instance.has_chromium_test_listener:
          extras['listener'] = (
              'org.chromium.testing.TestListInstrumentationRunListener')
        elif not run_disabled:
          extras['notAnnotation'] = 'androidx.test.filters.FlakyTest'

        target = '%s/%s' % (test_package, junit4_runner_class)
        timeout = 240
        if self._test_instance.wait_for_java_debugger:
          timeout = None
        with self._ArchiveLogcat(dev, 'list_tests'):
          test_list_run_output = dev.StartInstrumentation(target,
                                                          raw=True,
                                                          extras=extras,
                                                          retries=0,
                                                          timeout=timeout)
        if ('INSTRUMENTATION_RESULT: shortMsg=Process crashed.'
            in test_list_run_output):
          # Message output by ActivityManagerService when app crashes.
          logging.error('Crashed detected. Output was: \n%s',
                        test_list_run_output)
          return None
        if self._test_instance.has_chromium_test_listener:
          logging.info('Parsing tests from TestListInstrumentationRunListener')
          return _ParseTestListOutputFromChromiumListener(test_list_run_output)
        logging.info('Parsing tests from androidx InstrumentationResultPrinter')
        return _ParseTestListOutputFromAndroidxListener(test_list_run_output)

      return crash_handler.RetryOnSystemCrash(_run, d)

    raw_test_lists = self._env.parallel_devices.pMap(list_tests).pGet(None)

    # If all devices failed to list tests, raise an exception.
    # Check that tl is not None and is not empty.
    if all(not tl for tl in raw_test_lists):
      raise device_errors.CommandFailedError(
          'Failed to list tests on any device')

    # Get the first viable list of raw tests
    raw_tests = [tl for tl in raw_test_lists if tl][0]

    return raw_tests

  @contextlib.contextmanager
  def _ArchiveLogcat(self, device, test_name):
    stream_name = 'logcat_%s_shard%s_%s_%s' % (
        test_name.replace('#', '.'), self._test_instance.external_shard_index,
        time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()), device.serial)

    logcat_file = None
    logmon = None
    try:
      with self._env.output_manager.ArchivedTempfile(stream_name,
                                                     'logcat') as logcat_file:
        symbolizer = stack_symbolizer.PassThroughSymbolizerPool(
            device.product_cpu_abi)
        with symbolizer:
          with logcat_monitor.LogcatMonitor(
              device.adb,
              filter_specs=local_device_environment.LOGCAT_FILTERS,
              output_file=logcat_file.name,
              transform_func=lambda lines: symbolizer.TransformLines(
                  self._test_instance.MaybeDeobfuscateLines(lines)),
              check_error=False) as logmon:
            with contextlib_ext.Optional(trace_event.trace(test_name),
                                         self._env.trace_output):
              yield logcat_file
    finally:
      if logmon:
        logmon.Close()
      if logcat_file and logcat_file.Link():
        logging.critical('Logcat saved to %s', logcat_file.Link())

  def _SaveTraceData(self, trace_device_file, device, test_class):
    trace_host_file = self._env.trace_output

    device_file_path = trace_device_file.name
    if self._env.force_main_user:
      device_file_path = device.ResolveSpecialPath(device_file_path)
    if device.PathExists(device_file_path, as_root=self._env.force_main_user):
      try:
        java_trace_json = device.ReadFile(device_file_path,
                                          as_root=self._env.force_main_user)
      except IOError as e:
        raise Exception('error pulling trace file from device') from e
      finally:
        trace_device_file.close()

      process_name = '%s (device %s)' % (test_class, device.serial)
      process_hash = int(hashlib.md5(process_name).hexdigest()[:6], 16)

      java_trace = json.loads(java_trace_json)
      java_trace.sort(key=lambda event: event['ts'])

      get_date_command = 'echo $EPOCHREALTIME'
      device_time = device.RunShellCommand(get_date_command, single_line=True)
      device_time = float(device_time) * 1e6
      system_time = trace_time.Now()
      time_difference = system_time - device_time

      threads_to_add = set()
      for event in java_trace:
        # Ensure thread ID and thread name will be linked in the metadata.
        threads_to_add.add((event['tid'], event['name']))

        event['pid'] = process_hash

        # Adjust time stamp to align with Python trace times (from
        # trace_time.Now()).
        event['ts'] += time_difference

      for tid, thread_name in threads_to_add:
        thread_name_metadata = {'pid': process_hash, 'tid': tid,
                                'ts': 0, 'ph': 'M', 'cat': '__metadata',
                                'name': 'thread_name',
                                'args': {'name': thread_name}}
        java_trace.append(thread_name_metadata)

      process_name_metadata = {'pid': process_hash, 'tid': 0, 'ts': 0,
                               'ph': 'M', 'cat': '__metadata',
                               'name': 'process_name',
                               'args': {'name': process_name}}
      java_trace.append(process_name_metadata)

      java_trace_json = json.dumps(java_trace)
      java_trace_json = java_trace_json.rstrip(' ]')

      with open(trace_host_file, 'r') as host_handle:
        host_contents = host_handle.readline()

      if host_contents:
        java_trace_json = ',%s' % java_trace_json.lstrip(' [')

      with open(trace_host_file, 'a') as host_handle:
        host_handle.write(java_trace_json)

  def _SaveScreenshot(self, device, screenshot_device_file, test_name, results,
                      link_name):
    screenshot_filename = '%s-%s.png' % (
        test_name, time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()))
    device_file_path = screenshot_device_file.name
    if self._env.force_main_user:
      device_file_path = device.ResolveSpecialPath(device_file_path)
    if device.PathExists(device_file_path, as_root=self._env.force_main_user):
      with self._env.output_manager.ArchivedTempfile(
          screenshot_filename, 'screenshot',
          output_manager.Datatype.PNG) as screenshot_host_file:
        try:
          device.PullFile(device_file_path,
                          screenshot_host_file.name,
                          as_root=self._env.force_main_user)
        finally:
          screenshot_device_file.close()
      _SetLinkOnResults(results, test_name, link_name,
                        screenshot_host_file.Link())

  def _ProcessRenderTestResults(self, device, results):
    if not self._render_tests_device_output_dir:
      return
    # TODO(b/295350872): Remove this and other timestamp logging in Gold-related
    # code once the source of flaky slowness is tracked down.
    logging.info('Starting render test result processing')
    start_time = time.time()
    self._ProcessSkiaGoldRenderTestResults(device, results)
    logging.info('Render test result processing took %fs',
                 time.time() - start_time)

  def _ProcessSkiaGoldRenderTestResults(self, device, results):
    gold_dir = posixpath.join(self._render_tests_device_output_dir.name,
                              _DEVICE_GOLD_DIR)
    logging.info('Starting Gold directory existence check')
    start_time = time.time()
    try:
      if not device.PathExists(gold_dir):
        return
    finally:
      logging.info('Gold directory existence check took %fs',
                   time.time() - start_time)

    gold_properties = self._test_instance.skia_gold_properties
    with tempfile_ext.NamedTemporaryDirectory() as host_dir:
      use_luci = not (gold_properties.local_pixel_tests
                      or gold_properties.no_luci_auth)

      # Pull everything at once instead of pulling individually, as it's
      # slightly faster since each command over adb has some overhead compared
      # to doing the same thing locally.
      host_dir = os.path.join(host_dir, _DEVICE_GOLD_DIR)

      logging.info('Starting Gold directory pull')
      start_time = time.time()
      device.PullFile(gold_dir, host_dir)
      logging.info('Gold directory pull took %fs', time.time() - start_time)

      for image_name in os.listdir(host_dir):
        if not image_name.endswith('.png'):
          continue

        render_name = image_name[:-4]
        json_name = render_name + '.json'
        json_path = os.path.join(host_dir, json_name)
        image_path = os.path.join(host_dir, image_name)
        full_test_name = None
        if not os.path.exists(json_path):
          _FailTestIfNecessary(results, full_test_name)
          _AppendToLog(
              results, full_test_name,
              'Unable to find corresponding JSON file for image %s '
              'when doing Skia Gold comparison.' % image_name)
          continue

        # Add 'ignore': '1' if a comparison failure would not be surfaced, as
        # that implies that we aren't actively maintaining baselines for the
        # test. This helps prevent unrelated CLs from getting comments posted to
        # them.
        should_rewrite = False
        with open(json_path) as infile:
          # All the key/value pairs in the JSON file are strings, so convert
          # to a bool.
          json_dict = json.load(infile)
          optional_dict = json_dict.get('optional_keys', {})
          if 'optional_keys' in json_dict:
            should_rewrite = True
            del json_dict['optional_keys']
          fail_on_unsupported = optional_dict.get('fail_on_unsupported_configs',
                                                  'false')
          fail_on_unsupported = fail_on_unsupported.lower() == 'true'
          # Grab the full test name so we can associate the comparison with a
          # particular test, which is necessary if tests are batched together.
          # Remove the key/value pair from the JSON since we don't need/want to
          # upload it to Gold.
          full_test_name = json_dict.get('full_test_name')
          if 'full_test_name' in json_dict:
            should_rewrite = True
            del json_dict['full_test_name']

        running_on_unsupported = (
            device.build_version_sdk not in RENDER_TEST_MODEL_SDK_CONFIGS.get(
                device.product_model, []) and not fail_on_unsupported)
        should_ignore_in_gold = running_on_unsupported
        # We still want to fail the test even if we're ignoring the image in
        # Gold if we're running on a supported configuration, so
        # should_ignore_in_gold != should_hide_failure.
        should_hide_failure = running_on_unsupported
        if should_ignore_in_gold:
          # This is put in the regular keys dict instead of the optional one
          # because ignore rules do not apply to optional keys.
          json_dict['ignore'] = '1'
        if should_rewrite:
          with open(json_path, 'w') as outfile:
            json.dump(json_dict, outfile)

        gold_session = self._skia_gold_session_manager.GetSkiaGoldSession(
            keys_input=json_path)

        logging.info('Starting Gold comparison')
        start_time = time.time()
        try:
          status, error = gold_session.RunComparison(
              name=render_name,
              png_file=image_path,
              output_manager=self._env.output_manager,
              use_luci=use_luci,
              optional_keys=optional_dict)
        except Exception as e:  # pylint: disable=broad-except
          _FailTestIfNecessary(results, full_test_name)
          _AppendToLog(results, full_test_name,
                       'Skia Gold comparison raised exception: %s' % e)
          continue
        finally:
          logging.info('Gold comparison took %fs', time.time() - start_time)

        if not status:
          continue

        # Don't fail the test if we ran on an unsupported configuration unless
        # the test has explicitly opted in, as it's likely that baselines
        # aren't maintained for that configuration.
        if should_hide_failure:
          if self._test_instance.skia_gold_properties.local_pixel_tests:
            _AppendToLog(
                results, full_test_name,
                'Gold comparison for %s failed, but model %s with SDK '
                '%d is not a supported configuration. This failure would be '
                'ignored on the bots, but failing since tests are being run '
                'locally.' %
                (render_name, device.product_model, device.build_version_sdk))
          else:
            _AppendToLog(
                results, full_test_name,
                'Gold comparison for %s failed, but model %s with SDK '
                '%d is not a supported configuration, so ignoring failure.' %
                (render_name, device.product_model, device.build_version_sdk))
            continue

        _FailTestIfNecessary(results, full_test_name)
        failure_log = (
            'Skia Gold reported failure for RenderTest %s. See '
            'RENDER_TESTS.md for how to fix this failure.' % render_name)
        status_codes =\
            self._skia_gold_session_manager.GetSessionClass().StatusCodes
        if status == status_codes.AUTH_FAILURE:
          _AppendToLog(results, full_test_name,
                       'Gold authentication failed with output %s' % error)
        elif status == status_codes.INIT_FAILURE:
          _AppendToLog(results, full_test_name,
                       'Gold initialization failed with output %s' % error)
        elif status == status_codes.COMPARISON_FAILURE_REMOTE:
          public_triage_link, internal_triage_link =\
              gold_session.GetTriageLinks(render_name)
          if not public_triage_link:
            _AppendToLog(
                results, full_test_name,
                'Failed to get triage link for %s, raw output: %s' %
                (render_name, error))
            _AppendToLog(
                results, full_test_name, 'Reason for no triage link: %s' %
                gold_session.GetTriageLinkOmissionReason(render_name))
            continue
          if gold_properties.IsTryjobRun():
            _SetLinkOnResults(results, full_test_name,
                              'Public Skia Gold triage link for entire CL',
                              public_triage_link)
            _SetLinkOnResults(results, full_test_name,
                              'Internal Skia Gold triage link for entire CL',
                              internal_triage_link)
          else:
            _SetLinkOnResults(
                results, full_test_name,
                'Public Skia Gold triage link for %s' % render_name,
                public_triage_link)
            _SetLinkOnResults(
                results, full_test_name,
                'Internal Skia Gold triage link for %s' % render_name,
                internal_triage_link)
          _AppendToLog(results, full_test_name, failure_log)

        elif status == status_codes.COMPARISON_FAILURE_LOCAL:
          given_link = gold_session.GetGivenImageLink(render_name)
          closest_link = gold_session.GetClosestImageLink(render_name)
          diff_link = gold_session.GetDiffImageLink(render_name)

          processed_template_output = _GenerateRenderTestHtml(
              render_name, given_link, closest_link, diff_link)
          with self._env.output_manager.ArchivedTempfile(
              '%s.html' % render_name, 'gold_local_diffs',
              output_manager.Datatype.HTML) as html_results:
            html_results.write(processed_template_output)
          _SetLinkOnResults(results, full_test_name, render_name,
                            html_results.Link())
          _AppendToLog(
              results, full_test_name,
              'See %s link for diff image with closest positive.' % render_name)
        elif status == status_codes.LOCAL_DIFF_FAILURE:
          _AppendToLog(results, full_test_name,
                       'Failed to generate diffs from Gold: %s' % error)
        else:
          logging.error(
              'Given unhandled SkiaGoldSession StatusCode %s with error %s',
              status, error)

  #override
  def _ShouldRetry(self, test, result):
    # We've tried to disable retries in the past with mixed results.
    # See crbug.com/619055 for historical context and crbug.com/797002
    # for ongoing efforts.
    if 'Batch' in test['annotations'] and test['annotations']['Batch'][
        'value'] == 'UnitTests':
      return False
    del test, result
    return True

  #override
  def _ShouldShardTestsForDevices(self):
    """Shard tests across several devices.

    Returns:
      True if tests should be sharded across several devices,
      False otherwise.
    """
    return True

  @classmethod
  def _GetTimeoutScaleFromAnnotations(cls, annotations):
    try:
      return int(annotations.get('TimeoutScale', {}).get('value', 1))
    except ValueError as e:
      logging.warning("Non-integer value of TimeoutScale ignored. (%s)", str(e))
      return 1

  @classmethod
  def _GetTimeoutFromAnnotations(cls, annotations, test_name):
    for k, v in TIMEOUT_ANNOTATIONS:
      if k in annotations:
        timeout = v
        break
    else:
      logging.warning('Using default 1 minute timeout for %s', test_name)
      timeout = 60

    timeout *= cls._GetTimeoutScaleFromAnnotations(annotations)

    return timeout


def _IsWPRRecordReplayTest(test):
  """Determines whether a test or a list of tests is a WPR RecordReplay Test."""
  if not isinstance(test, list):
    test = [test]
  return any(WPR_RECORD_REPLAY_TEST_FEATURE_ANNOTATION in t['annotations'].get(
      FEATURE_ANNOTATION, {}).get('value', ()) for t in test)


def _GetWPRArchivePath(test):
  """Retrieves the archive path from the WPRArchiveDirectory annotation."""
  return test['annotations'].get(WPR_ARCHIVE_FILE_PATH_ANNOTATION,
                                 {}).get('value', ())


def _GetWPRArchiveFileName(test):
  """Retrieves the WPRArchiveDirectory.ArchiveName annotation."""
  value = test['annotations'].get(WPR_ARCHIVE_NAME_ANNOTATION,
                                  {}).get('value', None)
  return value[0] if value else None


def _ReplaceUncommonChars(original):
  """Replaces uncommon characters with __."""
  if not original:
    raise ValueError('parameter should not be empty')

  uncommon_chars = ['#']
  for char in uncommon_chars:
    original = original.replace(char, '__')
  return original


def _IsRenderTest(test):
  """Determines if a test or list of tests has a RenderTest amongst them."""
  if not isinstance(test, list):
    test = [test]
  return any(RENDER_TEST_FEATURE_ANNOTATION in t['annotations'].get(
      FEATURE_ANNOTATION, {}).get('value', ()) for t in test)


def _GenerateRenderTestHtml(image_name, failure_link, golden_link, diff_link):
  """Generates a RenderTest results page.

  Displays the generated (failure) image, the golden image, and the diff
  between them.

  Args:
    image_name: The name of the image whose comparison failed.
    failure_link: The URL to the generated/failure image.
    golden_link: The URL to the golden image.
    diff_link: The URL to the diff image between the failure and golden images.

  Returns:
    A string containing the generated HTML.
  """
  jinja2_env = jinja2.Environment(
      loader=jinja2.FileSystemLoader(_JINJA_TEMPLATE_DIR), trim_blocks=True)
  template = jinja2_env.get_template(_JINJA_TEMPLATE_FILENAME)
  # pylint: disable=no-member
  return template.render(
      test_name=image_name,
      failure_link=failure_link,
      golden_link=golden_link,
      diff_link=diff_link)


def _FailTestIfNecessary(results, full_test_name):
  """Marks the given results as failed if it wasn't already.

  Marks the result types as ResultType.FAIL unless they were already some sort
  of failure type, e.g. ResultType.CRASH.

  Args:
    results: A list of base_test_result.BaseTestResult objects.
    full_test_name: A string containing the full name of the test, e.g.
        org.chromium.chrome.SomeTestClass#someTestMethod.
  """
  found_matching_test = _MatchingTestInResults(results, full_test_name)
  if not found_matching_test and _ShouldReportNoMatchingResult(full_test_name):
    logging.error(
        'Could not find result specific to %s, failing all tests in the batch.',
        full_test_name)
  for result in results:
    if found_matching_test and result.GetName() != full_test_name:
      continue
    if result.GetType() not in [
        base_test_result.ResultType.FAIL, base_test_result.ResultType.CRASH,
        base_test_result.ResultType.TIMEOUT, base_test_result.ResultType.UNKNOWN
    ]:
      result.SetType(base_test_result.ResultType.FAIL)


def _AppendToLog(results, full_test_name, line):
  """Appends the given line to the end of the logs of the given results.

  Args:
    results: A list of base_test_result.BaseTestResult objects.
    full_test_name: A string containing the full name of the test, e.g.
        org.chromium.chrome.SomeTestClass#someTestMethod.
    line: A string to be appended as a neww line to the log of |result|.
  """
  found_matching_test = _MatchingTestInResults(results, full_test_name)
  if not found_matching_test and _ShouldReportNoMatchingResult(full_test_name):
    logging.error(
        'Could not find result specific to %s, appending to log of all tests '
        'in the batch.', full_test_name)
  for result in results:
    if found_matching_test and result.GetName() != full_test_name:
      continue
    _AppendToLogForResult(result, line)


def _AppendToLogForResult(result, line):
  result.SetLog(result.GetLog() + '\n' + line)


def _SetLinkOnResults(results, full_test_name, link_name, link):
  """Sets the given link on the given results.

  Args:
    results: A list of base_test_result.BaseTestResult objects.
    full_test_name: A string containing the full name of the test, e.g.
        org.chromium.chrome.SomeTestClass#someTestMethod.
    link_name: A string containing the name of the link being set.
    link: A string containing the link being set.
  """
  found_matching_test = _MatchingTestInResults(results, full_test_name)
  if not found_matching_test and _ShouldReportNoMatchingResult(full_test_name):
    logging.error(
        'Could not find result specific to %s, adding link to results of all '
        'tests in the batch.', full_test_name)
  for result in results:
    if found_matching_test and result.GetName() != full_test_name:
      continue
    result.SetLink(link_name, link)


def _MatchingTestInResults(results, full_test_name):
  """Checks if any tests named |full_test_name| are in |results|.

  Args:
    results: A list of base_test_result.BaseTestResult objects.
    full_test_name: A string containing the full name of the test, e.g.
        org.chromium.chrome.Some

  Returns:
    True if one of the results in |results| has the same name as
    |full_test_name|, otherwise False.
  """
  return any(r for r in results if r.GetName() == full_test_name)


def _ShouldReportNoMatchingResult(full_test_name):
  """Determines whether a failure to find a matching result is actually bad.

  Args:
    full_test_name: A string containing the full name of the test, e.g.
        org.chromium.chrome.Some

  Returns:
    False if the failure to find a matching result is expected and should not
    be reported, otherwise True.
  """
  if full_test_name is not None and full_test_name.endswith(_BATCH_SUFFIX):
    # Handle batched tests, whose reported name is the first test's name +
    # "_batch".
    return False
  return True
