• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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