Home | History | Annotate | Download | only in power_monitor
      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
      3 # found in the LICENSE file.
      4 
      5 import csv
      6 import logging
      7 
      8 from telemetry.internal.platform.power_monitor import android_power_monitor_base
      9 
     10 class DumpsysPowerMonitor(android_power_monitor_base.AndroidPowerMonitorBase):
     11   """PowerMonitor that relies on the dumpsys batterystats to monitor the power
     12   consumption of a single android application. This measure uses a heuristic
     13   and is the same information end-users see with the battery application.
     14   Available on Android L and higher releases.
     15   """
     16   def __init__(self, battery, platform_backend):
     17     """Constructor.
     18 
     19     Args:
     20         battery: A BatteryUtil instance.
     21         platform_backend: A LinuxBasedPlatformBackend instance.
     22     """
     23     super(DumpsysPowerMonitor, self).__init__()
     24     self._battery = battery
     25     self._browser = None
     26     self._platform = platform_backend
     27 
     28   def CanMonitorPower(self):
     29     result = self._platform.device.RunShellCommand(
     30         ['dumpsys', 'batterystats', '-c'], check_return=True)
     31     DUMP_VERSION_INDEX = 0
     32     # Dumpsys power data is present in dumpsys versions 8 and 9
     33     # which is found on L+ devices.
     34     return (csv.reader(result).next()[DUMP_VERSION_INDEX] in ['8', '9'])
     35 
     36   def StartMonitoringPower(self, browser):
     37     self._CheckStart()
     38     assert browser
     39     self._browser = browser
     40     # Disable the charging of the device over USB. This is necessary because the
     41     # device only collects information about power usage when the device is not
     42     # charging.
     43 
     44   def StopMonitoringPower(self):
     45     self._CheckStop()
     46     assert self._browser
     47     package = self._browser._browser_backend.package
     48     self._browser = None
     49 
     50     voltage = self._ParseVoltage(self._battery.GetBatteryInfo().get('voltage'))
     51     power_data = self._battery.GetPowerData()
     52     power_results = self.ProcessPowerData(power_data, voltage, package)
     53     self._LogPowerAnomalies(power_results, package)
     54     return power_results
     55 
     56   @staticmethod
     57   def ProcessPowerData(power_data, voltage, package):
     58     package_power_data = power_data['per_package'].get(package)
     59     if not package_power_data:
     60       logging.warning('No power data for %s in dumpsys output.' % package)
     61       package_power = 0
     62     else:
     63       package_power = sum(package_power_data['data'])
     64 
     65     return {'identifier': 'dumpsys',
     66             'power_samples_mw': [],
     67             'energy_consumption_mwh': power_data['system_total'] * voltage,
     68             'application_energy_consumption_mwh': package_power * voltage}
     69