예제 #1
0
    def SetCharging(self, enabled, timeout=None, retries=None):
        """Enables or disables charging on the device.

    Args:
      enabled: A boolean indicating whether charging should be enabled or
        disabled.
      timeout: timeout in seconds
      retries: number of retries

    Raises:
      device_errors.CommandFailedError: If method of disabling charging cannot
        be determined.
    """
        if 'charging_config' not in self._cache:
            for c in _CONTROL_CHARGING_COMMANDS:
                if self._device.FileExists(c['witness_file']):
                    self._cache['charging_config'] = c
                    break
            else:
                raise device_errors.CommandFailedError(
                    'Unable to find charging commands.')

        if enabled:
            command = self._cache['charging_config']['enable_command']
        else:
            command = self._cache['charging_config']['disable_command']

        def set_and_verify_charging():
            self._device.RunShellCommand(command, check_return=True)
            return self.GetCharging() == enabled

        timeout_retry.WaitFor(set_and_verify_charging, wait_period=1)
예제 #2
0
    def LetBatteryCoolToTemperature(self, target_temp, wait_period=180):
        """Lets device sit to give battery time to cool down
    Args:
      temp: maximum temperature to allow in tenths of degrees c.
      wait_period: time in seconds to wait between checking.
    """
        def cool_device():
            temp = self.GetBatteryInfo().get('temperature')
            if temp is None:
                logging.warning('Unable to find current battery temperature.')
                temp = 0
            else:
                logging.info('Current battery temperature: %s', temp)
            if int(temp) <= target_temp:
                return True
            else:
                if self._cache['profile']['name'] == 'Nexus 5':
                    self._DischargeDevice(1)
                return False

        self._DiscoverDeviceProfile()
        self.EnableBatteryUpdates()
        logging.info('Waiting for the device to cool down to %s (0.1 C)',
                     target_temp)
        timeout_retry.WaitFor(cool_device, wait_period=wait_period)
예제 #3
0
    def SetCharging(self, enabled, timeout=None, retries=None):
        """Enables or disables charging on the device.

    Args:
      enabled: A boolean indicating whether charging should be enabled or
        disabled.
      timeout: timeout in seconds
      retries: number of retries

    Raises:
      device_errors.CommandFailedError: If method of disabling charging cannot
        be determined.
    """
        self._DiscoverDeviceProfile()
        if not self._cache['profile']['enable_command']:
            raise device_errors.CommandFailedError(
                'Unable to find charging commands.')

        if enabled:
            command = self._cache['profile']['enable_command']
        else:
            command = self._cache['profile']['disable_command']

        def verify_charging():
            return self.GetCharging() == enabled

        self._device.RunShellCommand(command,
                                     check_return=True,
                                     as_root=True,
                                     large_output=True)
        timeout_retry.WaitFor(verify_charging, wait_period=1)
예제 #4
0
    def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None):
        """Wait for the device to fully boot.

    This means waiting for the device to boot, the package manager to be
    available, and the SD card to be ready. It can optionally mean waiting
    for wifi to come up, too.

    Args:
      wifi: A boolean indicating if we should wait for wifi to come up or not.
      timeout: timeout in seconds
      retries: number of retries

    Raises:
      CommandFailedError on failure.
      CommandTimeoutError if one of the component waits times out.
      DeviceUnreachableError if the device becomes unresponsive.
    """
        def sd_card_ready():
            try:
                self.RunShellCommand(
                    ['test', '-d', self.GetExternalStoragePath()],
                    check_return=True)
                return True
            except device_errors.AdbCommandFailedError:
                return False

        def pm_ready():
            try:
                return self.GetApplicationPath('android')
            except device_errors.CommandFailedError:
                return False

        def boot_completed():
            return self.GetProp('sys.boot_completed') == '1'

        def wifi_enabled():
            return 'Wi-Fi is enabled' in self.RunShellCommand(
                ['dumpsys', 'wifi'], check_return=False)

        self.adb.WaitForDevice()
        timeout_retry.WaitFor(sd_card_ready)
        timeout_retry.WaitFor(pm_ready)
        timeout_retry.WaitFor(boot_completed)
        if wifi:
            timeout_retry.WaitFor(wifi_enabled)
