# Copyright 2016 Google Inc.
#
# 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.

import contextlib
import logging
import os
import re
import shutil
import time

from mobly import logger as mobly_logger
from mobly import runtime_test_info
from mobly import utils
from mobly.controllers.android_device_lib import adb
from mobly.controllers.android_device_lib import errors
from mobly.controllers.android_device_lib import fastboot
from mobly.controllers.android_device_lib import service_manager
from mobly.controllers.android_device_lib.services import logcat
from mobly.controllers.android_device_lib.services import snippet_management_service

# Convenience constant for the package of Mobly Bundled Snippets
# (http://github.com/google/mobly-bundled-snippets).
MBS_PACKAGE = 'com.google.android.mobly.snippet.bundled'

MOBLY_CONTROLLER_CONFIG_NAME = 'AndroidDevice'

ANDROID_DEVICE_PICK_ALL_TOKEN = '*'
_DEBUG_PREFIX_TEMPLATE = '[AndroidDevice|%s] %s'

# Key name for adb logcat extra params in config file.
ANDROID_DEVICE_ADB_LOGCAT_PARAM_KEY = 'adb_logcat_param'
ANDROID_DEVICE_EMPTY_CONFIG_MSG = 'Configuration is empty, abort!'
ANDROID_DEVICE_NOT_LIST_CONFIG_MSG = 'Configuration should be a list, abort!'

# System properties that are cached by the `AndroidDevice.build_info` property.
# The only properties on this list should be read-only system properties.
CACHED_SYSTEM_PROPS = [
    'ro.build.id',
    'ro.build.type',
    'ro.build.fingerprint',
    'ro.build.version.codename',
    'ro.build.version.incremental',
    'ro.build.version.sdk',
    'ro.build.product',
    'ro.build.characteristics',
    'ro.debuggable',
    'ro.product.name',
    'ro.hardware',
]

# Keys for attributes in configs that alternate the controller module behavior.
# If this is False for a device, errors from that device will be ignored
# during `create`. Default is True.
KEY_DEVICE_REQUIRED = 'required'
DEFAULT_VALUE_DEVICE_REQUIRED = True
# If True, logcat collection will not be started during `create`.
# Default is False.
KEY_SKIP_LOGCAT = 'skip_logcat'
DEFAULT_VALUE_SKIP_LOGCAT = False
SERVICE_NAME_LOGCAT = 'logcat'

# Default name for bug reports taken without a specified test name.
DEFAULT_BUG_REPORT_NAME = 'bugreport'

# Default Timeout to wait for boot completion
DEFAULT_TIMEOUT_BOOT_COMPLETION_SECOND = 15 * 60

# Timeout for the adb command for taking a screenshot
TAKE_SCREENSHOT_TIMEOUT_SECOND = 10

# Aliases of error types for backward compatibility.
Error = errors.Error
DeviceError = errors.DeviceError
SnippetError = snippet_management_service.Error

# Regex to heuristically determine if the device is an emulator.
EMULATOR_SERIAL_REGEX = re.compile(r'emulator-\d+')


def create(configs):
  """Creates AndroidDevice controller objects.

  Args:
    configs: A list of dicts, each representing a configuration for an
      Android device.

  Returns:
    A list of AndroidDevice objects.
  """
  if not configs:
    raise Error(ANDROID_DEVICE_EMPTY_CONFIG_MSG)
  elif configs == ANDROID_DEVICE_PICK_ALL_TOKEN:
    ads = get_all_instances()
  elif not isinstance(configs, list):
    raise Error(ANDROID_DEVICE_NOT_LIST_CONFIG_MSG)
  elif isinstance(configs[0], dict):
    # Configs is a list of dicts.
    ads = get_instances_with_configs(configs)
  elif isinstance(configs[0], str):
    # Configs is a list of strings representing serials.
    ads = get_instances(configs)
  else:
    raise Error('No valid config found in: %s' % configs)
  _start_services_on_ads(ads)
  return ads


def destroy(ads):
  """Cleans up AndroidDevice objects.

  Args:
    ads: A list of AndroidDevice objects.
  """
  for ad in ads:
    try:
      ad.services.stop_all()
    except Exception:
      ad.log.exception('Failed to clean up properly.')


def get_info(ads):
  """Get information on a list of AndroidDevice objects.

  Args:
    ads: A list of AndroidDevice objects.

  Returns:
    A list of dict, each representing info for an AndroidDevice objects.
  """
  return [ad.device_info for ad in ads]


