1# Copyright 2019 The Chromium OS 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. 4import logging 5 6from autotest_lib.client.bin import test 7from autotest_lib.client.common_lib import error 8from autotest_lib.client.common_lib.cros import chrome 9from autotest_lib.client.common_lib import utils 10from autotest_lib.client.cros.power import power_status 11from autotest_lib.client.cros.power import power_utils 12 13class power_BatteryDrain(test.test): 14 """Not a test, but a utility for server tests to drain the battery below 15 a certain threshold within a certain timeframe.""" 16 version = 1 17 18 backlight = None 19 keyboard_backlight = None 20 21 url = 'https://crospower.page.link/power_BatteryDrain' 22 23 def cleanup(self): 24 '''Cleanup for a test run''' 25 if self._force_discharge: 26 if not power_utils.charge_control_by_ectool(True): 27 logging.warn('Can not restore from force discharge.') 28 if self.backlight: 29 self.backlight.restore() 30 if self.keyboard_backlight: 31 default_level = self.keyboard_backlight.get_default_level() 32 self.keyboard_backlight.set_level(default_level) 33 34 def run_once(self, drain_to_percent, drain_timeout, force_discharge=False): 35 ''' 36 Entry point of this test. The DUT must not be connected to AC. 37 38 It turns the screen and keyboard backlight up as high as possible, and 39 then opens Chrome to a WebGL heavy webpage. I also tried using a 40 dedicated tool for stress-testing the CPU 41 (https://github.com/intel/psst), but that only drew 27 watts on my DUT, 42 compared with 35 watts using the WebGL website. If you find a better 43 way to use a lot of power, please modify this test! 44 45 @param drain_to_percent: Battery percentage to drain to. 46 @param drain_timeout: In seconds. 47 @param force_discharge: Force discharge even with AC plugged in. 48 ''' 49 status = power_status.get_status() 50 if not status.battery: 51 raise error.TestNAError('DUT has no battery. Test Skipped') 52 53 self._force_discharge = force_discharge 54 if force_discharge: 55 if not power_utils.charge_control_by_ectool(False): 56 raise error.TestError('Could not run battery force discharge.') 57 58 ac_error = error.TestFail('DUT is on AC power, but should not be') 59 if not force_discharge and status.on_ac(): 60 raise ac_error 61 62 self.backlight = power_utils.Backlight() 63 self.backlight.set_percent(100) 64 try: 65 self.keyboard_backlight = power_utils.KbdBacklight() 66 self.keyboard_backlight.set_percent(100) 67 except power_utils.KbdBacklightException as e: 68 logging.info("Assuming no keyboard backlight due to %s", str(e)) 69 self.keyboard_backlight = None 70 71 with chrome.Chrome(init_network_controller=True) as cr: 72 tab = cr.browser.tabs.New() 73 tab.Navigate(self.url) 74 75 logging.info( 76 'Waiting {} seconds for battery to drain to {} percent'.format( 77 drain_timeout, drain_to_percent)) 78 79 def is_battery_low_enough(): 80 """Check if battery level reach target.""" 81 status.refresh() 82 if not force_discharge and status.on_ac(): 83 raise ac_error 84 return status.percent_display_charge() <= drain_to_percent 85 86 err = error.TestFail( 87 "Battery did not drain to {} percent in {} seconds".format( 88 drain_to_percent, drain_timeout)) 89 utils.poll_for_condition(is_battery_low_enough, 90 exception=err, 91 timeout=drain_timeout, 92 sleep_interval=1) 93