예제 #5
0
def RestartServer():
    """Restarts the adb server.

  Raises:
    CommandFailedError if we fail to kill or restart the server.
  """
    def adb_killed():
        return not adb_wrapper.AdbWrapper.IsServerOnline()

    def adb_started():
        return adb_wrapper.AdbWrapper.IsServerOnline()

    adb_wrapper.AdbWrapper.KillServer()
    if not timeout_retry.WaitFor(adb_killed, wait_period=1, max_tries=5):
        # TODO(perezju): raise an exception after fixng http://crbug.com/442319
        logging.warning('Failed to kill adb server')
    adb_wrapper.AdbWrapper.StartServer()
    if not timeout_retry.WaitFor(adb_started, wait_period=1, max_tries=5):
        raise device_errors.CommandFailedError('Failed to start adb server')
예제 #6
0
def FinishProvisioning(device, options):
    if options.min_battery_level is not None:
        try:
            battery = battery_utils.BatteryUtils(device)
            battery.ChargeDeviceToLevel(options.min_battery_level)
        except device_errors.CommandFailedError:
            logging.exception('Unable to charge device to specified level.')

    if options.max_battery_temp is not None:
        try:
            battery = battery_utils.BatteryUtils(device)
            battery.LetBatteryCoolToTemperature(options.max_battery_temp)
        except device_errors.CommandFailedError:
            logging.exception(
                'Unable to let battery cool to specified temperature.')

    def _set_and_verify_date():
        if (device.build_version_sdk >=
                constants.ANDROID_SDK_VERSION_CODES.MARSHMALLOW):
            date_format = '%m%d%H%M%Y.%S'
            set_date_command = ['date']
        else:
            date_format = '%Y%m%d.%H%M%S'
            set_date_command = ['date', '-s']
        strgmtime = time.strftime(date_format, time.gmtime())
        set_date_command.append(strgmtime)
        device.RunShellCommand(set_date_command,
                               as_root=True,
                               check_return=True)

        device_time = device.RunShellCommand(['date', '+"%Y%m%d.%H%M%S"'],
                                             as_root=True,
                                             single_line=True).replace(
                                                 '"', '')
        device_time = datetime.datetime.strptime(device_time, "%Y%m%d.%H%M%S")
        correct_time = datetime.datetime.strptime(strgmtime, date_format)
        tdelta = (correct_time - device_time).seconds
        if tdelta <= 1:
            logging.info('Date/time successfully set on %s', device)
            return True
        else:
            return False

    # Sometimes the date is not set correctly on the devices. Retry on failure.
    if not timeout_retry.WaitFor(
            _set_and_verify_date, wait_period=1, max_tries=2):
        raise device_errors.CommandFailedError('Failed to set date & time.',
                                               device_serial=str(device))

    props = device.RunShellCommand('getprop', check_return=True)
    for prop in props:
        logging.info('  %s' % prop)
    if options.auto_reconnect:
        _PushAndLaunchAdbReboot(device, options.target)
예제 #7
0
def ChargeDeviceToLevel(device, level):
    def device_charged():
        battery_level = device.GetBatteryInfo().get('level')
        if battery_level is None:
            logging.warning('Unable to find current battery level.')
            battery_level = 100
        else:
            logging.info('current battery level: %d', battery_level)
            battery_level = int(battery_level)
        return battery_level >= level

    timeout_retry.WaitFor(device_charged, wait_period=60)
예제 #8
0
    def EnableBatteryUpdates(self, timeout=None, retries=None):
        """Restarts device charging so that dumpsys no longer collects power data.

    Args:
      timeout: timeout in seconds
      retries: number of retries

    Raises:
      device_errors.DeviceVersionError: If device is not L or higher.
    """
        def battery_updates_enabled():
            return (self.GetCharging() or
                    not bool('UPDATES STOPPED' in self._device.RunShellCommand(
                        ['dumpsys', 'battery'], check_return=True)))

        self._device.RunShellCommand(['dumpsys', 'battery', 'reset'],
                                     check_return=True)
        timeout_retry.WaitFor(battery_updates_enabled, wait_period=1)