def _validate_device_existence(serials):
  """Validate that all the devices specified by the configs can be reached.

  Args:
    serials: list of strings, the serials of all the devices that are expected
      to exist.
  """
  valid_ad_identifiers = list_adb_devices() + list_adb_devices_by_usb_id()
  for serial in serials:
    if serial not in valid_ad_identifiers:
      raise Error(f'Android device serial "{serial}" is specified in '
                  'config but is not reachable.')


def _start_services_on_ads(ads):
  """Starts long running services on multiple AndroidDevice objects.

  If any one AndroidDevice object fails to start services, cleans up all
  AndroidDevice objects and their services.

  Args:
    ads: A list of AndroidDevice objects whose services to start.
  """
  for ad in ads:
    start_logcat = not getattr(ad, KEY_SKIP_LOGCAT, DEFAULT_VALUE_SKIP_LOGCAT)
    try:
      if start_logcat:
        ad.services.logcat.start()
    except Exception:
      is_required = getattr(ad, KEY_DEVICE_REQUIRED,
                            DEFAULT_VALUE_DEVICE_REQUIRED)
      if is_required:
        ad.log.exception('Failed to start some services, abort!')
        destroy(ads)
        raise
      else:
        ad.log.exception('Skipping this optional device because some '
                         'services failed to start.')


def parse_device_list(device_list_str, key):
  """Parses a byte string representing a list of devices.

  The string is generated by calling either adb or fastboot. The tokens in
  each string is tab-separated.

  Args:
    device_list_str: Output of adb or fastboot.
    key: The token that signifies a device in device_list_str.

  Returns:
    A list of android device serial numbers.
  """
  try:
    clean_lines = str(device_list_str, 'utf-8').strip().split('\n')
  except UnicodeDecodeError:
    logging.warning("unicode decode error, origin str: %s", device_list_str)
    raise
  results = []
  for line in clean_lines:
    tokens = line.strip().split('\t')
    if len(tokens) == 2 and tokens[1] == key:
      results.append(tokens[0])
  return results


def list_adb_devices():
  """List all android devices connected to the computer that are detected by
  adb.

  Returns:
    A list of android device serials. Empty if there's none.
  """
  out = adb.AdbProxy().devices()
  return parse_device_list(out, 'device')


def list_adb_devices_by_usb_id():
  """List the usb id of all android devices connected to the computer that
  are detected by adb.

  Returns:
    A list of strings that are android device usb ids. Empty if there's
    none.
  """
  out = adb.AdbProxy().devices(['-l'])
  clean_lines = str(out, 'utf-8').strip().split('\n')
  results = []
  for line in clean_lines:
    tokens = line.strip().split()
    if len(tokens) > 2 and tokens[1] == 'device':
      results.append(tokens[2])
  return results


def list_fastboot_devices():
  """List all android devices connected to the computer that are in in
  fastboot mode. These are detected by fastboot.

  Returns:
    A list of android device serials. Empty if there's none.
  """
  out = fastboot.FastbootProxy().devices()
  return parse_device_list(out, 'fastboot')


def get_instances(serials):
  """Create AndroidDevice instances from a list of serials.

  Args:
    serials: A list of android device serials.

  Returns:
    A list of AndroidDevice objects.
  """
  _validate_device_existence(serials)

  results = []
  for s in serials:
    results.append(AndroidDevice(s))
  return results


def get_instances_with_configs(configs):
  """Create AndroidDevice instances from a list of dict configs.

  Each config should have the required key-value pair 'serial'.

  Args:
    configs: A list of dicts each representing the configuration of one
      android device.

  Returns:
    A list of AndroidDevice objects.
  """
  # First make sure each config contains a serial, and all the serials'
  # corresponding devices exist.
  serials = []
  for c in configs:
    try:
      serials.append(c['serial'])
    except KeyError:
      raise Error(
          'Required value "serial" is missing in AndroidDevice config %s.' % c)
  _validate_device_existence(serials)
  results = []
  for c in configs:
    serial = c.pop('serial')
    is_required = c.get(KEY_DEVICE_REQUIRED, True)
    try:
      ad = AndroidDevice(serial)
      ad.load_config(c)
    except Exception:
      if is_required:
        raise
      ad.log.exception('Skipping this optional device due to error.')
      continue
    results.append(ad)
  return results


