普通文本  |  88行  |  3.73 KB

# 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 rtc
from autotest_lib.client.cros.power import power_status, 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_start = power_stats.battery[0].charge_now
        voltage_start = power_stats.battery[0].voltage_now

        max_hours = charge_start * voltage_start / \
            (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
            before_suspend_secs = rtc.get_seconds()
            sys_power.do_suspend(sample_hours * 3600)
            after_suspend_secs = rtc.get_seconds()

            power_stats.refresh()
            if power_stats.percent_current_charge() < self._percent_min_charge:
                logging.warning("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_end = power_stats.battery[0].charge_now
        voltage_end = power_stats.battery[0].voltage_now
        standby_hours = power_stats.battery[0].charge_full_design / \
            (charge_start - charge_end) * elapsed_hours
        energy_used = charge_start * voltage_start - charge_end * voltage_end
        if energy_used <= 0:
            raise error.TestError("Energy used reading is suspect.")
        standby_milliwatts = energy_used / elapsed_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)