1# Copyright (c) 2010 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. 4 5import logging, time 6from autotest_lib.client.bin import test 7from autotest_lib.client.common_lib import error 8from autotest_lib.client.cros import service_stopper 9from autotest_lib.client.cros.power import power_status, power_utils 10 11class power_BatteryCharge(test.test): 12 """class power_BatteryCharge.""" 13 version = 1 14 15 def initialize(self): 16 if not power_utils.has_battery(): 17 raise error.TestNAError('DUT has no battery. Test Skipped') 18 19 self.status = power_status.get_status() 20 21 if not self.status.on_ac(): 22 raise error.TestNAError( 23 'This test needs to be run with the AC power online') 24 25 self._services = service_stopper.ServiceStopper( 26 service_stopper.ServiceStopper.POWER_DRAW_SERVICES + ['ui']) 27 self._services.stop_services() 28 29 30 def run_once(self, max_run_time=180, percent_charge_to_add=1, 31 percent_initial_charge_max=None, 32 percent_target_charge=None, 33 use_design_charge_capacity=True): 34 35 """ 36 max_run_time: maximum time the test will run for 37 percent_charge_to_add: percentage of the charge capacity charge to 38 add. The target charge will be capped at the charge capacity. 39 percent_initial_charge_max: maxium allowed initial charge. 40 use_design_charge_capacity: If set, use charge_full_design rather than 41 charge_full for calculations. charge_full represents 42 wear-state of battery, vs charge_full_design representing 43 ideal design state. 44 """ 45 46 time_to_sleep = 60 47 48 self._backlight = power_utils.Backlight() 49 self._backlight.set_percent(0) 50 51 self.remaining_time = self.max_run_time = max_run_time 52 53 self.charge_full_design = self.status.battery[0].charge_full_design 54 self.charge_full = self.status.battery[0].charge_full 55 if use_design_charge_capacity: 56 self.charge_capacity = self.charge_full_design 57 else: 58 self.charge_capacity = self.charge_full 59 60 if self.charge_capacity == 0: 61 raise error.TestError('Failed to determine charge capacity') 62 63 self.initial_charge = self.status.battery[0].charge_now 64 percent_initial_charge = self.initial_charge * 100 / \ 65 self.charge_capacity 66 if percent_initial_charge_max and percent_initial_charge > \ 67 percent_initial_charge_max: 68 raise error.TestError('Initial charge (%f) higher than max (%f)' 69 % (percent_initial_charge, percent_initial_charge_max)) 70 71 current_charge = self.initial_charge 72 if percent_target_charge is None: 73 charge_to_add = self.charge_capacity * \ 74 float(percent_charge_to_add) / 100 75 target_charge = current_charge + charge_to_add 76 else: 77 target_charge = self.charge_capacity * \ 78 float(percent_target_charge) / 100 79 80 # trim target_charge if it exceeds charge capacity 81 if target_charge > self.charge_capacity: 82 target_charge = self.charge_capacity 83 84 logging.info('max_run_time: %d', self.max_run_time) 85 logging.info('initial_charge: %f', self.initial_charge) 86 logging.info('target_charge: %f', target_charge) 87 88 while self.remaining_time and current_charge < target_charge: 89 if time_to_sleep > self.remaining_time: 90 time_to_sleep = self.remaining_time 91 self.remaining_time -= time_to_sleep 92 93 time.sleep(time_to_sleep) 94 95 self.status.refresh() 96 if not self.status.on_ac(): 97 raise error.TestError( 98 'This test needs to be run with the AC power online') 99 100 new_charge = self.status.battery[0].charge_now 101 logging.info('time_to_sleep: %d', time_to_sleep) 102 logging.info('charge_added: %f', (new_charge - current_charge)) 103 104 current_charge = new_charge 105 logging.info('current_charge: %f', current_charge) 106 107 if self.status.battery[0].status == 'Full': 108 logging.info('Battery full, aborting!') 109 break 110 111 112 def postprocess_iteration(self): 113 keyvals = {} 114 keyvals['ah_charge_full'] = self.charge_full 115 keyvals['ah_charge_full_design'] = self.charge_full_design 116 keyvals['ah_charge_capacity'] = self.charge_capacity 117 keyvals['ah_initial_charge'] = self.initial_charge 118 keyvals['ah_final_charge'] = self.status.battery[0].charge_now 119 keyvals['s_time_taken'] = self.max_run_time - self.remaining_time 120 keyvals['percent_initial_charge'] = self.initial_charge * 100 / \ 121 keyvals['ah_charge_capacity'] 122 keyvals['percent_final_charge'] = keyvals['ah_final_charge'] * 100 / \ 123 keyvals['ah_charge_capacity'] 124 125 percent_charge_added = keyvals['percent_final_charge'] - \ 126 keyvals['percent_initial_charge'] 127 # Conditionally write charge current keyval only when the amount of 128 # charge added is > 50% to remove samples when test is run but battery 129 # is already mostly full. Otherwise current will be ~0 and not 130 # meaningful. 131 if percent_charge_added > 50: 132 hrs_charging = keyvals['s_time_taken'] / 3600. 133 keyvals['a_avg50_charge_current'] = \ 134 (keyvals['ah_final_charge'] - self.initial_charge) / \ 135 hrs_charging 136 137 self.write_perf_keyval(keyvals) 138 139 140 def cleanup(self): 141 if hasattr(self, '_services') and self._services: 142 self._services.restore_services() 143 if hasattr(self, '_backlight') and self._backlight: 144 self._backlight.restore() 145