def get_all_instances(include_fastboot=False):
  """Create AndroidDevice instances for all attached android devices.

  Args:
    include_fastboot: Whether to include devices in bootloader mode or not.

  Returns:
    A list of AndroidDevice objects each representing an android device
    attached to the computer.
  """
  if include_fastboot:
    serial_list = list_adb_devices() + list_fastboot_devices()
    return get_instances(serial_list)
  return get_instances(list_adb_devices())


def filter_devices(ads, func):
  """Finds the AndroidDevice instances from a list that match certain
  conditions.

  Args:
    ads: A list of AndroidDevice instances.
    func: A function that takes an AndroidDevice object and returns True
      if the device satisfies the filter condition.

  Returns:
    A list of AndroidDevice instances that satisfy the filter condition.
  """
  results = []
  for ad in ads:
    if func(ad):
      results.append(ad)
  return results


def get_devices(ads, **kwargs):
  """Finds a list of AndroidDevice instance from a list that has specific
  attributes of certain values.

  Example:
    get_devices(android_devices, label='foo', phone_number='1234567890')
    get_devices(android_devices, model='angler')

  Args:
    ads: A list of AndroidDevice instances.
    kwargs: keyword arguments used to filter AndroidDevice instances.

  Returns:
    A list of target AndroidDevice instances.

  Raises:
    Error: No devices are matched.
  """

  def _get_device_filter(ad):
    for k, v in kwargs.items():
      if not hasattr(ad, k):
        return False
      elif getattr(ad, k) != v:
        return False
    return True

  filtered = filter_devices(ads, _get_device_filter)
  if not filtered:
    raise Error('Could not find a target device that matches condition: %s.' %
                kwargs)
  else:
    return filtered


def get_device(ads, **kwargs):
  """Finds a unique AndroidDevice instance from a list that has specific
  attributes of certain values.

  Example:
    get_device(android_devices, label='foo', phone_number='1234567890')
    get_device(android_devices, model='angler')

  Args:
    ads: A list of AndroidDevice instances.
    kwargs: keyword arguments used to filter AndroidDevice instances.

  Returns:
    The target AndroidDevice instance.

  Raises:
    Error: None or more than one device is matched.
  """

  filtered = get_devices(ads, **kwargs)
  if len(filtered) == 1:
    return filtered[0]
  else:
    serials = [ad.serial for ad in filtered]
    raise Error('More than one device matched: %s' % serials)


def take_bug_reports(ads, test_name=None, begin_time=None, destination=None):
  """Takes bug reports on a list of android devices.

  If you want to take a bug report, call this function with a list of
  android_device objects in on_fail. But reports will be taken on all the
  devices in the list concurrently. Bug report takes a relative long
  time to take, so use this cautiously.

  Args:
    ads: A list of AndroidDevice instances.
    test_name: Name of the test method that triggered this bug report.
      If None, the default name "bugreport" will be used.
    begin_time: timestamp taken when the test started, can be either
      string or int. If None, the current time will be used.
    destination: string, path to the directory where the bugreport
      should be saved.
  """
  if begin_time is None:
    begin_time = mobly_logger.get_log_file_timestamp()
  else:
    begin_time = mobly_logger.sanitize_filename(str(begin_time))

  def take_br(test_name, begin_time, ad, destination):
    ad.take_bug_report(test_name=test_name,
                       begin_time=begin_time,
                       destination=destination)

  args = [(test_name, begin_time, ad, destination) for ad in ads]
  utils.concurrent_exec(take_br, args)


