Home | History | Annotate | Download | only in android
      1 #!/usr/bin/env python
      2 # Copyright 2014 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 """
      7 Unit tests for the contents of battery_utils.py
      8 """
      9 
     10 # pylint: disable=protected-access,unused-argument
     11 
     12 import logging
     13 import unittest
     14 
     15 from devil import devil_env
     16 from devil.android import battery_utils
     17 from devil.android import device_errors
     18 from devil.android import device_utils
     19 from devil.android import device_utils_test
     20 from devil.utils import mock_calls
     21 
     22 with devil_env.SysPath(devil_env.PYMOCK_PATH):
     23   import mock  # pylint: disable=import-error
     24 
     25 _DUMPSYS_OUTPUT = [
     26     '9,0,i,uid,1000,test_package1',
     27     '9,0,i,uid,1001,test_package2',
     28     '9,1000,l,pwi,uid,1',
     29     '9,1001,l,pwi,uid,2',
     30     '9,0,l,pws,1728,2000,190,207',
     31 ]
     32 
     33 
     34 class BatteryUtilsTest(mock_calls.TestCase):
     35 
     36   _NEXUS_5 = {
     37     'name': 'Nexus 5',
     38     'witness_file': '/sys/kernel/debug/bq24192/INPUT_SRC_CONT',
     39     'enable_command': (
     40         'echo 0x4A > /sys/kernel/debug/bq24192/INPUT_SRC_CONT && '
     41         'echo 1 > /sys/class/power_supply/usb/online'),
     42     'disable_command': (
     43         'echo 0xCA > /sys/kernel/debug/bq24192/INPUT_SRC_CONT && '
     44         'chmod 644 /sys/class/power_supply/usb/online && '
     45         'echo 0 > /sys/class/power_supply/usb/online'),
     46     'charge_counter': None,
     47     'voltage': None,
     48     'current': None,
     49   }
     50 
     51   _NEXUS_6 = {
     52     'name': 'Nexus 6',
     53     'witness_file': None,
     54     'enable_command': None,
     55     'disable_command': None,
     56     'charge_counter': (
     57         '/sys/class/power_supply/max170xx_battery/charge_counter_ext'),
     58     'voltage': '/sys/class/power_supply/max170xx_battery/voltage_now',
     59     'current': '/sys/class/power_supply/max170xx_battery/current_now',
     60   }
     61 
     62   _NEXUS_10 = {
     63     'name': 'Nexus 10',
     64     'witness_file': None,
     65     'enable_command': None,
     66     'disable_command': None,
     67     'charge_counter': (
     68         '/sys/class/power_supply/ds2784-fuelgauge/charge_counter_ext'),
     69     'voltage': '/sys/class/power_supply/ds2784-fuelgauge/voltage_now',
     70     'current': '/sys/class/power_supply/ds2784-fuelgauge/current_now',
     71   }
     72 
     73   def ShellError(self, output=None, status=1):
     74     def action(cmd, *args, **kwargs):
     75       raise device_errors.AdbShellCommandFailedError(
     76           cmd, output, status, str(self.device))
     77     if output is None:
     78       output = 'Permission denied\n'
     79     return action
     80 
     81   def setUp(self):
     82     self.adb = device_utils_test._AdbWrapperMock('0123456789abcdef')
     83     self.device = device_utils.DeviceUtils(
     84         self.adb, default_timeout=10, default_retries=0)
     85     self.watchMethodCalls(self.call.adb, ignore=['GetDeviceSerial'])
     86     self.battery = battery_utils.BatteryUtils(
     87         self.device, default_timeout=10, default_retries=0)
     88 
     89 
     90 class BatteryUtilsInitTest(unittest.TestCase):
     91 
     92   def testInitWithDeviceUtil(self):
     93     serial = '0fedcba987654321'
     94     d = device_utils.DeviceUtils(serial)
     95     b = battery_utils.BatteryUtils(d)
     96     self.assertEqual(d, b._device)
     97 
     98   def testInitWithMissing_fails(self):
     99     with self.assertRaises(TypeError):
    100       battery_utils.BatteryUtils(None)
    101     with self.assertRaises(TypeError):
    102       battery_utils.BatteryUtils('')
    103 
    104 
    105 class BatteryUtilsSetChargingTest(BatteryUtilsTest):
    106 
    107   @mock.patch('time.sleep', mock.Mock())
    108   def testHardwareSetCharging_enabled(self):
    109     self.battery._cache['profile'] = self._NEXUS_5
    110     with self.assertCalls(
    111         (self.call.device.RunShellCommand(
    112             mock.ANY, shell=True, check_return=True, as_root=True,
    113             large_output=True), []),
    114         (self.call.battery.GetCharging(), False),
    115         (self.call.battery.GetCharging(), True)):
    116       self.battery._HardwareSetCharging(True)
    117 
    118   def testHardwareSetCharging_alreadyEnabled(self):
    119     self.battery._cache['profile'] = self._NEXUS_5
    120     with self.assertCalls(
    121         (self.call.device.RunShellCommand(
    122             mock.ANY, shell=True, check_return=True, as_root=True,
    123             large_output=True), []),
    124         (self.call.battery.GetCharging(), True)):
    125       self.battery._HardwareSetCharging(True)
    126 
    127   @mock.patch('time.sleep', mock.Mock())
    128   def testHardwareSetCharging_disabled(self):
    129     self.battery._cache['profile'] = self._NEXUS_5
    130     with self.assertCalls(
    131         (self.call.device.RunShellCommand(
    132             mock.ANY, shell=True, check_return=True, as_root=True,
    133             large_output=True), []),
    134         (self.call.battery.GetCharging(), True),
    135         (self.call.battery.GetCharging(), False)):
    136       self.battery._HardwareSetCharging(False)
    137 
    138 
    139 class BatteryUtilsSetBatteryMeasurementTest(BatteryUtilsTest):
    140 
    141   @mock.patch('time.sleep', mock.Mock())
    142   def testBatteryMeasurementWifi(self):
    143     with self.patch_call(self.call.device.build_version_sdk,
    144                          return_value=22):
    145       with self.assertCalls(
    146           (self.call.battery._ClearPowerData(), True),
    147           (self.call.device.RunShellCommand(
    148               ['dumpsys', 'battery', 'set', 'ac', '0'], check_return=True), []),
    149           (self.call.device.RunShellCommand(
    150               ['dumpsys', 'battery', 'set', 'usb', '0'], check_return=True),
    151            []),
    152           (self.call.battery.GetCharging(), False),
    153           (self.call.device.RunShellCommand(
    154               ['dumpsys', 'battery', 'reset'], check_return=True), []),
    155           (self.call.battery.GetCharging(), False),
    156           (self.call.device.RunShellCommand(
    157               ['dumpsys', 'battery'], check_return=True), ['UPDATES STOPPED']),
    158           (self.call.battery.GetCharging(), False),
    159           (self.call.device.RunShellCommand(
    160               ['dumpsys', 'battery'], check_return=True), [])):
    161         with self.battery.BatteryMeasurement():
    162           pass
    163 
    164   @mock.patch('time.sleep', mock.Mock())
    165   def testBatteryMeasurementUsb(self):
    166     with self.patch_call(self.call.device.build_version_sdk,
    167                          return_value=22):
    168       with self.assertCalls(
    169           (self.call.battery._ClearPowerData(), True),
    170           (self.call.device.RunShellCommand(
    171               ['dumpsys', 'battery', 'set', 'ac', '0'], check_return=True), []),
    172           (self.call.device.RunShellCommand(
    173               ['dumpsys', 'battery', 'set', 'usb', '0'], check_return=True),
    174            []),
    175           (self.call.battery.GetCharging(), False),
    176           (self.call.device.RunShellCommand(
    177               ['dumpsys', 'battery', 'reset'], check_return=True), []),
    178           (self.call.battery.GetCharging(), False),
    179           (self.call.device.RunShellCommand(
    180               ['dumpsys', 'battery'], check_return=True), ['UPDATES STOPPED']),
    181           (self.call.battery.GetCharging(), True)):
    182         with self.battery.BatteryMeasurement():
    183           pass
    184 
    185 
    186 class BatteryUtilsGetPowerData(BatteryUtilsTest):
    187 
    188   def testGetPowerData(self):
    189     with self.assertCalls(
    190         (self.call.device.RunShellCommand(
    191             ['dumpsys', 'batterystats', '-c'],
    192             check_return=True, large_output=True),
    193          _DUMPSYS_OUTPUT)):
    194       data = self.battery.GetPowerData()
    195       check = {
    196         'system_total': 2000.0,
    197         'per_package': {
    198           'test_package1': {'uid': '1000', 'data': [1.0]},
    199           'test_package2': {'uid': '1001', 'data': [2.0]}
    200         }
    201       }
    202       self.assertEqual(data, check)
    203 
    204   def testGetPowerData_packageCollisionSame(self):
    205     self.battery._cache['uids'] = {'test_package1': '1000'}
    206     with self.assertCall(
    207         self.call.device.RunShellCommand(
    208             ['dumpsys', 'batterystats', '-c'],
    209             check_return=True, large_output=True),
    210         _DUMPSYS_OUTPUT):
    211       data = self.battery.GetPowerData()
    212       check = {
    213         'system_total': 2000.0,
    214         'per_package': {
    215           'test_package1': {'uid': '1000', 'data': [1.0]},
    216           'test_package2': {'uid': '1001', 'data': [2.0]}
    217         }
    218       }
    219       self.assertEqual(data, check)
    220 
    221   def testGetPowerData_packageCollisionDifferent(self):
    222     self.battery._cache['uids'] = {'test_package1': '1'}
    223     with self.assertCall(
    224         self.call.device.RunShellCommand(
    225             ['dumpsys', 'batterystats', '-c'],
    226             check_return=True, large_output=True),
    227         _DUMPSYS_OUTPUT):
    228       with self.assertRaises(device_errors.CommandFailedError):
    229         self.battery.GetPowerData()
    230 
    231   def testGetPowerData_cacheCleared(self):
    232     with self.assertCalls(
    233         (self.call.device.RunShellCommand(
    234             ['dumpsys', 'batterystats', '-c'],
    235             check_return=True, large_output=True),
    236          _DUMPSYS_OUTPUT)):
    237       self.battery._cache.clear()
    238       data = self.battery.GetPowerData()
    239       check = {
    240         'system_total': 2000.0,
    241         'per_package': {
    242           'test_package1': {'uid': '1000', 'data': [1.0]},
    243           'test_package2': {'uid': '1001', 'data': [2.0]}
    244         }
    245       }
    246       self.assertEqual(data, check)
    247 
    248 
    249 class BatteryUtilsChargeDevice(BatteryUtilsTest):
    250 
    251   @mock.patch('time.sleep', mock.Mock())
    252   def testChargeDeviceToLevel_pass(self):
    253     with self.assertCalls(
    254         (self.call.battery.SetCharging(True)),
    255         (self.call.battery.GetBatteryInfo(), {'level': '50'}),
    256         (self.call.battery.GetBatteryInfo(), {'level': '100'})):
    257       self.battery.ChargeDeviceToLevel(95)
    258 
    259   @mock.patch('time.sleep', mock.Mock())
    260   def testChargeDeviceToLevel_failureSame(self):
    261     with self.assertCalls(
    262         (self.call.battery.SetCharging(True)),
    263         (self.call.battery.GetBatteryInfo(), {'level': '50'}),
    264         (self.call.battery.GetBatteryInfo(), {'level': '50'}),
    265 
    266         (self.call.battery.GetBatteryInfo(), {'level': '50'})):
    267       with self.assertRaises(device_errors.DeviceChargingError):
    268         old_max = battery_utils._MAX_CHARGE_ERROR
    269         try:
    270           battery_utils._MAX_CHARGE_ERROR = 2
    271           self.battery.ChargeDeviceToLevel(95)
    272         finally:
    273           battery_utils._MAX_CHARGE_ERROR = old_max
    274 
    275   @mock.patch('time.sleep', mock.Mock())
    276   def testChargeDeviceToLevel_failureDischarge(self):
    277     with self.assertCalls(
    278         (self.call.battery.SetCharging(True)),
    279         (self.call.battery.GetBatteryInfo(), {'level': '50'}),
    280         (self.call.battery.GetBatteryInfo(), {'level': '49'}),
    281         (self.call.battery.GetBatteryInfo(), {'level': '48'})):
    282       with self.assertRaises(device_errors.DeviceChargingError):
    283         old_max = battery_utils._MAX_CHARGE_ERROR
    284         try:
    285           battery_utils._MAX_CHARGE_ERROR = 2
    286           self.battery.ChargeDeviceToLevel(95)
    287         finally:
    288           battery_utils._MAX_CHARGE_ERROR = old_max
    289 
    290 
    291 class BatteryUtilsDischargeDevice(BatteryUtilsTest):
    292 
    293   @mock.patch('time.sleep', mock.Mock())
    294   def testDischargeDevice_exact(self):
    295     with self.assertCalls(
    296         (self.call.battery.GetBatteryInfo(), {'level': '100'}),
    297         (self.call.battery._HardwareSetCharging(False)),
    298         (self.call.battery._HardwareSetCharging(True)),
    299         (self.call.battery.GetBatteryInfo(), {'level': '99'})):
    300       self.battery._DischargeDevice(1)
    301 
    302   @mock.patch('time.sleep', mock.Mock())
    303   def testDischargeDevice_over(self):
    304     with self.assertCalls(
    305         (self.call.battery.GetBatteryInfo(), {'level': '100'}),
    306         (self.call.battery._HardwareSetCharging(False)),
    307         (self.call.battery._HardwareSetCharging(True)),
    308         (self.call.battery.GetBatteryInfo(), {'level': '50'})):
    309       self.battery._DischargeDevice(1)
    310 
    311   @mock.patch('time.sleep', mock.Mock())
    312   def testDischargeDevice_takeslong(self):
    313     with self.assertCalls(
    314         (self.call.battery.GetBatteryInfo(), {'level': '100'}),
    315         (self.call.battery._HardwareSetCharging(False)),
    316         (self.call.battery._HardwareSetCharging(True)),
    317         (self.call.battery.GetBatteryInfo(), {'level': '100'}),
    318         (self.call.battery._HardwareSetCharging(False)),
    319         (self.call.battery._HardwareSetCharging(True)),
    320         (self.call.battery.GetBatteryInfo(), {'level': '99'}),
    321         (self.call.battery._HardwareSetCharging(False)),
    322         (self.call.battery._HardwareSetCharging(True)),
    323         (self.call.battery.GetBatteryInfo(), {'level': '98'}),
    324         (self.call.battery._HardwareSetCharging(False)),
    325         (self.call.battery._HardwareSetCharging(True)),
    326         (self.call.battery.GetBatteryInfo(), {'level': '97'})):
    327       self.battery._DischargeDevice(3)
    328 
    329   @mock.patch('time.sleep', mock.Mock())
    330   def testDischargeDevice_dischargeTooClose(self):
    331     with self.assertCalls(
    332         (self.call.battery.GetBatteryInfo(), {'level': '100'})):
    333       self.battery._DischargeDevice(99)
    334 
    335   @mock.patch('time.sleep', mock.Mock())
    336   def testDischargeDevice_percentageOutOfBounds(self):
    337     with self.assertCalls(
    338         (self.call.battery.GetBatteryInfo(), {'level': '100'})):
    339       with self.assertRaises(ValueError):
    340         self.battery._DischargeDevice(100)
    341     with self.assertCalls(
    342         (self.call.battery.GetBatteryInfo(), {'level': '100'})):
    343       with self.assertRaises(ValueError):
    344         self.battery._DischargeDevice(0)
    345 
    346 
    347 class BatteryUtilsGetBatteryInfoTest(BatteryUtilsTest):
    348 
    349   def testGetBatteryInfo_normal(self):
    350     with self.assertCalls(
    351         (self.call.device.RunShellCommand(
    352             ['dumpsys', 'battery'], check_return=True),
    353         [
    354           'Current Battery Service state:',
    355           '  AC powered: false',
    356           '  USB powered: true',
    357           '  level: 100',
    358           '  temperature: 321',
    359         ])):
    360       self.assertEquals(
    361           {
    362             'AC powered': 'false',
    363             'USB powered': 'true',
    364             'level': '100',
    365             'temperature': '321',
    366           },
    367           self.battery.GetBatteryInfo())
    368 
    369   def testGetBatteryInfo_nothing(self):
    370     with self.assertCalls(
    371         (self.call.device.RunShellCommand(
    372             ['dumpsys', 'battery'], check_return=True), [])):
    373       self.assertEquals({}, self.battery.GetBatteryInfo())
    374 
    375 
    376 class BatteryUtilsGetChargingTest(BatteryUtilsTest):
    377 
    378   def testGetCharging_usb(self):
    379     with self.assertCall(
    380         self.call.battery.GetBatteryInfo(), {'USB powered': 'true'}):
    381       self.assertTrue(self.battery.GetCharging())
    382 
    383   def testGetCharging_usbFalse(self):
    384     with self.assertCall(
    385         self.call.battery.GetBatteryInfo(), {'USB powered': 'false'}):
    386       self.assertFalse(self.battery.GetCharging())
    387 
    388   def testGetCharging_ac(self):
    389     with self.assertCall(
    390         self.call.battery.GetBatteryInfo(), {'AC powered': 'true'}):
    391       self.assertTrue(self.battery.GetCharging())
    392 
    393   def testGetCharging_wireless(self):
    394     with self.assertCall(
    395         self.call.battery.GetBatteryInfo(), {'Wireless powered': 'true'}):
    396       self.assertTrue(self.battery.GetCharging())
    397 
    398   def testGetCharging_unknown(self):
    399     with self.assertCall(
    400         self.call.battery.GetBatteryInfo(), {'level': '42'}):
    401       self.assertFalse(self.battery.GetCharging())
    402 
    403 
    404 class BatteryUtilsGetNetworkDataTest(BatteryUtilsTest):
    405 
    406   def testGetNetworkData_noDataUsage(self):
    407     with self.assertCalls(
    408         (self.call.device.RunShellCommand(
    409             ['dumpsys', 'batterystats', '-c'],
    410             check_return=True, large_output=True),
    411          _DUMPSYS_OUTPUT),
    412         (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'),
    413             self.ShellError()),
    414         (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'),
    415             self.ShellError())):
    416       self.assertEquals(self.battery.GetNetworkData('test_package1'), (0, 0))
    417 
    418   def testGetNetworkData_badPackage(self):
    419     with self.assertCall(
    420         self.call.device.RunShellCommand(
    421             ['dumpsys', 'batterystats', '-c'],
    422             check_return=True, large_output=True),
    423         _DUMPSYS_OUTPUT):
    424       self.assertEqual(self.battery.GetNetworkData('asdf'), None)
    425 
    426   def testGetNetworkData_packageNotCached(self):
    427     with self.assertCalls(
    428         (self.call.device.RunShellCommand(
    429             ['dumpsys', 'batterystats', '-c'],
    430             check_return=True, large_output=True),
    431          _DUMPSYS_OUTPUT),
    432         (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'), 1),
    433         (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'), 2)):
    434       self.assertEqual(self.battery.GetNetworkData('test_package1'), (1, 2))
    435 
    436   def testGetNetworkData_packageCached(self):
    437     self.battery._cache['uids'] = {'test_package1': '1000'}
    438     with self.assertCalls(
    439         (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'), 1),
    440         (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'), 2)):
    441       self.assertEqual(self.battery.GetNetworkData('test_package1'), (1, 2))
    442 
    443   def testGetNetworkData_clearedCache(self):
    444     with self.assertCalls(
    445         (self.call.device.RunShellCommand(
    446             ['dumpsys', 'batterystats', '-c'],
    447             check_return=True, large_output=True),
    448          _DUMPSYS_OUTPUT),
    449         (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_snd'), 1),
    450         (self.call.device.ReadFile('/proc/uid_stat/1000/tcp_rcv'), 2)):
    451       self.battery._cache.clear()
    452       self.assertEqual(self.battery.GetNetworkData('test_package1'), (1, 2))
    453 
    454 
    455 class BatteryUtilsLetBatteryCoolToTemperatureTest(BatteryUtilsTest):
    456 
    457   @mock.patch('time.sleep', mock.Mock())
    458   def testLetBatteryCoolToTemperature_startUnder(self):
    459     self.battery._cache['profile'] = self._NEXUS_6
    460     with self.assertCalls(
    461         (self.call.battery.EnableBatteryUpdates(), []),
    462         (self.call.battery.GetBatteryInfo(), {'temperature': '500'})):
    463       self.battery.LetBatteryCoolToTemperature(600)
    464 
    465   @mock.patch('time.sleep', mock.Mock())
    466   def testLetBatteryCoolToTemperature_startOver(self):
    467     self.battery._cache['profile'] = self._NEXUS_6
    468     with self.assertCalls(
    469         (self.call.battery.EnableBatteryUpdates(), []),
    470         (self.call.battery.GetBatteryInfo(), {'temperature': '500'}),
    471         (self.call.battery.GetBatteryInfo(), {'temperature': '400'})):
    472       self.battery.LetBatteryCoolToTemperature(400)
    473 
    474   @mock.patch('time.sleep', mock.Mock())
    475   def testLetBatteryCoolToTemperature_nexus5Hot(self):
    476     self.battery._cache['profile'] = self._NEXUS_5
    477     with self.assertCalls(
    478         (self.call.battery.EnableBatteryUpdates(), []),
    479         (self.call.battery.GetBatteryInfo(), {'temperature': '500'}),
    480         (self.call.battery._DischargeDevice(1), []),
    481         (self.call.battery.GetBatteryInfo(), {'temperature': '400'})):
    482       self.battery.LetBatteryCoolToTemperature(400)
    483 
    484   @mock.patch('time.sleep', mock.Mock())
    485   def testLetBatteryCoolToTemperature_nexus5Cool(self):
    486     self.battery._cache['profile'] = self._NEXUS_5
    487     with self.assertCalls(
    488         (self.call.battery.EnableBatteryUpdates(), []),
    489         (self.call.battery.GetBatteryInfo(), {'temperature': '400'})):
    490       self.battery.LetBatteryCoolToTemperature(400)
    491 
    492 
    493 class BatteryUtilsSupportsFuelGaugeTest(BatteryUtilsTest):
    494 
    495   def testSupportsFuelGauge_false(self):
    496     self.battery._cache['profile'] = self._NEXUS_5
    497     self.assertFalse(self.battery.SupportsFuelGauge())
    498 
    499   def testSupportsFuelGauge_trueMax(self):
    500     self.battery._cache['profile'] = self._NEXUS_6
    501     # TODO(rnephew): Change this to assertTrue when we have support for
    502     # disabling hardware charging on nexus 6.
    503     self.assertFalse(self.battery.SupportsFuelGauge())
    504 
    505   def testSupportsFuelGauge_trueDS(self):
    506     self.battery._cache['profile'] = self._NEXUS_10
    507     # TODO(rnephew): Change this to assertTrue when we have support for
    508     # disabling hardware charging on nexus 10.
    509     self.assertFalse(self.battery.SupportsFuelGauge())
    510 
    511 
    512 class BatteryUtilsGetFuelGaugeChargeCounterTest(BatteryUtilsTest):
    513 
    514   def testGetFuelGaugeChargeCounter_noFuelGauge(self):
    515     self.battery._cache['profile'] = self._NEXUS_5
    516     with self.assertRaises(device_errors.CommandFailedError):
    517       self.battery.GetFuelGaugeChargeCounter()
    518 
    519   def testGetFuelGaugeChargeCounter_fuelGaugePresent(self):
    520     self.battery._cache['profile'] = self._NEXUS_6
    521     with self.assertCalls(
    522         (self.call.battery.SupportsFuelGauge(), True),
    523         (self.call.device.ReadFile(mock.ANY), '123')):
    524       self.assertEqual(self.battery.GetFuelGaugeChargeCounter(), 123)
    525 
    526 
    527 class BatteryUtilsSetCharging(BatteryUtilsTest):
    528 
    529   @mock.patch('time.sleep', mock.Mock())
    530   def testSetCharging_softwareSetTrue(self):
    531     self.battery._cache['profile'] = self._NEXUS_6
    532     with self.assertCalls(
    533         (self.call.battery.GetCharging(), False),
    534         (self.call.device.RunShellCommand(
    535             ['dumpsys', 'battery', 'reset'], check_return=True), []),
    536         (self.call.battery.GetCharging(), False),
    537         (self.call.device.RunShellCommand(
    538             ['dumpsys', 'battery'], check_return=True), ['UPDATES STOPPED']),
    539         (self.call.battery.GetCharging(), True)):
    540       self.battery.SetCharging(True)
    541 
    542   @mock.patch('time.sleep', mock.Mock())
    543   def testSetCharging_softwareSetFalse(self):
    544     self.battery._cache['profile'] = self._NEXUS_6
    545     with self.assertCalls(
    546         (self.call.battery.GetCharging(), True),
    547         (self.call.battery._ClearPowerData(), True),
    548         (self.call.device.RunShellCommand(
    549             ['dumpsys', 'battery', 'set', 'ac', '0'], check_return=True), []),
    550         (self.call.device.RunShellCommand(
    551             ['dumpsys', 'battery', 'set', 'usb', '0'], check_return=True), []),
    552         (self.call.battery.GetCharging(), False)):
    553       self.battery.SetCharging(False)
    554 
    555   @mock.patch('time.sleep', mock.Mock())
    556   def testSetCharging_hardwareSetTrue(self):
    557     self.battery._cache['profile'] = self._NEXUS_5
    558     with self.assertCalls(
    559         (self.call.battery.GetCharging(), False),
    560         (self.call.battery._HardwareSetCharging(True))):
    561       self.battery.SetCharging(True)
    562 
    563   @mock.patch('time.sleep', mock.Mock())
    564   def testSetCharging_hardwareSetFalse(self):
    565     self.battery._cache['profile'] = self._NEXUS_5
    566     with self.assertCalls(
    567         (self.call.battery.GetCharging(), True),
    568         (self.call.battery._ClearPowerData(), True),
    569         (self.call.battery._HardwareSetCharging(False))):
    570       self.battery.SetCharging(False)
    571 
    572   def testSetCharging_expectedStateAlreadyTrue(self):
    573     with self.assertCalls((self.call.battery.GetCharging(), True)):
    574       self.battery.SetCharging(True)
    575 
    576   def testSetCharging_expectedStateAlreadyFalse(self):
    577     with self.assertCalls((self.call.battery.GetCharging(), False)):
    578       self.battery.SetCharging(False)
    579 
    580 
    581 class BatteryUtilsPowerMeasurement(BatteryUtilsTest):
    582 
    583   def testPowerMeasurement_hardware(self):
    584     self.battery._cache['profile'] = self._NEXUS_5
    585     with self.assertCalls(
    586         (self.call.battery.GetCharging(), True),
    587         (self.call.battery._ClearPowerData(), True),
    588         (self.call.battery._HardwareSetCharging(False)),
    589         (self.call.battery.GetCharging(), False),
    590         (self.call.battery._HardwareSetCharging(True))):
    591       with self.battery.PowerMeasurement():
    592         pass
    593 
    594   @mock.patch('time.sleep', mock.Mock())
    595   def testPowerMeasurement_software(self):
    596     self.battery._cache['profile'] = self._NEXUS_6
    597     with self.assertCalls(
    598         (self.call.battery.GetCharging(), True),
    599         (self.call.battery._ClearPowerData(), True),
    600         (self.call.device.RunShellCommand(
    601             ['dumpsys', 'battery', 'set', 'ac', '0'], check_return=True), []),
    602         (self.call.device.RunShellCommand(
    603             ['dumpsys', 'battery', 'set', 'usb', '0'], check_return=True), []),
    604         (self.call.battery.GetCharging(), False),
    605         (self.call.battery.GetCharging(), False),
    606         (self.call.device.RunShellCommand(
    607             ['dumpsys', 'battery', 'reset'], check_return=True), []),
    608         (self.call.battery.GetCharging(), False),
    609         (self.call.device.RunShellCommand(
    610             ['dumpsys', 'battery'], check_return=True), ['UPDATES STOPPED']),
    611         (self.call.battery.GetCharging(), True)):
    612       with self.battery.PowerMeasurement():
    613         pass
    614 
    615 
    616 class BatteryUtilsDiscoverDeviceProfile(BatteryUtilsTest):
    617 
    618   def testDiscoverDeviceProfile_known(self):
    619     with self.patch_call(self.call.device.product_model,
    620                          return_value='Nexus 4'):
    621       self.battery._DiscoverDeviceProfile()
    622       self.assertListEqual(self.battery._cache['profile']['name'], ["Nexus 4"])
    623 
    624   def testDiscoverDeviceProfile_unknown(self):
    625     with self.patch_call(self.call.device.product_model,
    626                          return_value='Other'):
    627       self.battery._DiscoverDeviceProfile()
    628       self.assertListEqual(self.battery._cache['profile']['name'], [])
    629 
    630 
    631 class BatteryUtilsClearPowerData(BatteryUtilsTest):
    632 
    633   def testClearPowerData_preL(self):
    634     with self.patch_call(self.call.device.build_version_sdk,
    635                          return_value=20):
    636       self.assertFalse(self.battery._ClearPowerData())
    637 
    638   def testClearPowerData_clearedL(self):
    639     with self.patch_call(self.call.device.build_version_sdk,
    640                          return_value=22):
    641       with self.assertCalls(
    642           (self.call.device.RunShellCommand(
    643               ['dumpsys', 'battery', 'set', 'usb', '1'], check_return=True),
    644            []),
    645           (self.call.device.RunShellCommand(
    646               ['dumpsys', 'battery', 'set', 'ac', '1'], check_return=True), []),
    647           (self.call.device.RunShellCommand(
    648               ['dumpsys', 'batterystats', '--reset'], check_return=True), []),
    649           (self.call.device.RunShellCommand(
    650               ['dumpsys', 'batterystats', '--charged', '-c'],
    651               check_return=True, large_output=True), []),
    652           (self.call.device.RunShellCommand(
    653               ['dumpsys', 'battery', 'reset'], check_return=True), [])):
    654         self.assertTrue(self.battery._ClearPowerData())
    655 
    656   @mock.patch('time.sleep', mock.Mock())
    657   def testClearPowerData_notClearedL(self):
    658     with self.patch_call(self.call.device.build_version_sdk,
    659                          return_value=22):
    660       with self.assertCalls(
    661           (self.call.device.RunShellCommand(
    662               ['dumpsys', 'battery', 'set', 'usb', '1'], check_return=True),
    663            []),
    664           (self.call.device.RunShellCommand(
    665               ['dumpsys', 'battery', 'set', 'ac', '1'], check_return=True), []),
    666           (self.call.device.RunShellCommand(
    667               ['dumpsys', 'batterystats', '--reset'], check_return=True), []),
    668           (self.call.device.RunShellCommand(
    669               ['dumpsys', 'batterystats', '--charged', '-c'],
    670               check_return=True, large_output=True),
    671               ['9,1000,l,pwi,uid,0.0327']),
    672           (self.call.device.RunShellCommand(
    673               ['dumpsys', 'batterystats', '--reset'], check_return=True), []),
    674           (self.call.device.RunShellCommand(
    675               ['dumpsys', 'batterystats', '--charged', '-c'],
    676               check_return=True, large_output=True),
    677               ['9,1000,l,pwi,uid,0.0327']),
    678           (self.call.device.RunShellCommand(
    679               ['dumpsys', 'batterystats', '--reset'], check_return=True), []),
    680           (self.call.device.RunShellCommand(
    681               ['dumpsys', 'batterystats', '--charged', '-c'],
    682               check_return=True, large_output=True),
    683               ['9,1000,l,pwi,uid,0.0327']),
    684           (self.call.device.RunShellCommand(
    685               ['dumpsys', 'batterystats', '--reset'], check_return=True), []),
    686           (self.call.device.RunShellCommand(
    687               ['dumpsys', 'batterystats', '--charged', '-c'],
    688               check_return=True, large_output=True),
    689               ['9,1000,l,pwi,uid,0.0']),
    690           (self.call.device.RunShellCommand(
    691               ['dumpsys', 'battery', 'reset'], check_return=True), [])):
    692         self.battery._ClearPowerData()
    693 
    694 
    695 if __name__ == '__main__':
    696   logging.getLogger().setLevel(logging.DEBUG)
    697   unittest.main(verbosity=2)
    698