1# Copyright (c) 2011 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, math, time 6 7from autotest_lib.client.bin import test 8from autotest_lib.client.common_lib import error 9from autotest_lib.client.cros import rtc 10from autotest_lib.client.cros.power import power_status, sys_power 11 12class power_Standby(test.test): 13 """Measure Standby(S3) power test.""" 14 version = 1 15 _percent_min_charge = 0.1 16 _min_sample_hours = 0.1 17 18 def run_once(self, test_hours=None, sample_hours=None, 19 percent_initial_charge_min=0.2, max_milliwatts_standby=None): 20 21 if test_hours <= sample_hours: 22 raise error.TestFail("Test hours must be greater than sample hours") 23 24 # If we're measuring <= 6min of S3 then the S0 time is not negligible. 25 # Note, reasonable rule of thumb is S0 idle is ~10-20 times S3 power. 26 if sample_hours < self._min_sample_hours: 27 raise error.TestFail("Must suspend more than %.2f hours" % \ 28 sample_hours) 29 30 # Query initial power status 31 power_stats = power_status.get_status() 32 power_stats.assert_battery_state(percent_initial_charge_min) 33 charge_start = power_stats.battery[0].charge_now 34 voltage_start = power_stats.battery[0].voltage_now 35 36 max_hours = charge_start * voltage_start / \ 37 (max_milliwatts_standby / 1000) 38 if max_hours < test_hours: 39 raise error.TestFail('Battery not charged adequately for test') 40 41 elapsed_hours = 0 42 43 while elapsed_hours < test_hours: 44 charge_before = power_stats.battery[0].charge_now 45 before_suspend_secs = rtc.get_seconds() 46 sys_power.do_suspend(sample_hours * 3600) 47 after_suspend_secs = rtc.get_seconds() 48 49 power_stats.refresh() 50 if power_stats.percent_current_charge() < self._percent_min_charge: 51 logging.warning("Battery percent = %.2f%%. Too low to continue") 52 break 53 54 # check that the RTC slept the correct amount of time as there could 55 # potentially be another wake source that would spoil the test. 56 actual_hours = (after_suspend_secs - before_suspend_secs) / 3600.0 57 logging.debug("actual_hours = %.4f", actual_hours) 58 percent_diff = math.fabs((actual_hours - sample_hours) / 59 ((actual_hours + sample_hours) / 2) * 100) 60 if percent_diff > 2: 61 err_str = "Requested S3 time and actual varied by %.2f%%." \ 62 % percent_diff 63 raise error.TestFail(err_str) 64 65 # Check resulting charge consumption 66 charge_used = charge_before - power_stats.battery[0].charge_now 67 logging.debug("charge_used = %.6f", charge_used) 68 69 elapsed_hours += actual_hours 70 logging.debug("elapsed_hours = %.4f", elapsed_hours) 71 72 charge_end = power_stats.battery[0].charge_now 73 voltage_end = power_stats.battery[0].voltage_now 74 standby_hours = power_stats.battery[0].charge_full_design / \ 75 (charge_start - charge_end) * elapsed_hours 76 energy_used = charge_start * voltage_start - charge_end * voltage_end 77 if energy_used <= 0: 78 raise error.TestError("Energy used reading is suspect.") 79 standby_milliwatts = energy_used / elapsed_hours * 1000 80 81 results = {} 82 results['milliwatts_standby_power'] = standby_milliwatts 83 results['hours_standby_time'] = standby_hours 84 self.write_perf_keyval(results) 85 86 # need to sleep for some time to allow network connection to return 87 time.sleep(10) 88