Home | History | Annotate | Download | only in power
      1 # Copyright 2018 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 import time
      5 
      6 from autotest_lib.client.bin import test
      7 from autotest_lib.client.cros import service_stopper
      8 from autotest_lib.client.cros.power import power_dashboard
      9 from autotest_lib.client.cros.power import power_rapl
     10 from autotest_lib.client.cros.power import power_status
     11 from autotest_lib.client.cros.power import power_telemetry_utils
     12 from autotest_lib.client.cros.power import power_utils
     13 
     14 
     15 class power_Test(test.test):
     16     """Optional base class power related tests."""
     17     version = 1
     18 
     19     def initialize(self, seconds_period=20., pdash_note=''):
     20         """Perform necessary initialization prior to power test run.
     21 
     22         @param seconds_period: float of probing interval in seconds.
     23         @param pdash_note: note of the current run to send to power dashboard.
     24 
     25         @var backlight: power_utils.Backlight object.
     26         @var keyvals: dictionary of result keyvals.
     27         @var status: power_status.SysStat object.
     28 
     29         @var _checkpoint_logger: power_status.CheckpointLogger to track
     30                                  checkpoint data.
     31         @var _plog: power_status.PowerLogger object to monitor power.
     32         @var _psr: power_utils.DisplayPanelSelfRefresh object to monitor PSR.
     33         @var _services: service_stopper.ServiceStopper object.
     34         @var _start_time: float of time in seconds since Epoch test started.
     35         @var _stats: power_status.StatoMatic object.
     36         @var _tlog: power_status.TempLogger object to monitor temperatures.
     37         @var _clog: power_status.CPUStatsLogger object to monitor CPU(s)
     38                     frequencies and c-states.
     39         @var _meas_logs: list of power_status.MeasurementLoggers
     40         """
     41         super(power_Test, self).initialize()
     42         self.backlight = power_utils.Backlight()
     43         self.backlight.set_default()
     44         self.keyvals = dict()
     45         self.status = power_status.get_status()
     46 
     47         self._checkpoint_logger = power_status.CheckpointLogger()
     48 
     49         measurements = []
     50         if not self.status.on_ac():
     51             measurements.append(
     52                 power_status.SystemPower(self.status.battery_path))
     53         if power_utils.has_powercap_support():
     54             measurements += power_rapl.create_powercap()
     55         elif power_utils.has_rapl_support():
     56             measurements += power_rapl.create_rapl()
     57         self._plog = power_status.PowerLogger(measurements,
     58                 seconds_period=seconds_period,
     59                 checkpoint_logger=self._checkpoint_logger)
     60         self._psr = power_utils.DisplayPanelSelfRefresh()
     61         self._services = service_stopper.ServiceStopper(
     62                 service_stopper.ServiceStopper.POWER_DRAW_SERVICES)
     63         self._services.stop_services()
     64         self._stats = power_status.StatoMatic()
     65 
     66         self._tlog = power_status.TempLogger([],
     67                 seconds_period=seconds_period,
     68                 checkpoint_logger=self._checkpoint_logger)
     69         self._clog = power_status.CPUStatsLogger(seconds_period=seconds_period,
     70                 checkpoint_logger=self._checkpoint_logger)
     71 
     72         self._meas_logs = [self._plog, self._tlog, self._clog]
     73 
     74         self._pdash_note = pdash_note
     75 
     76     def warmup(self, warmup_time=30):
     77         """Warm up.
     78 
     79         Wait between initialization and run_once for new settings to stabilize.
     80 
     81         @param warmup_time: integer of seconds to warmup.
     82         """
     83         time.sleep(warmup_time)
     84 
     85     def start_measurements(self):
     86         """Start measurements."""
     87         for log in self._meas_logs:
     88             log.start()
     89         self._start_time = time.time()
     90         power_telemetry_utils.start_measurement()
     91 
     92     def loop_sleep(self, loop, sleep_secs):
     93         """Jitter free sleep.
     94 
     95         @param loop: integer of loop (1st is zero).
     96         @param sleep_secs: integer of desired sleep seconds.
     97         """
     98         next_time = self._start_time + (loop + 1) * sleep_secs
     99         time.sleep(next_time - time.time())
    100 
    101     def checkpoint_measurements(self, name, start_time=None):
    102         """Checkpoint measurements.
    103 
    104         @param name: string name of measurement being checkpointed.
    105         @param start_time: float of time in seconds since Epoch that
    106                 measurements being checkpointed began.
    107         """
    108         if not start_time:
    109             start_time = self._start_time
    110         self.status.refresh()
    111         self._checkpoint_logger.checkpoint(name, start_time)
    112         self._psr.refresh()
    113 
    114     def publish_keyvals(self):
    115         """Publish power result keyvals."""
    116         keyvals = self._stats.publish()
    117         keyvals['level_backlight_max'] = self.backlight.get_max_level()
    118         keyvals['level_backlight_current'] = self.backlight.get_level()
    119 
    120         # record battery stats if not on AC
    121         if self.status.on_ac():
    122             keyvals['b_on_ac'] = 1
    123         else:
    124             keyvals['b_on_ac'] = 0
    125 
    126         if self.status.battery:
    127             keyvals['ah_charge_full'] = self.status.battery[0].charge_full
    128             keyvals['ah_charge_full_design'] = \
    129                                 self.status.battery[0].charge_full_design
    130             keyvals['ah_charge_now'] = self.status.battery[0].charge_now
    131             keyvals['a_current_now'] = self.status.battery[0].current_now
    132             keyvals['wh_energy'] = self.status.battery[0].energy
    133             keyvals['w_energy_rate'] = self.status.battery[0].energy_rate
    134             keyvals['v_voltage_min_design'] = \
    135                                 self.status.battery[0].voltage_min_design
    136             keyvals['v_voltage_now'] = self.status.battery[0].voltage_now
    137 
    138         for log in self._meas_logs:
    139             keyvals.update(log.calc())
    140         keyvals.update(self._psr.get_keyvals())
    141 
    142         self.keyvals.update(keyvals)
    143 
    144         core_keyvals = power_utils.get_core_keyvals(self.keyvals)
    145         self.write_perf_keyval(core_keyvals)
    146 
    147     def _publish_dashboard(self):
    148         """Report results to chromeperf & power dashboard."""
    149 
    150         self.publish_keyvals()
    151 
    152         # publish power values
    153         for key, values in self.keyvals.iteritems():
    154             if key.endswith('pwr'):
    155                 self.output_perf_value(description=key, value=values, units='W',
    156                                    higher_is_better=False, graph='power')
    157 
    158         # publish temperature values
    159         for key, values in self.keyvals.iteritems():
    160             if key.endswith('temp'):
    161                 self.output_perf_value(description=key, value=values, units='C',
    162                                    higher_is_better=False, graph='temperature')
    163 
    164         # publish to power dashboard
    165         pdash = power_dashboard.PowerLoggerDashboard(
    166             self._plog, self.tagged_testname, self.resultsdir,
    167             note=self._pdash_note)
    168         pdash.upload()
    169         cdash = power_dashboard.CPUStatsLoggerDashboard(
    170             self._clog, self.tagged_testname, self.resultsdir,
    171             note=self._pdash_note)
    172         cdash.upload()
    173         tdash = power_dashboard.TempLoggerDashboard(
    174             self._tlog, self.tagged_testname, self.resultsdir,
    175             note=self._pdash_note)
    176         tdash.upload()
    177 
    178     def _save_results(self):
    179         """Save results of each logger in resultsdir."""
    180         for log in self._meas_logs:
    181             log.save_results(self.resultsdir)
    182         self._checkpoint_logger.save_checkpoint_data(self.resultsdir)
    183 
    184     def postprocess_iteration(self):
    185         """Write keyval and send data to dashboard."""
    186         power_telemetry_utils.end_measurement()
    187         super(power_Test, self).postprocess_iteration()
    188         self._publish_dashboard()
    189         self._save_results()
    190 
    191     def cleanup(self):
    192         """Reverse setting change in initialization."""
    193         if self.backlight:
    194             self.backlight.restore()
    195         self._services.restore_services()
    196         super(power_Test, self).cleanup()
    197