class AndroidDevice:
  """Class representing an android device.

  Each object of this class represents one Android device in Mobly. This class
  provides various ways, like adb, fastboot, and Mobly snippets, to control
  an Android device, whether it's a real device or an emulator instance.

  You can also register your own services to the device's service manager.
  See the docs of `service_manager` and `base_service` for details.

  Attributes:
    serial: A string that's the serial number of the Android device.
    log_path: A string that is the path where all logs collected on this
      android device should be stored.
    log: A logger adapted from root logger with an added prefix specific
      to an AndroidDevice instance. The default prefix is
      [AndroidDevice|<serial>]. Use self.debug_tag = 'tag' to use a
      different tag in the prefix.
    adb_logcat_file_path: A string that's the full path to the adb logcat
      file collected, if any.
    adb: An AdbProxy object used for interacting with the device via adb.
    fastboot: A FastbootProxy object used for interacting with the device
      via fastboot.
    services: ServiceManager, the manager of long-running services on the
      device.
  """

  def __init__(self, serial=''):
    self._serial = str(serial)
    # logging.log_path only exists when this is used in an Mobly test run.
    self._log_path_base = getattr(logging, 'log_path', '/tmp/logs')
    self._log_path = os.path.join(self._log_path_base,
                                  'AndroidDevice%s' % self._normalized_serial)
    self._debug_tag = self._serial
    self.log = AndroidDeviceLoggerAdapter(logging.getLogger(),
                                          {'tag': self.debug_tag})
    self._build_info = None
    self._is_rebooting = False
    self.adb = adb.AdbProxy(serial)
    self.fastboot = fastboot.FastbootProxy(serial)
    if self.is_rootable:
      self.root_adb()
    self.services = service_manager.ServiceManager(self)
    self.services.register(SERVICE_NAME_LOGCAT,
                           logcat.Logcat,
                           start_service=False)
    self.services.register('snippets',
                           snippet_management_service.SnippetManagementService)
    # Device info cache.
    self._user_added_device_info = {}

  def __repr__(self):
    return '<AndroidDevice|%s>' % self.debug_tag

  @property
  def adb_logcat_file_path(self):
    if self.services.has_service_by_name(SERVICE_NAME_LOGCAT):
      return self.services.logcat.adb_logcat_file_path

  @property
  def _normalized_serial(self):
    """Normalized serial name for usage in log filename.

    Some Android emulators use ip:port as their serial names, while on
    Windows `:` is not valid in filename, it should be sanitized first.
    """
    if self._serial is None:
      return None
    return mobly_logger.sanitize_filename(self._serial)

  @property
  def device_info(self):
    """Information to be pulled into controller info.

    The latest serial, model, and build_info are included. Additional info
    can be added via `add_device_info`.
    """
    info = {
        'serial': self.serial,
        'model': self.model,
        'build_info': self.build_info,
        'user_added_info': self._user_added_device_info
    }
    return info

  def add_device_info(self, name, info):
    """Add information of the device to be pulled into controller info.

    Adding the same info name the second time will override existing info.

    Args:
      name: string, name of this info.
      info: serializable, content of the info.
    """
    self._user_added_device_info.update({name: info})

  @property
  def sl4a(self):
    """Attribute for direct access of sl4a client.

    Not recommended. This is here for backward compatibility reasons.

    Preferred: directly access `ad.services.sl4a`.
    """
    if self.services.has_service_by_name('sl4a'):
      return self.services.sl4a

  @property
  def ed(self):
    """Attribute for direct access of sl4a's event dispatcher.

    Not recommended. This is here for backward compatibility reasons.

    Preferred: directly access `ad.services.sl4a.ed`.
    """
    if self.services.has_service_by_name('sl4a'):
      return self.services.sl4a.ed

  @property
  def debug_tag(self):
    """A string that represents a device object in debug info. Default value
    is the device serial.

    This will be used as part of the prefix of debugging messages emitted by
    this device object, like log lines and the message of DeviceError.
    """
    return self._debug_tag

  @debug_tag.setter
  def debug_tag(self, tag):
    """Setter for the debug tag.

    By default, the tag is the serial of the device, but sometimes it may
    be more descriptive to use a different tag of the user's choice.

    Changing debug tag changes part of the prefix of debug info emitted by
    this object, like log lines and the message of DeviceError.

    Example:
      By default, the device's serial number is used:
        'INFO [AndroidDevice|abcdefg12345] One pending call ringing.'
      The tag can be customized with `ad.debug_tag = 'Caller'`:
        'INFO [AndroidDevice|Caller] One pending call ringing.'
    """
    self.log.info('Logging debug tag set to "%s"', tag)
    self._debug_tag = tag
    self.log.extra['tag'] = tag

  @property
  def has_active_service(self):
    """True if any service is running on the device.

    A service can be a snippet or logcat collection.
    """
    return self.services.is_any_alive

  @property
  def log_path(self):
    """A string that is the path for all logs collected from this device.
    """
    return self._log_path

  @log_path.setter
  def log_path(self, new_path):
    """Setter for `log_path`, use with caution."""
    if self.has_active_service:
      raise DeviceError(
          self, 'Cannot change `log_path` when there is service running.')
    old_path = self._log_path
    if new_path == old_path:
      return
    if os.listdir(new_path):
      raise DeviceError(self,
                        'Logs already exist at %s, cannot override.' % new_path)
    if os.path.exists(old_path):
      # Remove new path so copytree doesn't complain.
      shutil.rmtree(new_path, ignore_errors=True)
      shutil.copytree(old_path, new_path)
      shutil.rmtree(old_path, ignore_errors=True)
    self._log_path = new_path

  @property
  def serial(self):
    """The serial number used to identify a device.

    This is essentially the value used for adb's `-s` arg, which means it
    can be a network address or USB bus number.
    """
    return self._serial

  def update_serial(self, new_serial):
    """Updates the serial number of a device.

    The "serial number" used with adb's `-s` arg is not necessarily the
    actual serial number. For remote devices, it could be a combination of
    host names and port numbers.

    This is used for when such identifier of remote devices changes during
    a test. For example, when a remote device reboots, it may come back
    with a different serial number.

    This is NOT meant for switching the object to represent another device.

    We intentionally did not make it a regular setter of the serial
    property so people don't accidentally call this without understanding
    the consequences.

    Args:
      new_serial: string, the new serial number for the same device.

    Raises:
      DeviceError: tries to update serial when any service is running.
    """
    new_serial = str(new_serial)
    if self.has_active_service:
      raise DeviceError(
          self,
          'Cannot change device serial number when there is service running.')
    if self._debug_tag == self.serial:
      self._debug_tag = new_serial
    self._serial = new_serial
    self.adb.serial = new_serial
    self.fastboot.serial = new_serial

  @contextlib.contextmanager
  def handle_reboot(self):
    """Properly manage the service life cycle when the device needs to
    temporarily disconnect.

    The device can temporarily lose adb connection due to user-triggered
    reboot. Use this function to make sure the services
    started by Mobly are properly stopped and restored afterwards.

    For sample usage, see self.reboot().
    """
    live_service_names = self.services.list_live_services()
    self.services.stop_all()
    # On rooted devices, system properties may change on reboot, so disable
    # the `build_info` cache by setting `_is_rebooting` to True and
    # repopulate it after reboot.
    # Note, this logic assumes that instance variable assignment in Python
    # is atomic; otherwise, `threading` data structures would be necessary.
    # Additionally, nesting calls to `handle_reboot` while changing the
    # read-only property values during reboot will result in stale values.
    self._is_rebooting = True
    try:
      yield
    finally:
      self.wait_for_boot_completion()
      # On boot completion, invalidate the `build_info` cache since any
      # value it had from before boot completion is potentially invalid.
      # If the value gets set after the final invalidation and before
      # setting`_is_rebooting` to True, then that's okay because the
      # device has finished rebooting at that point, and values at that
      # point should be valid.
      # If the reboot fails for some reason, then `_is_rebooting` is never
      # set to False, which means the `build_info` cache remains disabled
      # until the next reboot. This is relatively okay because the
      # `build_info` cache is only minimizes adb commands.
      self._build_info = None
      self._is_rebooting = False
      if self.is_rootable:
        self.root_adb()
    self.services.start_services(live_service_names)

  @contextlib.contextmanager
  def handle_usb_disconnect(self):
    """Properly manage the service life cycle when USB is disconnected.

    The device can temporarily lose adb connection due to user-triggered
    USB disconnection, e.g. the following cases can be handled by this
    method:

    * Power measurement: Using Monsoon device to measure battery consumption
      would potentially disconnect USB.
    * Unplug USB so device loses connection.
    * ADB connection over WiFi and WiFi got disconnected.
    * Any other type of USB disconnection, as long as snippet session can
      be kept alive while USB disconnected (reboot caused USB
      disconnection is not one of these cases because snippet session
      cannot survive reboot.
      Use handle_reboot() instead).

    Use this function to make sure the services started by Mobly are
    properly reconnected afterwards.

    Just like the usage of self.handle_reboot(), this method does not
    automatically detect if the disconnection is because of a reboot or USB
    disconnect. Users of this function should make sure the right handle_*
    function is used to handle the correct type of disconnection.

    This method also reconnects snippet event client. Therefore, the
    callback objects created (by calling Async RPC methods) before
    disconnection would still be valid and can be used to retrieve RPC
    execution result after device got reconnected.

    Example Usage:

    .. code-block:: python

      with ad.handle_usb_disconnect():
        try:
          # User action that triggers USB disconnect, could throw
          # exceptions.
          do_something()
        finally:
          # User action that triggers USB reconnect
          action_that_reconnects_usb()
          # Make sure device is reconnected before returning from this
          # context
          ad.adb.wait_for_device(timeout=SOME_TIMEOUT)
    """
    live_service_names = self.services.list_live_services()
    self.services.pause_all()
    try:
      yield
    finally:
      self.services.resume_services(live_service_names)

  @property
  def build_info(self):
    """Get the build info of this Android device, including build id and
    build type.

    This is not available if the device is in bootloader mode.

    Returns:
      A dict with the build info of this Android device, or None if the
      device is in bootloader mode.
    """
    if self.is_bootloader:
      self.log.error('Device is in fastboot mode, could not get build ' 'info.')
      return
    if self._build_info is None or self._is_rebooting:
      info = {}
      build_info = self.adb.getprops(CACHED_SYSTEM_PROPS)
      info['build_id'] = build_info['ro.build.id']
      info['build_type'] = build_info['ro.build.type']
      info['build_fingerprint'] = build_info.get('ro.build.fingerprint', '')
      info['build_version_codename'] = build_info.get(
          'ro.build.version.codename', '')
      info['build_version_incremental'] = build_info.get(
          'ro.build.version.incremental', '')
      info['build_version_sdk'] = build_info.get('ro.build.version.sdk', '')
      info['build_product'] = build_info.get('ro.build.product', '')
      info['build_characteristics'] = build_info.get('ro.build.characteristics',
                                                     '')
      info['debuggable'] = build_info.get('ro.debuggable', '')
      info['product_name'] = build_info.get('ro.product.name', '')
      info['hardware'] = build_info.get('ro.hardware', '')
      self._build_info = info
      return info
    return self._build_info

  @property
  def is_bootloader(self):
    """True if the device is in bootloader mode.
    """
    return self.serial in list_fastboot_devices()

  @property
  def is_adb_root(self):
    """True if adb is running as root for this device.
    """
    try:
      return '0' == self.adb.shell('id -u').decode('utf-8').strip()
    except adb.AdbError:
      # Wait a bit and retry to work around adb flakiness for this cmd.
      time.sleep(0.2)
      return '0' == self.adb.shell('id -u').decode('utf-8').strip()

  @property
  def is_rootable(self):
    return not self.is_bootloader and self.build_info['debuggable'] == '1'

  @property
  def model(self):
    """The Android code name for the device.
    """
    # If device is in bootloader mode, get mode name from fastboot.
    if self.is_bootloader:
      out = self.fastboot.getvar('product').strip()
      # 'out' is never empty because of the 'total time' message fastboot
      # writes to stderr.
      lines = out.decode('utf-8').split('\n', 1)
      if lines:
        tokens = lines[0].split(' ')
        if len(tokens) > 1:
          return tokens[1].lower()
      return None
    model = self.build_info['build_product'].lower()
    if model == 'sprout':
      return model
    return self.build_info['product_name'].lower()

  @property
  def is_emulator(self):
    """Whether this device is probably an emulator.

    Returns:
      True if this is probably an emulator.
    """
    if EMULATOR_SERIAL_REGEX.match(self.serial):
      # If the device's serial follows 'emulator-dddd', then it's almost
      # certainly an emulator.
      return True
    elif self.build_info['build_characteristics'] == 'emulator':
      # If the device says that it's an emulator, then it's probably an
      # emulator although some real devices apparently report themselves
      # as emulators in addition to other things, so only return True on
      # an exact match.
      return True
    elif self.build_info['hardware'] in ['ranchu', 'goldfish']:
      # Ranchu and Goldfish are the hardware properties that the AOSP
      # emulators report, so if the device says it's an AOSP emulator, it
      # probably is one.
      return True
    else:
      return False

  def load_config(self, config):
    """Add attributes to the AndroidDevice object based on config.

    Args:
      config: A dictionary representing the configs.

    Raises:
      Error: The config is trying to overwrite an existing attribute.
    """
    for k, v in config.items():
      if hasattr(self, k) and k not in _ANDROID_DEVICE_SETTABLE_PROPS:
        raise DeviceError(
            self, ('Attribute %s already exists with value %s, cannot set '
                   'again.') % (k, getattr(self, k)))
      setattr(self, k, v)

  def root_adb(self):
    """Change adb to root mode for this device if allowed.

    If executed on a production build, adb will not be switched to root
    mode per security restrictions.
    """
    self.adb.root()
    # `root` causes the device to temporarily disappear from adb.
    # So we need to wait for the device to come back before proceeding.
    self.adb.wait_for_device(timeout=DEFAULT_TIMEOUT_BOOT_COMPLETION_SECOND)

  def load_snippet(self, name, package):
    """Starts the snippet apk with the given package name and connects.

    Examples:

    .. code-block:: python

      ad.load_snippet(
          name='maps', package='com.google.maps.snippets')
      ad.maps.activateZoom('3')

    Args:
      name: string, the attribute name to which to attach the snippet
        client. E.g. `name='maps'` attaches the snippet client to
        `ad.maps`.
      package: string, the package name of the snippet apk to connect to.

    Raises:
      SnippetError: Illegal load operations are attempted.
    """
    # Should not load snippet with an existing attribute.
    if hasattr(self, name):
      raise SnippetError(
          self,
          'Attribute "%s" already exists, please use a different name.' % name)
    self.services.snippets.add_snippet_client(name, package)

  def unload_snippet(self, name):
    """Stops a snippet apk.

    Args:
      name: The attribute name the snippet server is attached with.

    Raises:
      SnippetError: The given snippet name is not registered.
    """
    self.services.snippets.remove_snippet_client(name)

  def generate_filename(self,
                        file_type,
                        time_identifier=None,
                        extension_name=None):
    """Generates a name for an output file related to this device.

    The name follows the pattern:

      {file type},{debug_tag},{serial},{model},{time identifier}.{ext}

    "debug_tag" is only added if it's different from the serial. "ext" is
    added if specified by user.

    Args:
      file_type: string, type of this file, like "logcat" etc.
      time_identifier: string or RuntimeTestInfo. If a `RuntimeTestInfo`
        is passed in, the `signature` of the test case will be used. If
        a string is passed in, the string itself will be used.
        Otherwise the current timestamp will be used.
      extension_name: string, the extension name of the file.

    Returns:
      String, the filename generated.
    """
    time_str = time_identifier
    if time_identifier is None:
      time_str = mobly_logger.get_log_file_timestamp()
    elif isinstance(time_identifier, runtime_test_info.RuntimeTestInfo):
      time_str = time_identifier.signature
    filename_tokens = [file_type]
    if self.debug_tag != self.serial:
      filename_tokens.append(self.debug_tag)
    filename_tokens.extend([self.serial, self.model, time_str])
    filename_str = ','.join(filename_tokens)
    if extension_name is not None:
      filename_str = '%s.%s' % (filename_str, extension_name)
    filename_str = mobly_logger.sanitize_filename(filename_str)
    self.log.debug('Generated filename: %s', filename_str)
    return filename_str

  def take_bug_report(self,
                      test_name=None,
                      begin_time=None,
                      timeout=300,
                      destination=None):
    """Takes a bug report on the device and stores it in a file.

    Args:
      test_name: Name of the test method that triggered this bug report.
      begin_time: Timestamp of when the test started. If not set, then
        this will default to the current time.
      timeout: float, the number of seconds to wait for bugreport to
        complete, default is 5min.
      destination: string, path to the directory where the bugreport
        should be saved.

    Returns:
      A string that is the absolute path to the bug report on the host.
    """
    prefix = DEFAULT_BUG_REPORT_NAME
    if test_name:
      prefix = '%s,%s' % (DEFAULT_BUG_REPORT_NAME, test_name)
    if begin_time is None:
      begin_time = mobly_logger.get_log_file_timestamp()

    new_br = True
    try:
      stdout = self.adb.shell('bugreportz -v').decode('utf-8')
      # This check is necessary for builds before N, where adb shell's ret
      # code and stderr are not propagated properly.
      if 'not found' in stdout:
        new_br = False
    except adb.AdbError:
      new_br = False

    if destination is None:
      destination = os.path.join(self.log_path, 'BugReports')
    br_path = utils.abs_path(destination)
    utils.create_dir(br_path)
    filename = self.generate_filename(prefix, str(begin_time), 'txt')
    if new_br:
      filename = filename.replace('.txt', '.zip')
    full_out_path = os.path.join(br_path, filename)
    # in case device restarted, wait for adb interface to return
    self.wait_for_boot_completion()
    self.log.debug('Start taking bugreport.')
    if new_br:
      out = self.adb.shell('bugreportz', timeout=timeout).decode('utf-8')
      if not out.startswith('OK'):
        raise DeviceError(self, 'Failed to take bugreport: %s' % out)
      br_out_path = out.split(':')[1].strip()
      self.adb.pull([br_out_path, full_out_path])
      self.adb.shell(['rm', br_out_path])
    else:
      # shell=True as this command redirects the stdout to a local file
      # using shell redirection.
      self.adb.bugreport(' > "%s"' % full_out_path, shell=True, timeout=timeout)
    self.log.debug('Bugreport taken at %s.', full_out_path)
    return full_out_path

  def take_screenshot(self, destination, prefix='screenshot'):
    """Takes a screenshot of the device.

    Args:
      destination: string, full path to the directory to save in.
      prefix: string, prefix file name of the screenshot.

    Returns:
      string, full path to the screenshot file on the host.
    """
    filename = self.generate_filename(prefix, extension_name='png')
    device_path = os.path.join('/storage/emulated/0/', filename)
    self.adb.shell(['screencap', '-p', device_path],
                   timeout=TAKE_SCREENSHOT_TIMEOUT_SECOND)
    utils.create_dir(destination)
    self.adb.pull([device_path, destination])
    pic_path = os.path.join(destination, filename)
    self.log.debug('Screenshot taken, saved on the host: %s', pic_path)
    self.adb.shell(['rm', device_path])
    return pic_path

  def run_iperf_client(self, server_host, extra_args=''):
    """Start iperf client on the device.

    Return status as true if iperf client start successfully.
    And data flow information as results.

    Args:
      server_host: Address of the iperf server.
      extra_args: A string representing extra arguments for iperf client,
        e.g. '-i 1 -t 30'.

    Returns:
      status: true if iperf client start successfully.
      results: results have data flow information
    """
    out = self.adb.shell('iperf3 -c %s %s' % (server_host, extra_args))
    clean_out = str(out, 'utf-8').strip().split('\n')
    if 'error' in clean_out[0].lower():
      return False, clean_out
    return True, clean_out

  def wait_for_boot_completion(self,
                               timeout=DEFAULT_TIMEOUT_BOOT_COMPLETION_SECOND):
    """Waits for Android framework to broadcast ACTION_BOOT_COMPLETED.

    This function times out after 15 minutes.

    Args:
      timeout: float, the number of seconds to wait before timing out.
        If not specified, no timeout takes effect.
    """
    deadline = time.perf_counter() + timeout

    self.adb.wait_for_device(timeout=timeout)
    while time.perf_counter() < deadline:
      try:
        if self.is_boot_completed():
          return
      except (adb.AdbError, adb.AdbTimeoutError):
        # adb shell calls may fail during certain period of booting
        # process, which is normal. Ignoring these errors.
        pass
      time.sleep(5)
    raise DeviceError(self, 'Booting process timed out')

  def is_boot_completed(self):
    """Checks if device boot is completed by verifying system property."""
    completed = self.adb.getprop('sys.boot_completed')
    if completed == '1':
      self.log.debug('Device boot completed.')
      return True
    return False

  def is_adb_detectable(self):
    """Checks if USB is on and device is ready by verifying adb devices."""
    serials = list_adb_devices()
    if self.serial in serials:
      self.log.debug('Is now adb detectable.')
      return True
    return False

  def reboot(self):
    """Reboots the device.

    Generally one should use this method to reboot the device instead of
    directly calling `adb.reboot`. Because this method gracefully handles
    the teardown and restoration of running services.

    This method is blocking and only returns when the reboot has completed
    and the services restored.

    Raises:
      Error: Waiting for completion timed out.
    """
    if self.is_bootloader:
      self.fastboot.reboot()
      return
    with self.handle_reboot():
      self.adb.reboot()

  def __getattr__(self, name):
    """Tries to return a snippet client registered with `name`.

    This is for backward compatibility of direct accessing snippet clients.
    """
    client = self.services.snippets.get_snippet_client(name)
    if client:
      return client
    return self.__getattribute__(name)


# Properties in AndroidDevice that have setters.
# This line has to live below the AndroidDevice code.
_ANDROID_DEVICE_SETTABLE_PROPS = utils.get_settable_properties(AndroidDevice)


class AndroidDeviceLoggerAdapter(logging.LoggerAdapter):
  """A wrapper class that adds a prefix to each log line.

  Usage:

  .. code-block:: python

    my_log = AndroidDeviceLoggerAdapter(logging.getLogger(), {
      'tag': <custom tag>
    })

  Then each log line added by my_log will have a prefix
  '[AndroidDevice|<tag>]'
  """

  def process(self, msg, kwargs):
    msg = _DEBUG_PREFIX_TEMPLATE % (self.extra['tag'], msg)
    return (msg, kwargs)
