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