OLD | NEW |
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Provides a variety of device interactions based on adb. | 5 """Provides a variety of device interactions based on adb. |
6 | 6 |
7 Eventually, this will be based on adb_wrapper. | 7 Eventually, this will be based on adb_wrapper. |
8 """ | 8 """ |
9 # pylint: disable=unused-argument | 9 # pylint: disable=unused-argument |
10 | 10 |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 self.old_interface = pylib.android_commands.AndroidCommands(str(device)) | 161 self.old_interface = pylib.android_commands.AndroidCommands(str(device)) |
162 elif isinstance(device, pylib.android_commands.AndroidCommands): | 162 elif isinstance(device, pylib.android_commands.AndroidCommands): |
163 self.adb = adb_wrapper.AdbWrapper(device.GetDevice()) | 163 self.adb = adb_wrapper.AdbWrapper(device.GetDevice()) |
164 self.old_interface = device | 164 self.old_interface = device |
165 else: | 165 else: |
166 raise ValueError('Unsupported device value: %r' % device) | 166 raise ValueError('Unsupported device value: %r' % device) |
167 self._commands_installed = None | 167 self._commands_installed = None |
168 self._default_timeout = default_timeout | 168 self._default_timeout = default_timeout |
169 self._default_retries = default_retries | 169 self._default_retries = default_retries |
170 self._cache = {} | 170 self._cache = {} |
| 171 self._client_caches = {} |
171 assert hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR) | 172 assert hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR) |
172 assert hasattr(self, decorators.DEFAULT_RETRIES_ATTR) | 173 assert hasattr(self, decorators.DEFAULT_RETRIES_ATTR) |
173 | 174 |
174 def __str__(self): | 175 def __str__(self): |
175 """Returns the device serial.""" | 176 """Returns the device serial.""" |
176 return self.adb.GetDeviceSerial() | 177 return self.adb.GetDeviceSerial() |
177 | 178 |
178 @decorators.WithTimeoutAndRetriesFromInstance() | 179 @decorators.WithTimeoutAndRetriesFromInstance() |
179 def IsOnline(self, timeout=None, retries=None): | 180 def IsOnline(self, timeout=None, retries=None): |
180 """Checks whether the device is online. | 181 """Checks whether the device is online. |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 retries: number of retries | 400 retries: number of retries |
400 | 401 |
401 Raises: | 402 Raises: |
402 CommandTimeoutError on timeout. | 403 CommandTimeoutError on timeout. |
403 DeviceUnreachableError on missing device. | 404 DeviceUnreachableError on missing device. |
404 """ | 405 """ |
405 def device_offline(): | 406 def device_offline(): |
406 return not self.IsOnline() | 407 return not self.IsOnline() |
407 | 408 |
408 self.adb.Reboot() | 409 self.adb.Reboot() |
409 self._cache = {} | 410 self._ClearCache() |
410 timeout_retry.WaitFor(device_offline, wait_period=1) | 411 timeout_retry.WaitFor(device_offline, wait_period=1) |
411 if block: | 412 if block: |
412 self.WaitUntilFullyBooted(wifi=wifi) | 413 self.WaitUntilFullyBooted(wifi=wifi) |
413 | 414 |
414 INSTALL_DEFAULT_TIMEOUT = 4 * _DEFAULT_TIMEOUT | 415 INSTALL_DEFAULT_TIMEOUT = 4 * _DEFAULT_TIMEOUT |
415 INSTALL_DEFAULT_RETRIES = _DEFAULT_RETRIES | 416 INSTALL_DEFAULT_RETRIES = _DEFAULT_RETRIES |
416 | 417 |
417 @decorators.WithTimeoutAndRetriesDefaults( | 418 @decorators.WithTimeoutAndRetriesDefaults( |
418 INSTALL_DEFAULT_TIMEOUT, | 419 INSTALL_DEFAULT_TIMEOUT, |
419 INSTALL_DEFAULT_RETRIES) | 420 INSTALL_DEFAULT_RETRIES) |
(...skipping 1011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1431 | 1432 |
1432 Parameters passed to this function are passed directly to | 1433 Parameters passed to this function are passed directly to |
1433 |logcat_monitor.LogcatMonitor| and are documented there. | 1434 |logcat_monitor.LogcatMonitor| and are documented there. |
1434 | 1435 |
1435 Args: | 1436 Args: |
1436 timeout: timeout in seconds | 1437 timeout: timeout in seconds |
1437 retries: number of retries | 1438 retries: number of retries |
1438 """ | 1439 """ |
1439 return logcat_monitor.LogcatMonitor(self.adb, *args, **kwargs) | 1440 return logcat_monitor.LogcatMonitor(self.adb, *args, **kwargs) |
1440 | 1441 |
| 1442 # TODO(rnephew): Remove when battery_utils is switched to. |
1441 @decorators.WithTimeoutAndRetriesFromInstance() | 1443 @decorators.WithTimeoutAndRetriesFromInstance() |
1442 def GetBatteryInfo(self, timeout=None, retries=None): | 1444 def GetBatteryInfo(self, timeout=None, retries=None): |
1443 """Gets battery info for the device. | 1445 """Gets battery info for the device. |
1444 | 1446 |
1445 Args: | 1447 Args: |
1446 timeout: timeout in seconds | 1448 timeout: timeout in seconds |
1447 retries: number of retries | 1449 retries: number of retries |
1448 Returns: | 1450 Returns: |
1449 A dict containing various battery information as reported by dumpsys | 1451 A dict containing various battery information as reported by dumpsys |
1450 battery. | 1452 battery. |
1451 """ | 1453 """ |
1452 result = {} | 1454 result = {} |
1453 # Skip the first line, which is just a header. | 1455 # Skip the first line, which is just a header. |
1454 for line in self.RunShellCommand( | 1456 for line in self.RunShellCommand( |
1455 ['dumpsys', 'battery'], check_return=True)[1:]: | 1457 ['dumpsys', 'battery'], check_return=True)[1:]: |
1456 # If usb charging has been disabled, an extra line of header exists. | 1458 # If usb charging has been disabled, an extra line of header exists. |
1457 if 'UPDATES STOPPED' in line: | 1459 if 'UPDATES STOPPED' in line: |
1458 logging.warning('Dumpsys battery not receiving updates. ' | 1460 logging.warning('Dumpsys battery not receiving updates. ' |
1459 'Run dumpsys battery reset if this is in error.') | 1461 'Run dumpsys battery reset if this is in error.') |
1460 elif ':' not in line: | 1462 elif ':' not in line: |
1461 logging.warning('Unknown line found in dumpsys battery.') | 1463 logging.warning('Unknown line found in dumpsys battery.') |
1462 logging.warning(line) | 1464 logging.warning(line) |
1463 else: | 1465 else: |
1464 k, v = line.split(': ', 1) | 1466 k, v = line.split(': ', 1) |
1465 result[k.strip()] = v.strip() | 1467 result[k.strip()] = v.strip() |
1466 return result | 1468 return result |
1467 | 1469 |
| 1470 # TODO(rnephew): Remove when battery_utils is switched to. |
1468 @decorators.WithTimeoutAndRetriesFromInstance() | 1471 @decorators.WithTimeoutAndRetriesFromInstance() |
1469 def GetCharging(self, timeout=None, retries=None): | 1472 def GetCharging(self, timeout=None, retries=None): |
1470 """Gets the charging state of the device. | 1473 """Gets the charging state of the device. |
1471 | 1474 |
1472 Args: | 1475 Args: |
1473 timeout: timeout in seconds | 1476 timeout: timeout in seconds |
1474 retries: number of retries | 1477 retries: number of retries |
1475 Returns: | 1478 Returns: |
1476 True if the device is charging, false otherwise. | 1479 True if the device is charging, false otherwise. |
1477 """ | 1480 """ |
1478 battery_info = self.GetBatteryInfo() | 1481 battery_info = self.GetBatteryInfo() |
1479 for k in ('AC powered', 'USB powered', 'Wireless powered'): | 1482 for k in ('AC powered', 'USB powered', 'Wireless powered'): |
1480 if (k in battery_info and | 1483 if (k in battery_info and |
1481 battery_info[k].lower() in ('true', '1', 'yes')): | 1484 battery_info[k].lower() in ('true', '1', 'yes')): |
1482 return True | 1485 return True |
1483 return False | 1486 return False |
1484 | 1487 |
| 1488 # TODO(rnephew): Remove when battery_utils is switched to. |
1485 @decorators.WithTimeoutAndRetriesFromInstance() | 1489 @decorators.WithTimeoutAndRetriesFromInstance() |
1486 def SetCharging(self, enabled, timeout=None, retries=None): | 1490 def SetCharging(self, enabled, timeout=None, retries=None): |
1487 """Enables or disables charging on the device. | 1491 """Enables or disables charging on the device. |
1488 | 1492 |
1489 Args: | 1493 Args: |
1490 enabled: A boolean indicating whether charging should be enabled or | 1494 enabled: A boolean indicating whether charging should be enabled or |
1491 disabled. | 1495 disabled. |
1492 timeout: timeout in seconds | 1496 timeout: timeout in seconds |
1493 retries: number of retries | 1497 retries: number of retries |
1494 """ | 1498 """ |
(...skipping 10 matching lines...) Expand all Loading... |
1505 command = self._cache['charging_config']['enable_command'] | 1509 command = self._cache['charging_config']['enable_command'] |
1506 else: | 1510 else: |
1507 command = self._cache['charging_config']['disable_command'] | 1511 command = self._cache['charging_config']['disable_command'] |
1508 | 1512 |
1509 def set_and_verify_charging(): | 1513 def set_and_verify_charging(): |
1510 self.RunShellCommand(command, check_return=True) | 1514 self.RunShellCommand(command, check_return=True) |
1511 return self.GetCharging() == enabled | 1515 return self.GetCharging() == enabled |
1512 | 1516 |
1513 timeout_retry.WaitFor(set_and_verify_charging, wait_period=1) | 1517 timeout_retry.WaitFor(set_and_verify_charging, wait_period=1) |
1514 | 1518 |
1515 # TODO(rnephew): Make private when all use cases can use the context manager. | 1519 # TODO(rnephew): Remove when battery_utils is switched to. |
1516 @decorators.WithTimeoutAndRetriesFromInstance() | 1520 @decorators.WithTimeoutAndRetriesFromInstance() |
1517 def DisableBatteryUpdates(self, timeout=None, retries=None): | 1521 def DisableBatteryUpdates(self, timeout=None, retries=None): |
1518 """ Resets battery data and makes device appear like it is not | 1522 """ Resets battery data and makes device appear like it is not |
1519 charging so that it will collect power data since last charge. | 1523 charging so that it will collect power data since last charge. |
1520 | 1524 |
1521 Args: | 1525 Args: |
1522 timeout: timeout in seconds | 1526 timeout: timeout in seconds |
1523 retries: number of retries | 1527 retries: number of retries |
1524 """ | 1528 """ |
1525 def battery_updates_disabled(): | 1529 def battery_updates_disabled(): |
1526 return self.GetCharging() is False | 1530 return self.GetCharging() is False |
1527 | 1531 |
1528 self.RunShellCommand( | 1532 self.RunShellCommand( |
1529 ['dumpsys', 'batterystats', '--reset'], check_return=True) | 1533 ['dumpsys', 'batterystats', '--reset'], check_return=True) |
1530 battery_data = self.RunShellCommand( | 1534 battery_data = self.RunShellCommand( |
1531 ['dumpsys', 'batterystats', '--charged', '--checkin'], | 1535 ['dumpsys', 'batterystats', '--charged', '--checkin'], |
1532 check_return=True) | 1536 check_return=True) |
1533 ROW_TYPE_INDEX = 3 | 1537 ROW_TYPE_INDEX = 3 |
1534 PWI_POWER_INDEX = 5 | 1538 PWI_POWER_INDEX = 5 |
1535 for line in battery_data: | 1539 for line in battery_data: |
1536 l = line.split(',') | 1540 l = line.split(',') |
1537 if (len(l) > PWI_POWER_INDEX and l[ROW_TYPE_INDEX] == 'pwi' | 1541 if (len(l) > PWI_POWER_INDEX and l[ROW_TYPE_INDEX] == 'pwi' |
1538 and l[PWI_POWER_INDEX] != 0): | 1542 and l[PWI_POWER_INDEX] != 0): |
1539 raise device_errors.CommandFailedError( | 1543 raise device_errors.CommandFailedError( |
1540 'Non-zero pmi value found after reset.') | 1544 'Non-zero pmi value found after reset.') |
1541 self.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '0'], | 1545 self.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '0'], |
1542 check_return=True) | 1546 check_return=True) |
1543 timeout_retry.WaitFor(battery_updates_disabled, wait_period=1) | 1547 timeout_retry.WaitFor(battery_updates_disabled, wait_period=1) |
1544 | 1548 |
1545 # TODO(rnephew): Make private when all use cases can use the context manager. | 1549 # TODO(rnephew): Remove when battery_utils is switched to. |
1546 @decorators.WithTimeoutAndRetriesFromInstance() | 1550 @decorators.WithTimeoutAndRetriesFromInstance() |
1547 def EnableBatteryUpdates(self, timeout=None, retries=None): | 1551 def EnableBatteryUpdates(self, timeout=None, retries=None): |
1548 """ Restarts device charging so that dumpsys no longer collects power data. | 1552 """ Restarts device charging so that dumpsys no longer collects power data. |
1549 | 1553 |
1550 Args: | 1554 Args: |
1551 timeout: timeout in seconds | 1555 timeout: timeout in seconds |
1552 retries: number of retries | 1556 retries: number of retries |
1553 """ | 1557 """ |
1554 def battery_updates_enabled(): | 1558 def battery_updates_enabled(): |
1555 return self.GetCharging() is True | 1559 return self.GetCharging() is True |
1556 | 1560 |
1557 self.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '1'], | 1561 self.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '1'], |
1558 check_return=True) | 1562 check_return=True) |
1559 self.RunShellCommand(['dumpsys', 'battery', 'reset'], check_return=True) | 1563 self.RunShellCommand(['dumpsys', 'battery', 'reset'], check_return=True) |
1560 timeout_retry.WaitFor(battery_updates_enabled, wait_period=1) | 1564 timeout_retry.WaitFor(battery_updates_enabled, wait_period=1) |
1561 | 1565 |
| 1566 # TODO(rnephew): Remove when battery_utils is switched to. |
1562 @contextlib.contextmanager | 1567 @contextlib.contextmanager |
1563 def BatteryMeasurement(self, timeout=None, retries=None): | 1568 def BatteryMeasurement(self, timeout=None, retries=None): |
1564 """Context manager that enables battery data collection. It makes | 1569 """Context manager that enables battery data collection. It makes |
1565 the device appear to stop charging so that dumpsys will start collecting | 1570 the device appear to stop charging so that dumpsys will start collecting |
1566 power data since last charge. Once the with block is exited, charging is | 1571 power data since last charge. Once the with block is exited, charging is |
1567 resumed and power data since last charge is no longer collected. | 1572 resumed and power data since last charge is no longer collected. |
1568 | 1573 |
1569 Only for devices L and higher. | 1574 Only for devices L and higher. |
1570 | 1575 |
1571 Example usage: | 1576 Example usage: |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1641 """ | 1646 """ |
1642 if not devices: | 1647 if not devices: |
1643 devices = adb_wrapper.AdbWrapper.GetDevices() | 1648 devices = adb_wrapper.AdbWrapper.GetDevices() |
1644 if not devices: | 1649 if not devices: |
1645 raise device_errors.NoDevicesError() | 1650 raise device_errors.NoDevicesError() |
1646 devices = [d if isinstance(d, cls) else cls(d) for d in devices] | 1651 devices = [d if isinstance(d, cls) else cls(d) for d in devices] |
1647 if async: | 1652 if async: |
1648 return parallelizer.Parallelizer(devices) | 1653 return parallelizer.Parallelizer(devices) |
1649 else: | 1654 else: |
1650 return parallelizer.SyncParallelizer(devices) | 1655 return parallelizer.SyncParallelizer(devices) |
| 1656 |
| 1657 def GetClientCache(self, client_name): |
| 1658 """Returns client cache.""" |
| 1659 if client_name not in self._client_caches: |
| 1660 self._client_caches[client_name] = {} |
| 1661 return self._client_caches[client_name] |
| 1662 |
| 1663 def _ClearCache(self): |
| 1664 """Clears all caches.""" |
| 1665 for client in self._client_caches: |
| 1666 self._client_caches[client].clear() |
| 1667 self._cache.clear() |
OLD | NEW |