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