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 1421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1432 | 1432 |
1433 Parameters passed to this function are passed directly to | 1433 Parameters passed to this function are passed directly to |
1434 |logcat_monitor.LogcatMonitor| and are documented there. | 1434 |logcat_monitor.LogcatMonitor| and are documented there. |
1435 | 1435 |
1436 Args: | 1436 Args: |
1437 timeout: timeout in seconds | 1437 timeout: timeout in seconds |
1438 retries: number of retries | 1438 retries: number of retries |
1439 """ | 1439 """ |
1440 return logcat_monitor.LogcatMonitor(self.adb, *args, **kwargs) | 1440 return logcat_monitor.LogcatMonitor(self.adb, *args, **kwargs) |
1441 | 1441 |
1442 # TODO(rnephew): Remove when battery_utils is switched to. | |
1443 @decorators.WithTimeoutAndRetriesFromInstance() | |
1444 def GetBatteryInfo(self, timeout=None, retries=None): | |
1445 """Gets battery info for the device. | |
1446 | |
1447 Args: | |
1448 timeout: timeout in seconds | |
1449 retries: number of retries | |
1450 Returns: | |
1451 A dict containing various battery information as reported by dumpsys | |
1452 battery. | |
1453 """ | |
1454 result = {} | |
1455 # Skip the first line, which is just a header. | |
1456 for line in self.RunShellCommand( | |
1457 ['dumpsys', 'battery'], check_return=True)[1:]: | |
1458 # If usb charging has been disabled, an extra line of header exists. | |
1459 if 'UPDATES STOPPED' in line: | |
1460 logging.warning('Dumpsys battery not receiving updates. ' | |
1461 'Run dumpsys battery reset if this is in error.') | |
1462 elif ':' not in line: | |
1463 logging.warning('Unknown line found in dumpsys battery.') | |
1464 logging.warning(line) | |
1465 else: | |
1466 k, v = line.split(': ', 1) | |
1467 result[k.strip()] = v.strip() | |
1468 return result | |
1469 | |
1470 # TODO(rnephew): Remove when battery_utils is switched to. | |
1471 @decorators.WithTimeoutAndRetriesFromInstance() | |
1472 def GetCharging(self, timeout=None, retries=None): | |
1473 """Gets the charging state of the device. | |
1474 | |
1475 Args: | |
1476 timeout: timeout in seconds | |
1477 retries: number of retries | |
1478 Returns: | |
1479 True if the device is charging, false otherwise. | |
1480 """ | |
1481 battery_info = self.GetBatteryInfo() | |
1482 for k in ('AC powered', 'USB powered', 'Wireless powered'): | |
1483 if (k in battery_info and | |
1484 battery_info[k].lower() in ('true', '1', 'yes')): | |
1485 return True | |
1486 return False | |
1487 | |
1488 # TODO(rnephew): Remove when battery_utils is switched to. | |
1489 @decorators.WithTimeoutAndRetriesFromInstance() | |
1490 def SetCharging(self, enabled, timeout=None, retries=None): | |
1491 """Enables or disables charging on the device. | |
1492 | |
1493 Args: | |
1494 enabled: A boolean indicating whether charging should be enabled or | |
1495 disabled. | |
1496 timeout: timeout in seconds | |
1497 retries: number of retries | |
1498 """ | |
1499 if 'charging_config' not in self._cache: | |
1500 for c in _CONTROL_CHARGING_COMMANDS: | |
1501 if self.FileExists(c['witness_file']): | |
1502 self._cache['charging_config'] = c | |
1503 break | |
1504 else: | |
1505 raise device_errors.CommandFailedError( | |
1506 'Unable to find charging commands.') | |
1507 | |
1508 if enabled: | |
1509 command = self._cache['charging_config']['enable_command'] | |
1510 else: | |
1511 command = self._cache['charging_config']['disable_command'] | |
1512 | |
1513 def set_and_verify_charging(): | |
1514 self.RunShellCommand(command, check_return=True) | |
1515 return self.GetCharging() == enabled | |
1516 | |
1517 timeout_retry.WaitFor(set_and_verify_charging, wait_period=1) | |
1518 | |
1519 # TODO(rnephew): Remove when battery_utils is switched to. | |
1520 @decorators.WithTimeoutAndRetriesFromInstance() | |
1521 def DisableBatteryUpdates(self, timeout=None, retries=None): | |
1522 """ Resets battery data and makes device appear like it is not | |
1523 charging so that it will collect power data since last charge. | |
1524 | |
1525 Args: | |
1526 timeout: timeout in seconds | |
1527 retries: number of retries | |
1528 """ | |
1529 def battery_updates_disabled(): | |
1530 return self.GetCharging() is False | |
1531 | |
1532 self.RunShellCommand( | |
1533 ['dumpsys', 'batterystats', '--reset'], check_return=True) | |
1534 battery_data = self.RunShellCommand( | |
1535 ['dumpsys', 'batterystats', '--charged', '--checkin'], | |
1536 check_return=True) | |
1537 ROW_TYPE_INDEX = 3 | |
1538 PWI_POWER_INDEX = 5 | |
1539 for line in battery_data: | |
1540 l = line.split(',') | |
1541 if (len(l) > PWI_POWER_INDEX and l[ROW_TYPE_INDEX] == 'pwi' | |
1542 and l[PWI_POWER_INDEX] != 0): | |
1543 raise device_errors.CommandFailedError( | |
1544 'Non-zero pmi value found after reset.') | |
1545 self.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '0'], | |
1546 check_return=True) | |
1547 timeout_retry.WaitFor(battery_updates_disabled, wait_period=1) | |
1548 | |
1549 # TODO(rnephew): Remove when battery_utils is switched to. | |
1550 @decorators.WithTimeoutAndRetriesFromInstance() | |
1551 def EnableBatteryUpdates(self, timeout=None, retries=None): | |
1552 """ Restarts device charging so that dumpsys no longer collects power data. | |
1553 | |
1554 Args: | |
1555 timeout: timeout in seconds | |
1556 retries: number of retries | |
1557 """ | |
1558 def battery_updates_enabled(): | |
1559 return self.GetCharging() is True | |
1560 | |
1561 self.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '1'], | |
1562 check_return=True) | |
1563 self.RunShellCommand(['dumpsys', 'battery', 'reset'], check_return=True) | |
1564 timeout_retry.WaitFor(battery_updates_enabled, wait_period=1) | |
1565 | |
1566 # TODO(rnephew): Remove when battery_utils is switched to. | |
1567 @contextlib.contextmanager | |
1568 def BatteryMeasurement(self, timeout=None, retries=None): | |
1569 """Context manager that enables battery data collection. It makes | |
1570 the device appear to stop charging so that dumpsys will start collecting | |
1571 power data since last charge. Once the with block is exited, charging is | |
1572 resumed and power data since last charge is no longer collected. | |
1573 | |
1574 Only for devices L and higher. | |
1575 | |
1576 Example usage: | |
1577 with BatteryMeasurement(): | |
1578 browser_actions() | |
1579 get_power_data() # report usage within this block | |
1580 after_measurements() # Anything that runs after power | |
1581 # measurements are collected | |
1582 | |
1583 Args: | |
1584 timeout: timeout in seconds | |
1585 retries: number of retries | |
1586 """ | |
1587 if self.build_version_sdk < constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP: | |
1588 raise device_errors.CommandFailedError('Device must be L or higher.') | |
1589 try: | |
1590 self.DisableBatteryUpdates(timeout=timeout, retries=retries) | |
1591 yield | |
1592 finally: | |
1593 self.EnableBatteryUpdates(timeout=timeout, retries=retries) | |
1594 | |
1595 @decorators.WithTimeoutAndRetriesFromInstance() | 1442 @decorators.WithTimeoutAndRetriesFromInstance() |
1596 def GetDevicePieWrapper(self, timeout=None, retries=None): | 1443 def GetDevicePieWrapper(self, timeout=None, retries=None): |
1597 """Gets the absolute path to the run_pie wrapper on the device. | 1444 """Gets the absolute path to the run_pie wrapper on the device. |
1598 | 1445 |
1599 We have to build our device executables to be PIE, but they need to be able | 1446 We have to build our device executables to be PIE, but they need to be able |
1600 to run on versions of android that don't support PIE (i.e. ICS and below). | 1447 to run on versions of android that don't support PIE (i.e. ICS and below). |
1601 To do so, we push a wrapper to the device that lets older android versions | 1448 To do so, we push a wrapper to the device that lets older android versions |
1602 run PIE executables. This method pushes that wrapper to the device if | 1449 run PIE executables. This method pushes that wrapper to the device if |
1603 necessary and returns the path to it. | 1450 necessary and returns the path to it. |
1604 | 1451 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1658 """Returns client cache.""" | 1505 """Returns client cache.""" |
1659 if client_name not in self._client_caches: | 1506 if client_name not in self._client_caches: |
1660 self._client_caches[client_name] = {} | 1507 self._client_caches[client_name] = {} |
1661 return self._client_caches[client_name] | 1508 return self._client_caches[client_name] |
1662 | 1509 |
1663 def _ClearCache(self): | 1510 def _ClearCache(self): |
1664 """Clears all caches.""" | 1511 """Clears all caches.""" |
1665 for client in self._client_caches: | 1512 for client in self._client_caches: |
1666 self._client_caches[client].clear() | 1513 self._client_caches[client].clear() |
1667 self._cache.clear() | 1514 self._cache.clear() |
OLD | NEW |