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""" 7Unit tests for the contents of battery_utils.py 8""" 9 10# pylint: disable=protected-access,unused-argument 11 12import logging 13import unittest 14 15from devil import devil_env 16from devil.android import battery_utils 17from devil.android import device_errors 18from devil.android import device_utils 19from devil.android import device_utils_test 20from devil.utils import mock_calls 21 22with 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 34class 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 90class 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 105class 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 139class 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 186class 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 249class 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 291class 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 347class 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 376class 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 404class 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 455class 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 493class 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 512class 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 527class 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 581class 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 616class 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 631class 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 695if __name__ == '__main__': 696 logging.getLogger().setLevel(logging.DEBUG) 697 unittest.main(verbosity=2) 698