blob: 50acb7a409f727945e9a5aca9c25915057ef1621 [file] [log] [blame]
# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging, math, time
from autotest_lib.client.bin import test
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros import power_status, rtc, sys_power
class power_Standby(test.test):
"""Measure Standby(S3) power test."""
version = 1
_percent_min_charge = 0.1
_min_sample_hours = 0.1
def run_once(self, test_hours=None, sample_hours=None,
percent_initial_charge_min=0.2, max_milliwatts_standby=None):
if test_hours <= sample_hours:
raise error.TestFail("Test hours must be greater than sample hours")
# If we're measuring <= 6min of S3 then the S0 time is not negligible.
# Note, reasonable rule of thumb is S0 idle is ~10-20 times S3 power.
if sample_hours < self._min_sample_hours:
raise error.TestFail("Must suspend more than %.2f hours" % \
sample_hours)
# Query initial power status
power_stats = power_status.get_status()
power_stats.assert_battery_state(percent_initial_charge_min)
charge_avail = power_stats.battery[0].charge_now
max_hours = charge_avail * power_stats.battery[0].voltage_min_design / \
(max_milliwatts_standby / 1000)
if max_hours < test_hours:
raise error.TestFail('Battery not charged adequately for test')
elapsed_hours = 0
while elapsed_hours < test_hours:
charge_before = power_stats.battery[0].charge_now
# Set RTC for wakeup
before_suspend_secs = rtc.get_seconds()
alarm_secs = before_suspend_secs + int(sample_hours * 3600)
# flush RTC as it may not work subsequently if wake was not RTC
rtc.set_wake_alarm(0)
rtc.set_wake_alarm(alarm_secs)
sys_power.suspend_to_ram()
after_suspend_secs = rtc.get_seconds()
power_stats.refresh()
if power_stats.percent_current_charge() < self._percent_min_charge:
logging.warn("Battery percent = %.2f%%. Too low to continue")
break
# check that the RTC slept the correct amount of time as there could
# potentially be another wake source that would spoil the test.
actual_hours = (after_suspend_secs - before_suspend_secs) / 3600.0
logging.debug("actual_hours = %.4f", actual_hours)
percent_diff = math.fabs((actual_hours - sample_hours) /
((actual_hours + sample_hours) / 2) * 100)
if percent_diff > 2:
err_str = "Requested S3 time and actual varied by %.2f%%." \
% percent_diff
raise error.TestFail(err_str)
# Check resulting charge consumption
charge_used = charge_before - power_stats.battery[0].charge_now
logging.debug("charge_used = %.6f", charge_used)
elapsed_hours += actual_hours
logging.debug("elapsed_hours = %.4f", elapsed_hours)
charge_used = charge_avail - power_stats.battery[0].charge_now
if charge_used <= 0:
raise error.TestFail("Charge used reading is suspect.")
standby_hours = power_stats.battery[0].charge_full_design / \
charge_used * elapsed_hours
energy_used = charge_used * power_stats.battery[0].voltage_min_design
standby_milliwatts = energy_used / standby_hours * 1000
results = {}
results['milliwatts_standby_power'] = standby_milliwatts
results['hours_standby_time'] = standby_hours
self.write_perf_keyval(results)
# need to sleep for some time to allow network connection to return
time.sleep(10)