예제 #9
0
    def LetBatteryCoolToTemperature(self, target_temp, wait_period=60):
        """Lets device sit to give battery time to cool down
    Args:
      temp: maximum temperature to allow in tenths of degrees c.
      wait_period: time in seconds to wait between checking.
    """
        def cool_device():
            temp = self.GetBatteryInfo().get('temperature')
            if temp is None:
                logging.warning('Unable to find current battery temperature.')
                temp = 0
            else:
                logging.info('Current battery temperature: %s', temp)
            return int(temp) <= target_temp

        logging.info('Waiting for the device to cool down to %s degrees.',
                     target_temp)
        timeout_retry.WaitFor(cool_device, wait_period=wait_period)
예제 #10
0
    def DisableBatteryUpdates(self, timeout=None, retries=None):
        """ Resets battery data and makes device appear like it is not
    charging so that it will collect power data since last charge.

    Args:
      timeout: timeout in seconds
      retries: number of retries

    Raises:
      device_errors.CommandFailedError: When resetting batterystats fails to
        reset power values.
      device_errors.DeviceVersionError: If device is not L or higher.
    """
        def battery_updates_disabled():
            return self.GetCharging() is False

        if (self._device.build_version_sdk <
                constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
            raise device_errors.DeviceVersionError(
                'Device must be L or higher.')

        self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '1'],
                                     check_return=True)
        self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'ac', '1'],
                                     check_return=True)
        self._device.RunShellCommand(['dumpsys', 'batterystats', '--reset'],
                                     check_return=True)
        battery_data = self._device.RunShellCommand(
            ['dumpsys', 'batterystats', '--charged', '--checkin'],
            check_return=True,
            large_output=True)
        ROW_TYPE_INDEX = 3
        PWI_POWER_INDEX = 5
        for line in battery_data:
            l = line.split(',')
            if (len(l) > PWI_POWER_INDEX and l[ROW_TYPE_INDEX] == 'pwi'
                    and l[PWI_POWER_INDEX] != 0):
                raise device_errors.CommandFailedError(
                    'Non-zero pmi value found after reset.')
        self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'ac', '0'],
                                     check_return=True)
        self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '0'],
                                     check_return=True)
        timeout_retry.WaitFor(battery_updates_disabled, wait_period=1)
예제 #11
0
    def Reboot(self, block=True, timeout=None, retries=None):
        """Reboot the device.

    Args:
      block: A boolean indicating if we should wait for the reboot to complete.
      timeout: timeout in seconds
      retries: number of retries

    Raises:
      CommandTimeoutError on timeout.
      DeviceUnreachableError on missing device.
    """
        def device_offline():
            return not self.IsOnline()

        self.adb.Reboot()
        self._cache = {}
        timeout_retry.WaitFor(device_offline, wait_period=1)
        if block:
            self.WaitUntilFullyBooted()
예제 #12
0
    def ChargeDeviceToLevel(self, level, wait_period=60):
        """Enables charging and waits for device to be charged to given level.

    Args:
      level: level of charge to wait for.
      wait_period: time in seconds to wait between checking.
    """
        self.SetCharging(True)

        def device_charged():
            battery_level = self.GetBatteryInfo().get('level')
            if battery_level is None:
                logging.warning('Unable to find current battery level.')
                battery_level = 100
            else:
                logging.info('current battery level: %s', battery_level)
                battery_level = int(battery_level)
            return battery_level >= level

        timeout_retry.WaitFor(device_charged, wait_period=wait_period)
