# 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.version.codename',
    '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)
  valid_ad_identifiers = list_adb_devices() + list_adb_devices_by_usb_id()

  for ad in ads:
    if ad.serial not in valid_ad_identifiers:
      raise DeviceError(
          ad, 'Android device is specified in config but is not '
          'attached.')
  _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:
      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 _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.
  """
  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.
  """
  results = []
  for c in configs:
    try:
      serial = c.pop('serial')
    except KeyError:
      raise Error(
          'Required value "serial" is missing in AndroidDevice config %s.' % c)
    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 Androi 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_version_codename'] = build_info.get(
          'ro.build.version.codename', '')
      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):
    """Takes a screenshot of the device.

    Args:
      destination: string, full path to the directory to save in.

    Returns:
      string, full path to the screenshot file on the host.
    """
    filename = self.generate_filename('screenshot', 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.
    """
    timeout_start = time.time()

    self.adb.wait_for_device(timeout=timeout)
    while time.time() < timeout_start + timeout:
      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)