예제 #13
0
    def EnableBatteryUpdates(self, timeout=None, retries=None):
        """ Restarts device charging so that dumpsys no longer collects power data.

    Args:
      timeout: timeout in seconds
      retries: number of retries

    Raises:
      device_errors.DeviceVersionError: If device is not L or higher.
    """
        def battery_updates_enabled():
            return self.GetCharging() is True

        if (self._device.build_version_sdk <
                constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
            raise device_errors.DeviceVersionError(
                'Device must be L or higher.')

        self._device.RunShellCommand(['dumpsys', 'battery', 'reset'],
                                     check_return=True)
        timeout_retry.WaitFor(battery_updates_enabled, wait_period=1)
예제 #14
0
  def Reboot(self, block=True, wifi=False, timeout=None, retries=None):
    """Reboot the device.

    Args:
      block: A boolean indicating if we should wait for the reboot to complete.
      wifi: A boolean indicating if we should wait for wifi to be enabled after
        the reboot. The option has no effect unless |block| is also True.
      timeout: timeout in seconds
      retries: number of retries

    Raises:
      CommandTimeoutError on timeout.
      DeviceUnreachableError on missing device.
    """
    def device_offline():
      return not self.IsOnline()

    self.adb.Reboot()
    self._cache = {}
    timeout_retry.WaitFor(device_offline, wait_period=1)
    if block:
      self.WaitUntilFullyBooted(wifi=wifi)
예제 #15
0
    def DisableBatteryUpdates(self, timeout=None, retries=None):
        """Resets battery data and makes device appear like it is not
    charging so that it will collect power data since last charge.

    Args:
      timeout: timeout in seconds
      retries: number of retries

    Raises:
      device_errors.CommandFailedError: When resetting batterystats fails to
        reset power values.
      device_errors.DeviceVersionError: If device is not L or higher.
    """
        def battery_updates_disabled():
            return self.GetCharging() is False

        self._ClearPowerData()
        self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'ac', '0'],
                                     check_return=True)
        self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '0'],
                                     check_return=True)
        timeout_retry.WaitFor(battery_updates_disabled, wait_period=1)
예제 #16
0
    def _DischargeDevice(self, percent, wait_period=120):
        """Disables charging and waits for device to discharge given amount

    Args:
      percent: level of charge to discharge.

    Raises:
      ValueError: If percent is not between 1 and 99.
    """
        battery_level = int(self.GetBatteryInfo().get('level'))
        if not 0 < percent < 100:
            raise ValueError('Discharge amount(%s) must be between 1 and 99' %
                             percent)
        if battery_level is None:
            logging.warning(
                'Unable to find current battery level. Cannot discharge.')
            return
        # Do not discharge if it would make battery level too low.
        if percent >= battery_level - 10:
            logging.warning(
                'Battery is too low or discharge amount requested is too '
                'high. Cannot discharge phone %s percent.', percent)
            return

        self.SetCharging(False)

        def device_discharged():
            self.SetCharging(True)
            current_level = int(self.GetBatteryInfo().get('level'))
            logging.info('current battery level: %s', current_level)
            if battery_level - current_level >= percent:
                return True
            self.SetCharging(False)
            return False

        timeout_retry.WaitFor(device_discharged, wait_period=wait_period)
예제 #17
0
def main():
    parser = optparse.OptionParser()
    parser.add_option('',
                      '--out-dir',
                      help='Directory where the device path is stored',
                      default=os.path.join(constants.DIR_SOURCE_ROOT, 'out'))
    parser.add_option(
        '--no-provisioning-check',
        action='store_true',
        help='Will not check if devices are provisioned properly.')
    parser.add_option('--device-status-dashboard',
                      action='store_true',
                      help='Output device status data for dashboard.')
    parser.add_option('--restart-usb',
                      action='store_true',
                      help='DEPRECATED. '
                      'This script now always tries to reset USB.')
    parser.add_option('--json-output',
                      help='Output JSON information into a specified file.')
    parser.add_option('-v',
                      '--verbose',
                      action='count',
                      default=1,
                      help='Log more information.')

    options, args = parser.parse_args()
    if args:
        parser.error('Unknown options %s' % args)

    run_tests_helper.SetLogLevel(options.verbose)

    # Remove the last build's "bad devices" before checking device statuses.
    device_blacklist.ResetBlacklist()

    KillAllAdb()
    reset_usb.reset_all_android_devices()

    try:
        expected_devices = set(
            device_list.GetPersistentDeviceList(
                os.path.join(options.out_dir,
                             device_list.LAST_DEVICES_FILENAME)))
    except IOError:
        expected_devices = set()

    def all_devices_found():
        devices = device_utils.DeviceUtils.HealthyDevices()
        device_serials = set(d.adb.GetDeviceSerial() for d in devices)
        return not bool(expected_devices.difference(device_serials))

    timeout_retry.WaitFor(all_devices_found, wait_period=1, max_tries=5)

    devices = device_utils.DeviceUtils.HealthyDevices()
    device_serials = set(d.adb.GetDeviceSerial() for d in devices)

    missing_devices = expected_devices.difference(device_serials)
    new_devices = device_serials.difference(expected_devices)

    if missing_devices or new_devices:
        logging.warning('expected_devices:')
        for d in sorted(expected_devices):
            logging.warning('  %s', d)
        logging.warning('devices:')
        for d in sorted(device_serials):
            logging.warning('  %s', d)

    types, builds, batteries, errors, devices_ok, json_data = ([], [], [], [],
                                                               [], [])
    if devices:
        types, builds, batteries, errors, devices_ok, json_data = (zip(
            *[DeviceInfo(dev, options) for dev in devices]))

    # Write device info to file for buildbot info display.
    if os.path.exists('/home/chrome-bot'):
        with open('/home/chrome-bot/.adb_device_info', 'w') as f:
            for device in json_data:
                try:
                    f.write('%s %s %s %.1fC %s%%\n' %
                            (device['serial'], device['type'], device['build'],
                             float(device['battery']['temperature']) / 10,
                             device['battery']['level']))
                except Exception:
                    pass

    err_msg = CheckForMissingDevices(options, devices) or []

    unique_types = list(set(types))
    unique_builds = list(set(builds))

    bb_annotations.PrintMsg('Online devices: %d. Device types %s, builds %s' %
                            (len(devices), unique_types, unique_builds))

    for j in json_data:
        logging.info('Device %s (%s)', j.get('serial'), j.get('type'))
        logging.info('  Build: %s (%s)', j.get('build'), j.get('build_detail'))
        logging.info('  Current Battery Service state:')
        for k, v in j.get('battery', {}).iteritems():
            logging.info('    %s: %s', k, v)
        logging.info('  IMEI slice: %s', j.get('imei_slice'))
        logging.info('  WiFi IP: %s', j.get('wifi_ip'))

    for dev, dev_errors in zip(devices, errors):
        if dev_errors:
            err_msg += ['%s errors:' % str(dev)]
            err_msg += ['    %s' % error for error in dev_errors]

    if err_msg:
        bb_annotations.PrintWarning()
        for e in err_msg:
            logging.error(e)
        from_address = '*****@*****.**'
        to_addresses = ['*****@*****.**']
        bot_name = os.environ.get('BUILDBOT_BUILDERNAME')
        slave_name = os.environ.get('BUILDBOT_SLAVENAME')
        subject = 'Device status check errors on %s, %s.' % (slave_name,
                                                             bot_name)
        SendEmail(from_address, to_addresses, [], subject, '\n'.join(err_msg))

    if options.device_status_dashboard:
        offline_devices = [
            device_utils.DeviceUtils(a)
            for a in adb_wrapper.AdbWrapper.Devices(is_ready=False)
            if a.GetState() == 'offline'
        ]

        perf_tests_results_helper.PrintPerfResult('BotDevices',
                                                  'OnlineDevices',
                                                  [len(devices)], 'devices')
        perf_tests_results_helper.PrintPerfResult('BotDevices',
                                                  'OfflineDevices',
                                                  [len(offline_devices)],
                                                  'devices', 'unimportant')
        for dev, battery in zip(devices, batteries):
            perf_tests_results_helper.PrintPerfResult('DeviceBattery',
                                                      str(dev), [battery], '%',
                                                      'unimportant')

    if options.json_output:
        with open(options.json_output, 'wb') as f:
            f.write(json.dumps(json_data, indent=4))

    num_failed_devs = 0
    for device_ok, device in zip(devices_ok, devices):
        if not device_ok:
            logging.warning('Blacklisting %s', str(device))
            device_blacklist.ExtendBlacklist([str(device)])
            num_failed_devs += 1

    if num_failed_devs == len(devices):
        return 2

    if not devices:
        return 1
예제 #18
0
 def _FindDeviceWithTimeout(self):
   """Find which device to use with timeout."""
   timeout_retry.WaitFor(self._FindDevice, wait_period=1)