# Copyright (c) 2012 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 collections
import contextlib
import ctypes
import fcntl
import glob
import itertools
import json
import logging
import math
import numpy
import os
import re
import struct
import threading
import time

from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error, enum
from autotest_lib.client.cros import kernel_trace
from autotest_lib.client.cros.power import power_utils

BatteryDataReportType = enum.Enum('CHARGE', 'ENERGY')

# battery data reported at 1e6 scale
BATTERY_DATA_SCALE = 1e6
# number of times to retry reading the battery in the case of bad data
BATTERY_RETRY_COUNT = 3
# default filename when saving CheckpointLogger data to file
CHECKPOINT_LOG_DEFAULT_FNAME = 'checkpoint_log.json'


class DevStat(object):
    """
    Device power status. This class implements generic status initialization
    and parsing routines.
    """

    def __init__(self, fields, path=None):
        self.fields = fields
        self.path = path


    def reset_fields(self):
        """
        Reset all class fields to None to mark their status as unknown.
        """
        for field in self.fields.iterkeys():
            setattr(self, field, None)


    def read_val(self,  file_name, field_type):
        """Read a value from file.
        """
        try:
            path = file_name
            if not file_name.startswith('/'):
                path = os.path.join(self.path, file_name)
            f = open(path, 'r')
            out = f.readline().rstrip('\n')
            val = field_type(out)
            return val

        except:
            return field_type(0)


    def read_all_vals(self):
        """Read all values.
        """
        for field, prop in self.fields.iteritems():
            if prop[0]:
                val = self.read_val(prop[0], prop[1])
                setattr(self, field, val)

    def update(self):
        """Update the DevStat.

        Need to implement in subclass.
        """
        pass

class ThermalStatACPI(DevStat):
    """
    ACPI-based thermal status.

    Fields:
    (All temperatures are in millidegrees Celsius.)

    str   enabled:            Whether thermal zone is enabled
    int   temp:               Current temperature
    str   type:               Thermal zone type
    int   num_trip_points:    Number of thermal trip points that activate
                                cooling devices
    int   num_points_tripped: Temperature is above this many trip points
    str   trip_point_N_type:  Trip point #N's type
    int   trip_point_N_temp:  Trip point #N's temperature value
    int   cdevX_trip_point:   Trip point o cooling device #X (index)
    """

    MAX_TRIP_POINTS = 20

    thermal_fields = {
        'enabled':              ['enabled', str],
        'temp':                 ['temp', int],
        'type':                 ['type', str],
        'num_points_tripped':   ['', '']
        }
    path = '/sys/class/thermal/thermal_zone*'

    def __init__(self, path=None):
        # Browse the thermal folder for trip point fields.
        self.num_trip_points = 0

        thermal_fields = glob.glob(path + '/*')
        for file in thermal_fields:
            field = file[len(path + '/'):]
            if field.find('trip_point') != -1:
                if field.find('temp'):
                    field_type = int
                else:
                    field_type = str
                self.thermal_fields[field] = [field, field_type]

                # Count the number of trip points.
                if field.find('_type') != -1:
                    self.num_trip_points += 1

        super(ThermalStatACPI, self).__init__(self.thermal_fields, path)
        self.update()

    def update(self):
        if not os.path.exists(self.path):
            return

        self.read_all_vals()
        self.num_points_tripped = 0

        for field in self.thermal_fields:
            if field.find('trip_point_') != -1 and field.find('_temp') != -1 \
                    and self.temp > self.read_val(field, int):
                self.num_points_tripped += 1
                logging.info('Temperature trip point #' + \
                            field[len('trip_point_'):field.rfind('_temp')] + \
                            ' tripped.')


class ThermalStatHwmon(DevStat):
    """
    hwmon-based thermal status.

    Fields:
    int   <tname>_temp<num>_input: Current temperature in millidegrees Celsius
      where:
          <tname> : name of hwmon device in sysfs
          <num>   : number of temp as some hwmon devices have multiple

    """
    path = '/sys/class/hwmon'

    thermal_fields = {}
    def __init__(self, rootpath=None):
        if not rootpath:
            rootpath = self.path
        for subpath1 in glob.glob('%s/hwmon*' % rootpath):
            for subpath2 in ['','device/']:
                gpaths = glob.glob("%s/%stemp*_input" % (subpath1, subpath2))
                for gpath in gpaths:
                    bname = os.path.basename(gpath)
                    field_path = os.path.join(subpath1, subpath2, bname)

                    tname_path = os.path.join(os.path.dirname(gpath), "name")
                    tname = utils.read_one_line(tname_path)

                    field_key = "%s_%s" % (tname, bname)
                    self.thermal_fields[field_key] = [field_path, int]

        super(ThermalStatHwmon, self).__init__(self.thermal_fields, rootpath)
        self.update()

    def update(self):
        if not os.path.exists(self.path):
            return

        self.read_all_vals()

    def read_val(self,  file_name, field_type):
        try:
            path = os.path.join(self.path, file_name)
            f = open(path, 'r')
            out = f.readline()
            return field_type(out)
        except:
            return field_type(0)


class ThermalStat(object):
    """helper class to instantiate various thermal devices."""
    def __init__(self):
        self._thermals = []
        self.min_temp = 999999999
        self.max_temp = -999999999

        thermal_stat_types = [(ThermalStatHwmon.path, ThermalStatHwmon),
                              (ThermalStatACPI.path, ThermalStatACPI)]
        for thermal_glob_path, thermal_type in thermal_stat_types:
            try:
                thermal_path = glob.glob(thermal_glob_path)[0]
                logging.debug('Using %s for thermal info.', thermal_path)
                self._thermals.append(thermal_type(thermal_path))
            except:
                logging.debug('Could not find thermal path %s, skipping.',
                              thermal_glob_path)


    def get_temps(self):
        """Get temperature readings.

        Returns:
            string of temperature readings.
        """
        temp_str = ''
        for thermal in self._thermals:
            thermal.update()
            for kname in thermal.fields:
                if kname is 'temp' or kname.endswith('_input'):
                    val = getattr(thermal, kname)
                    temp_str += '%s:%d ' % (kname, val)
                    if val > self.max_temp:
                        self.max_temp = val
                    if val < self.min_temp:
                        self.min_temp = val


        return temp_str


class BatteryStat(DevStat):
    """
    Battery status.

    Fields:

    float charge_full:        Last full capacity reached [Ah]
    float charge_full_design: Full capacity by design [Ah]
    float charge_now:         Remaining charge [Ah]
    float current_now:        Battery discharge rate [A]
    float energy:             Current battery charge [Wh]
    float energy_full:        Last full capacity reached [Wh]
    float energy_full_design: Full capacity by design [Wh]
    float energy_rate:        Battery discharge rate [W]
    float power_now:          Battery discharge rate [W]
    float remaining_time:     Remaining discharging time [h]
    float voltage_min_design: Minimum voltage by design [V]
    float voltage_max_design: Maximum voltage by design [V]
    float voltage_now:        Voltage now [V]
    """

    battery_fields = {
        'status':               ['status', str],
        'charge_full':          ['charge_full', float],
        'charge_full_design':   ['charge_full_design', float],
        'charge_now':           ['charge_now', float],
        'current_now':          ['current_now', float],
        'voltage_min_design':   ['voltage_min_design', float],
        'voltage_max_design':   ['voltage_max_design', float],
        'voltage_now':          ['voltage_now', float],
        'energy':               ['energy_now', float],
        'energy_full':          ['energy_full', float],
        'energy_full_design':   ['energy_full_design', float],
        'power_now':            ['power_now', float],
        'present':              ['present', int],
        'energy_rate':          ['', ''],
        'remaining_time':       ['', '']
        }

    def __init__(self, path=None):
        super(BatteryStat, self).__init__(self.battery_fields, path)
        self.update()


    def update(self):
        for _ in xrange(BATTERY_RETRY_COUNT):
            try:
                self._read_battery()
                return
            except error.TestError as e:
                logging.warn(e)
                for field, prop in self.battery_fields.iteritems():
                    logging.warn(field + ': ' + repr(getattr(self, field)))
                continue
        raise error.TestError('Failed to read battery state')


    def _read_battery(self):
        self.read_all_vals()

        if self.charge_full == 0 and self.energy_full != 0:
            battery_type = BatteryDataReportType.ENERGY
        else:
            battery_type = BatteryDataReportType.CHARGE

        if self.voltage_min_design != 0:
            voltage_nominal = self.voltage_min_design
        else:
            voltage_nominal = self.voltage_now

        if voltage_nominal == 0:
            raise error.TestError('Failed to determine battery voltage')

        # Since charge data is present, calculate parameters based upon
        # reported charge data.
        if battery_type == BatteryDataReportType.CHARGE:
            self.charge_full = self.charge_full / BATTERY_DATA_SCALE
            self.charge_full_design = self.charge_full_design / \
                                      BATTERY_DATA_SCALE
            self.charge_now = self.charge_now / BATTERY_DATA_SCALE

            self.current_now = math.fabs(self.current_now) / \
                               BATTERY_DATA_SCALE

            self.energy =  voltage_nominal * \
                           self.charge_now / \
                           BATTERY_DATA_SCALE
            self.energy_full = voltage_nominal * \
                               self.charge_full / \
                               BATTERY_DATA_SCALE
            self.energy_full_design = voltage_nominal * \
                                      self.charge_full_design / \
                                      BATTERY_DATA_SCALE

        # Charge data not present, so calculate parameters based upon
        # reported energy data.
        elif battery_type == BatteryDataReportType.ENERGY:
            self.charge_full = self.energy_full / voltage_nominal
            self.charge_full_design = self.energy_full_design / \
                                      voltage_nominal
            self.charge_now = self.energy / voltage_nominal

            # TODO(shawnn): check if power_now can really be reported
            # as negative, in the same way current_now can
            self.current_now = math.fabs(self.power_now) / \
                               voltage_nominal

            self.energy = self.energy / BATTERY_DATA_SCALE
            self.energy_full = self.energy_full / BATTERY_DATA_SCALE
            self.energy_full_design = self.energy_full_design / \
                                      BATTERY_DATA_SCALE

        self.voltage_min_design = self.voltage_min_design / \
                                  BATTERY_DATA_SCALE
        self.voltage_max_design = self.voltage_max_design / \
                                  BATTERY_DATA_SCALE
        self.voltage_now = self.voltage_now / \
                           BATTERY_DATA_SCALE
        voltage_nominal = voltage_nominal / \
                          BATTERY_DATA_SCALE

        self.energy_rate =  self.voltage_now * self.current_now

        self.remaining_time = 0
        if self.current_now and self.energy_rate:
            self.remaining_time =  self.energy / self.energy_rate

        if self.charge_full > (self.charge_full_design * 1.5):
            raise error.TestError('Unreasonable charge_full value')
        if self.charge_now > (self.charge_full_design * 1.5):
            raise error.TestError('Unreasonable charge_now value')


class LineStatDummy(DevStat):
    """
    Dummy line stat for devices which don't provide power_supply related sysfs
    interface.
    """
    def __init__(self):
        self.online = True


    def update(self):
        pass

class LineStat(DevStat):
    """
    Power line status.

    Fields:

    bool online:              Line power online
    """

    linepower_fields = {
        'is_online':             ['online', int],
        'status':                ['status', str]
        }


    def __init__(self, path=None):
        super(LineStat, self).__init__(self.linepower_fields, path)
        logging.debug("line path: %s", path)
        self.update()


    def update(self):
        self.read_all_vals()
        self.online = self.is_online == 1


class SysStat(object):
    """
    System power status for a given host.

    Fields:

    battery:   A list of BatteryStat objects.
    linepower: A list of LineStat objects.
    """
    psu_types = ['Mains', 'USB', 'USB_ACA', 'USB_C', 'USB_CDP', 'USB_DCP',
                 'USB_PD', 'USB_PD_DRP', 'Unknown']

    def __init__(self):
        power_supply_path = '/sys/class/power_supply/*'
        self.battery = None
        self.linepower = []
        self.thermal = None
        self.battery_path = None
        self.linepower_path = []

        power_supplies = glob.glob(power_supply_path)
        for path in power_supplies:
            type_path = os.path.join(path,'type')
            if not os.path.exists(type_path):
                continue
            power_type = utils.read_one_line(type_path)
            if power_type == 'Battery':
                scope_path = os.path.join(path,'scope')
                if (os.path.exists(scope_path) and
                        utils.read_one_line(scope_path) == 'Device'):
                    continue
                self.battery_path = path
            elif power_type in self.psu_types:
                self.linepower_path.append(path)

        if not self.battery_path or not self.linepower_path:
            logging.warning("System does not provide power sysfs interface")

        self.thermal = ThermalStat()


    def refresh(self):
        """
        Initialize device power status objects.
        """
        self.linepower = []

        if self.battery_path:
            self.battery = [ BatteryStat(self.battery_path) ]

        for path in self.linepower_path:
            self.linepower.append(LineStat(path))
        if not self.linepower:
            self.linepower = [ LineStatDummy() ]

        temp_str = self.thermal.get_temps()
        if temp_str:
            logging.info('Temperature reading: ' + temp_str)
        else:
            logging.error('Could not read temperature, skipping.')


    def on_ac(self):
        """
        Returns true if device is currently running from AC power.
        """
        on_ac = False
        for linepower in self.linepower:
            on_ac |= linepower.online

        # Butterfly can incorrectly report AC online for some time after
        # unplug. Check battery discharge state to confirm.
        if utils.get_board() == 'butterfly':
            on_ac &= (not self.battery_discharging())
        return on_ac


    def ac_charging(self):
        """
        Returns true if device is currently charging from AC power.
        """
        charging = False
        for linepower in self.linepower:
            charging |= (linepower.status == 'Charging')
        return charging


    def battery_discharging(self):
        """
        Returns true if battery is currently discharging or false otherwise.
        """
        if not self.battery_path:
            logging.warn('Unable to determine battery discharge status')
            return False

        return(self.battery[0].status.rstrip() == 'Discharging')


    def battery_discharge_ok_on_ac(self):
        """Returns True if battery is ok to discharge on AC presently.

        some devices cycle between charge & discharge above a certain
        SoC.  If AC is charging and SoC > 95% we can safely assume that.
        """
        return self.ac_charging() and (self.percent_current_charge() > 95)


    def percent_current_charge(self):
        """Returns current charge compare to design capacity in percent.
        """
        return self.battery[0].charge_now * 100 / \
               self.battery[0].charge_full_design


    def assert_battery_state(self, percent_initial_charge_min):
        """Check initial power configuration state is battery.

        Args:
          percent_initial_charge_min: float between 0 -> 1.00 of
            percentage of battery that must be remaining.
            None|0|False means check not performed.

        Raises:
          TestError: if one of battery assertions fails
        """
        if self.on_ac():
            raise error.TestError(
                'Running on AC power. Please remove AC power cable.')

        percent_initial_charge = self.percent_current_charge()

        if percent_initial_charge_min and percent_initial_charge < \
                                          percent_initial_charge_min:
            raise error.TestError('Initial charge (%f) less than min (%f)'
                      % (percent_initial_charge, percent_initial_charge_min))


def get_status():
    """
    Return a new power status object (SysStat). A new power status snapshot
    for a given host can be obtained by either calling this routine again and
    constructing a new SysStat object, or by using the refresh method of the
    SysStat object.
    """
    status = SysStat()
    status.refresh()
    return status


class AbstractStats(object):
    """
    Common superclass for measurements of percentages per state over time.

    Public Attributes:
        incremental:  If False, stats returned are from a single
        _read_stats.  Otherwise, stats are from the difference between
        the current and last refresh.
    """

    @staticmethod
    def to_percent(stats):
        """
        Turns a dict with absolute time values into a dict with percentages.
        """
        total = sum(stats.itervalues())
        if total == 0:
            return {k: 0 for k in stats}
        return dict((k, v * 100.0 / total) for (k, v) in stats.iteritems())


    @staticmethod
    def do_diff(new, old):
        """
        Returns a dict with value deltas from two dicts with matching keys.
        """
        return dict((k, new[k] - old.get(k, 0)) for k in new.iterkeys())


    @staticmethod
    def format_results_percent(results, name, percent_stats):
        """
        Formats autotest result keys to format:
          percent_<name>_<key>_time
        """
        for key in percent_stats:
            results['percent_%s_%s_time' % (name, key)] = percent_stats[key]


    @staticmethod
    def format_results_wavg(results, name, wavg):
        """
        Add an autotest result keys to format: wavg_<name>
        """
        if wavg is not None:
            results['wavg_%s' % (name)] = wavg


    def __init__(self, name=None, incremental=True):
        if not name:
            raise error.TestFail("Need to name AbstractStats instance please.")
        self.name = name
        self.incremental = incremental
        self._stats = self._read_stats()


    def refresh(self):
        """
        Returns dict mapping state names to percentage of time spent in them.
        """
        raw_stats = result = self._read_stats()
        if self.incremental:
            result = self.do_diff(result, self._stats)
        self._stats = raw_stats
        return self.to_percent(result)


    def _automatic_weighted_average(self):
        """
        Turns a dict with absolute times (or percentages) into a weighted
        average value.
        """
        total = sum(self._stats.itervalues())
        if total == 0:
            return None

        return sum((float(k)*v) / total for (k, v) in self._stats.iteritems())


    def _supports_automatic_weighted_average(self):
        """
        Override!

        Returns True if stats collected can be automatically converted from
        percent distribution to weighted average. False otherwise.
        """
        return False


    def weighted_average(self):
        """
        Return weighted average calculated using the automated average method
        (if supported) or using a custom method defined by the stat.
        """
        if self._supports_automatic_weighted_average():
            return self._automatic_weighted_average()

        return self._weighted_avg_fn()


    def _weighted_avg_fn(self):
        """
        Override! Custom weighted average function.

        Returns weighted average as a single floating point value.
        """
        return None


    def _read_stats(self):
        """
        Override! Reads the raw data values that shall be measured into a dict.
        """
        raise NotImplementedError('Override _read_stats in the subclass!')


CPU_BASE_PATH = '/sys/devices/system/cpu/'

def count_all_cpus():
    """
    Return count of cpus on system.
    """
    path = '%s/cpu[0-9]*' % CPU_BASE_PATH
    return len(glob.glob(path))

def get_online_cpus():
    """
    Return list of integer cpu numbers that are online.
    """
    cpus = [int(f.split('/')[-1]) for f in glob.iglob('/dev/cpu/[0-9]*')]
    return frozenset(cpus)

def get_cpus_filepaths_for_suffix(cpus, suffix):
    """
    For each cpu in |cpus| check whether |CPU_BASE_PATH|/cpu%d/|suffix| exists.
    Return tuple of two lists t:
                    t[0]: all cpu ids where the condition above holds
                    t[1]: all full paths where condition above holds.
    """
    available_cpus = []
    available_paths = []
    for c in cpus:
        c_file_path = os.path.join(CPU_BASE_PATH, 'cpu%d' % c, suffix)
        if os.path.exists(c_file_path):
          available_cpus.append(c)
          available_paths.append(c_file_path)
    return (available_cpus, available_paths)

class CPUFreqStats(AbstractStats):
    """
    CPU Frequency statistics
    """
    MSR_PLATFORM_INFO = 0xce
    MSR_IA32_MPERF = 0xe7
    MSR_IA32_APERF = 0xe8

    def __init__(self, cpus=None):
        name = 'cpufreq'
        stats_suffix = 'cpufreq/stats/time_in_state'
        key_suffix = 'cpufreq/scaling_available_frequencies'
        cpufreq_driver = '/sys/devices/system/cpu/cpu0/cpufreq/scaling_driver'
        if not cpus:
            cpus = get_online_cpus()
        _, self._file_paths = get_cpus_filepaths_for_suffix(cpus,
                                                            stats_suffix)

        if len(cpus) and len(cpus) < count_all_cpus():
            name = '%s_%s' % (name, '_'.join([str(c) for c in cpus]))
        self._running_intel_pstate = False
        self._initial_perf = None
        self._current_perf = None
        self._max_freq = 0
        self._cpus = cpus
        self._available_freqs = set()

        if not self._file_paths:
            logging.debug('time_in_state file not found')

        # assumes cpufreq driver for CPU0 is the same as the others.
        freq_driver = utils.read_one_line(cpufreq_driver)
        if freq_driver == 'intel_pstate':
            logging.debug('intel_pstate driver active')
            self._running_intel_pstate = True
        else:
            _, cpufreq_key_paths = get_cpus_filepaths_for_suffix(cpus,
                                                                 key_suffix)
            for path in cpufreq_key_paths:
                self._available_freqs |= set(int(x) for x in
                                             utils.read_file(path).split())

        super(CPUFreqStats, self).__init__(name=name)


    def _read_stats(self):
        if self._running_intel_pstate:
            aperf = 0
            mperf = 0

            for cpu in self._cpus:
                aperf += utils.rdmsr(self.MSR_IA32_APERF, cpu)
                mperf += utils.rdmsr(self.MSR_IA32_MPERF, cpu)

            # max_freq is supposed to be the same for all CPUs and remain
            # constant throughout. So, we set the entry only once.
            # Note that this is max non-turbo frequency, some CPU can run at
            # higher turbo frequency in some condition.
            if not self._max_freq:
                platform_info = utils.rdmsr(self.MSR_PLATFORM_INFO)
                mul = platform_info >> 8 & 0xff
                bclk = utils.get_intel_bclk_khz()
                self._max_freq = mul * bclk

            if not self._initial_perf:
                self._initial_perf = (aperf, mperf)

            self._current_perf = (aperf, mperf)

        stats = dict((k, 0) for k in self._available_freqs)
        for path in self._file_paths:
            if not os.path.exists(path):
                logging.debug('%s is not found', path)
                continue

            data = utils.read_file(path)
            for line in data.splitlines():
                pair = line.split()
                freq = int(pair[0])
                timeunits = int(pair[1])
                if freq in stats:
                    stats[freq] += timeunits
                else:
                    stats[freq] = timeunits
        return stats


    def _supports_automatic_weighted_average(self):
        return not self._running_intel_pstate


    def _weighted_avg_fn(self):
        if not self._running_intel_pstate:
            return None

        if self._current_perf[1] != self._initial_perf[1]:
            # Avg freq = max_freq * aperf_delta / mperf_delta
            return self._max_freq * \
                float(self._current_perf[0] - self._initial_perf[0]) / \
                (self._current_perf[1] - self._initial_perf[1])
        return 1.0


class CPUCStateStats(AbstractStats):
    """
    Base class for C-state residency statistics
    """
    def __init__(self, name, non_c0_stat=''):
        self._non_c0_stat = non_c0_stat
        super(CPUCStateStats, self).__init__(name=name)


    def to_percent(self, stats):
        """
        Turns a dict with absolute time values into a dict with percentages.
        Ignore the |non_c0_stat_name| which is aggegate stat in the total count.
        """
        total = sum(v for k, v in stats.iteritems() if k != self._non_c0_stat)
        if total == 0:
            return {k: 0 for k in stats}
        return {k: v * 100.0 / total for k, v in stats.iteritems()}


class CPUIdleStats(CPUCStateStats):
    """
    CPU Idle statistics (refresh() will not work with incremental=False!)
    """
    # TODO (snanda): Handle changes in number of c-states due to events such
    # as ac <-> battery transitions.
    # TODO (snanda): Handle non-S0 states. Time spent in suspend states is
    # currently not factored out.
    def __init__(self, cpus=None):
        name = 'cpuidle'
        cpuidle_suffix = 'cpuidle'
        if not cpus:
            cpus = get_online_cpus()
        cpus, self._cpus = get_cpus_filepaths_for_suffix(cpus, cpuidle_suffix)
        if len(cpus) and len(cpus) < count_all_cpus():
            name = '%s_%s' % (name, '_'.join([str(c) for c in cpus]))
        super(CPUIdleStats, self).__init__(name=name, non_c0_stat='non-C0')


    def _read_stats(self):
        cpuidle_stats = collections.defaultdict(int)
        epoch_usecs = int(time.time() * 1000 * 1000)
        for cpu in self._cpus:
            state_path = os.path.join(cpu, 'state*')
            states = glob.glob(state_path)
            cpuidle_stats['C0'] += epoch_usecs

            for state in states:
                name = utils.read_one_line(os.path.join(state, 'name'))
                latency = utils.read_one_line(os.path.join(state, 'latency'))

                if not int(latency) and name == 'POLL':
                    # C0 state. Kernel stats aren't right, so calculate by
                    # subtracting all other states from total time (using epoch
                    # timer since we calculate differences in the end anyway).
                    # NOTE: Only x86 lists C0 under cpuidle, ARM does not.
                    continue

                usecs = int(utils.read_one_line(os.path.join(state, 'time')))
                cpuidle_stats['C0'] -= usecs

                if name == '<null>':
                    # Kernel race condition that can happen while a new C-state
                    # gets added (e.g. AC->battery). Don't know the 'name' of
                    # the state yet, but its 'time' would be 0 anyway.
                    logging.warning('Read name: <null>, time: %d from %s'
                        % (usecs, state) + '... skipping.')
                    continue

                cpuidle_stats[name] += usecs
                cpuidle_stats['non-C0'] += usecs

        return cpuidle_stats


class CPUPackageStats(CPUCStateStats):
    """
    Package C-state residency statistics for modern Intel CPUs.
    """

    ATOM         =              {'C2': 0x3F8, 'C4': 0x3F9, 'C6': 0x3FA}
    NEHALEM      =              {'C3': 0x3F8, 'C6': 0x3F9, 'C7': 0x3FA}
    SANDY_BRIDGE = {'C2': 0x60D, 'C3': 0x3F8, 'C6': 0x3F9, 'C7': 0x3FA}
    SILVERMONT   = {'C6': 0x3FA}
    GOLDMONT     = {'C2': 0x60D, 'C3': 0x3F8, 'C6': 0x3F9,'C10': 0x632}
    BROADWELL    = {'C2': 0x60D, 'C3': 0x3F8, 'C6': 0x3F9, 'C7': 0x3FA,
                                 'C8': 0x630, 'C9': 0x631,'C10': 0x632}

    def __init__(self):
        def _get_platform_states():
            """
            Helper to decide what set of microarchitecture-specific MSRs to use.

            Returns: dict that maps C-state name to MSR address, or None.
            """
            cpu_uarch = utils.get_intel_cpu_uarch()

            return {
                # model groups pulled from Intel SDM, volume 4
                # Group same package cstate using the older uarch name
                #
                # TODO(harry.pan): As the keys represent microarchitecture
                # names, we could consider to rename the PC state groups
                # to avoid ambiguity.
                'Airmont':      self.SILVERMONT,
                'Atom':         self.ATOM,
                'Broadwell':    self.BROADWELL,
                'Goldmont':     self.GOLDMONT,
                'Haswell':      self.SANDY_BRIDGE,
                'Ivy Bridge':   self.SANDY_BRIDGE,
                'Ivy Bridge-E': self.SANDY_BRIDGE,
                'Kaby Lake':    self.BROADWELL,
                'Nehalem':      self.NEHALEM,
                'Sandy Bridge': self.SANDY_BRIDGE,
                'Silvermont':   self.SILVERMONT,
                'Skylake':      self.BROADWELL,
                'Westmere':     self.NEHALEM,
                }.get(cpu_uarch, None)

        self._platform_states = _get_platform_states()
        super(CPUPackageStats, self).__init__(name='cpupkg',
                                              non_c0_stat='non-C0_C1')


    def _read_stats(self):
        packages = set()
        template = '/sys/devices/system/cpu/cpu%s/topology/physical_package_id'
        if not self._platform_states:
            return {}
        stats = dict((state, 0) for state in self._platform_states)
        stats['C0_C1'] = 0
        stats['non-C0_C1'] = 0

        for cpu in os.listdir('/dev/cpu'):
            if not os.path.exists(template % cpu):
                continue
            package = utils.read_one_line(template % cpu)
            if package in packages:
                continue
            packages.add(package)

            stats['C0_C1'] += utils.rdmsr(0x10, cpu) # TSC
            for (state, msr) in self._platform_states.iteritems():
                ticks = utils.rdmsr(msr, cpu)
                stats[state] += ticks
                stats['non-C0_C1'] += ticks
                stats['C0_C1'] -= ticks

        return stats


class DevFreqStats(AbstractStats):
    """
    Devfreq device frequency stats.
    """

    _DIR = '/sys/class/devfreq'


    def __init__(self, f):
        """Constructs DevFreqStats Object that track frequency stats
        for the path of the given Devfreq device.

        The frequencies for devfreq devices are listed in Hz.

        Args:
            path: the path to the devfreq device

        Example:
            /sys/class/devfreq/dmc
        """
        self._path = os.path.join(self._DIR, f)
        if not os.path.exists(self._path):
            raise error.TestError('DevFreqStats: devfreq device does not exist')

        fname = os.path.join(self._path, 'available_frequencies')
        af = utils.read_one_line(fname).strip()
        self._available_freqs = sorted(af.split(), key=int)

        super(DevFreqStats, self).__init__(name=f)

    def _read_stats(self):
        stats = dict((freq, 0) for freq in self._available_freqs)
        fname = os.path.join(self._path, 'trans_stat')

        with open(fname) as fd:
            # The lines that contain the time in each frequency start on the 3rd
            # line, so skip the first 2 lines. The last line contains the number
            # of transitions, so skip that line too.
            # The time in each frequency is at the end of the line.
            freq_pattern = re.compile(r'\d+(?=:)')
            for line in fd.readlines()[2:-1]:
                freq = freq_pattern.search(line)
                if freq and freq.group() in self._available_freqs:
                    stats[freq.group()] = int(line.strip().split()[-1])

        return stats


class GPUFreqStats(AbstractStats):
    """GPU Frequency statistics class.

    TODO(tbroch): add stats for other GPUs
    """

    _MALI_DEV = '/sys/class/misc/mali0/device'
    _MALI_EVENTS = ['mali_dvfs:mali_dvfs_set_clock']
    _MALI_TRACE_CLK_RE = \
            r'kworker.* (\d+\.\d+): mali_dvfs_set_clock: frequency=(\d+)\d{6}'

    _I915_ROOT = '/sys/kernel/debug/dri/0'
    _I915_EVENTS = ['i915:intel_gpu_freq_change']
    _I915_CLKS_FILES = ['i915_cur_delayinfo', 'i915_frequency_info']
    _I915_TRACE_CLK_RE = \
            r'kworker.* (\d+\.\d+): intel_gpu_freq_change: new_freq=(\d+)'
    _I915_CUR_FREQ_RE = r'CAGF:\s+(\d+)MHz'
    _I915_MIN_FREQ_RE = r'Lowest \(RPN\) frequency:\s+(\d+)MHz'
    _I915_MAX_FREQ_RE = r'Max non-overclocked \(RP0\) frequency:\s+(\d+)MHz'
    # There are 6 frequency steps per 100 MHz
    _I915_FREQ_STEPS = [0, 17, 33, 50, 67, 83]

    _gpu_type = None


    def _get_mali_freqs(self):
        """Get mali clocks based on kernel version.

        For 3.8-3.18:
            # cat /sys/class/misc/mali0/device/clock
            100000000
            # cat /sys/class/misc/mali0/device/available_frequencies
            100000000
            160000000
            266000000
            350000000
            400000000
            450000000
            533000000
            533000000

        For 4.4+:
            Tracked in DevFreqStats

        Returns:
          cur_mhz: string of current GPU clock in mhz
        """
        cur_mhz = None
        fqs = []

        fname = os.path.join(self._MALI_DEV, 'clock')
        if os.path.exists(fname):
            cur_mhz = str(int(int(utils.read_one_line(fname).strip()) / 1e6))
            fname = os.path.join(self._MALI_DEV, 'available_frequencies')
            with open(fname) as fd:
                for ln in fd.readlines():
                    freq = int(int(ln.strip()) / 1e6)
                    fqs.append(str(freq))
                fqs.sort()

        self._freqs = fqs
        return cur_mhz


    def __init__(self, incremental=False):


        min_mhz = None
        max_mhz = None
        cur_mhz = None
        events = None
        i915_path = None
        self._freqs = []
        self._prev_sample = None
        self._trace = None

        if os.path.exists(self._MALI_DEV) and \
           not os.path.exists(os.path.join(self._MALI_DEV, "devfreq")):
            self._set_gpu_type('mali')
        else:
            for file_name in self._I915_CLKS_FILES:
                full_path = os.path.join(self._I915_ROOT, file_name)
                if os.path.exists(full_path):
                    self._set_gpu_type('i915')
                    i915_path = full_path
                    break
            else:
                # We either don't know how to track GPU stats (yet) or the stats
                # are tracked in DevFreqStats.
                self._set_gpu_type(None)

        logging.debug("gpu_type is %s", self._gpu_type)

        if self._gpu_type is 'mali':
            events = self._MALI_EVENTS
            cur_mhz = self._get_mali_freqs()
            if self._freqs:
                min_mhz = self._freqs[0]
                max_mhz = self._freqs[-1]

        elif self._gpu_type is 'i915':
            events = self._I915_EVENTS
            with open(i915_path) as fd:
                for ln in fd.readlines():
                    logging.debug("ln = %s", ln)
                    result = re.findall(self._I915_CUR_FREQ_RE, ln)
                    if result:
                        cur_mhz = result[0]
                        continue
                    result = re.findall(self._I915_MIN_FREQ_RE, ln)
                    if result:
                        min_mhz = result[0]
                        continue
                    result = re.findall(self._I915_MAX_FREQ_RE, ln)
                    if result:
                        max_mhz = result[0]
                        continue
                if min_mhz and max_mhz:
                    for i in xrange(int(min_mhz), int(max_mhz) + 1):
                        if i % 100 in self._I915_FREQ_STEPS:
                            self._freqs.append(str(i))

        logging.debug("cur_mhz = %s, min_mhz = %s, max_mhz = %s", cur_mhz,
                      min_mhz, max_mhz)

        if cur_mhz and min_mhz and max_mhz:
            self._trace = kernel_trace.KernelTrace(events=events)

        # Not all platforms or kernel versions support tracing.
        if not self._trace or not self._trace.is_tracing():
            logging.warning("GPU frequency tracing not enabled.")
        else:
            self._prev_sample = (cur_mhz, self._trace.uptime_secs())
            logging.debug("Current GPU freq: %s", cur_mhz)
            logging.debug("All GPU freqs: %s", self._freqs)

        super(GPUFreqStats, self).__init__(name='gpu', incremental=incremental)


    @classmethod
    def _set_gpu_type(cls, gpu_type):
        cls._gpu_type = gpu_type


    def _read_stats(self):
        if self._gpu_type:
            return getattr(self, "_%s_read_stats" % self._gpu_type)()
        return {}


    def _trace_read_stats(self, regexp):
        """Read GPU stats from kernel trace outputs.

        Args:
            regexp: regular expression to match trace output for frequency

        Returns:
            Dict with key string in mhz and val float in seconds.
        """
        if not self._prev_sample:
            return {}

        stats = dict((k, 0.0) for k in self._freqs)
        results = self._trace.read(regexp=regexp)
        for (tstamp_str, freq) in results:
            tstamp = float(tstamp_str)

            # do not reparse lines in trace buffer
            if tstamp <= self._prev_sample[1]:
                continue
            delta = tstamp - self._prev_sample[1]
            logging.debug("freq:%s tstamp:%f - %f delta:%f",
                          self._prev_sample[0],
                          tstamp, self._prev_sample[1],
                          delta)
            stats[self._prev_sample[0]] += delta
            self._prev_sample = (freq, tstamp)

        # Do last record
        delta = self._trace.uptime_secs() - self._prev_sample[1]
        logging.debug("freq:%s tstamp:uptime - %f delta:%f",
                      self._prev_sample[0],
                      self._prev_sample[1], delta)
        stats[self._prev_sample[0]] += delta

        logging.debug("GPU freq percents:%s", stats)
        return stats


    def _mali_read_stats(self):
        """Read Mali GPU stats

        Frequencies are reported in Hz, so use a regex that drops the last 6
        digits.

        Output in trace looks like this:

            kworker/u:24-5220  [000] .... 81060.329232: mali_dvfs_set_clock: frequency=400
            kworker/u:24-5220  [000] .... 81061.830128: mali_dvfs_set_clock: frequency=350

        Returns:
            Dict with frequency in mhz as key and float in seconds for time
              spent at that frequency.
        """
        return self._trace_read_stats(self._MALI_TRACE_CLK_RE)


    def _i915_read_stats(self):
        """Read i915 GPU stats.

        Output looks like this (kernel >= 3.8):

          kworker/u:0-28247 [000] .... 259391.579610: intel_gpu_freq_change: new_freq=400
          kworker/u:0-28247 [000] .... 259391.581797: intel_gpu_freq_change: new_freq=350

        Returns:
            Dict with frequency in mhz as key and float in seconds for time
              spent at that frequency.
        """
        return self._trace_read_stats(self._I915_TRACE_CLK_RE)


    def _supports_automatic_weighted_average(self):
        return self._gpu_type is not None


class USBSuspendStats(AbstractStats):
    """
    USB active/suspend statistics (over all devices)
    """
    # TODO (snanda): handle hot (un)plugging of USB devices
    # TODO (snanda): handle duration counters wraparound

    def __init__(self):
        usb_stats_path = '/sys/bus/usb/devices/*/power'
        self._file_paths = glob.glob(usb_stats_path)
        if not self._file_paths:
            logging.debug('USB stats path not found')
        super(USBSuspendStats, self).__init__(name='usb')


    def _read_stats(self):
        usb_stats = {'active': 0, 'suspended': 0}

        for path in self._file_paths:
            active_duration_path = os.path.join(path, 'active_duration')
            total_duration_path = os.path.join(path, 'connected_duration')

            if not os.path.exists(active_duration_path) or \
               not os.path.exists(total_duration_path):
                logging.debug('duration paths do not exist for: %s', path)
                continue

            active = int(utils.read_file(active_duration_path))
            total = int(utils.read_file(total_duration_path))
            logging.debug('device %s active for %.2f%%',
                          path, active * 100.0 / total)

            usb_stats['active'] += active
            usb_stats['suspended'] += total - active

        return usb_stats


def get_cpu_sibling_groups():
    """
    Get CPU core groups in HMP systems.

    In systems with both small core and big core,
    returns groups of small and big sibling groups.
    """
    siblings_suffix = 'topology/core_siblings_list'
    sibling_groups = []
    cpus_processed = set()
    cpus, sibling_file_paths = get_cpus_filepaths_for_suffix(get_online_cpus(),
                                                             siblings_suffix)
    for c, siblings_path in zip(cpus, sibling_file_paths):
        if c in cpus_processed:
            # This cpu is already part of a sibling group. Skip.
            continue
        siblings_data = utils.read_file(siblings_path)
        sibling_group = set()
        for sibling_entry in siblings_data.split(','):
            entry_data = sibling_entry.split('-')
            sibling_start = sibling_end = int(entry_data[0])
            if len(entry_data) > 1:
              sibling_end = int(entry_data[1])
            siblings = set(range(sibling_start, sibling_end + 1))
            sibling_group |= siblings
        cpus_processed |= sibling_group
        sibling_groups.append(frozenset(sibling_group))
    return tuple(sibling_groups)


def get_available_cpu_stats():
    """Return CPUFreq/CPUIdleStats groups by big-small siblings groups."""
    ret = [CPUPackageStats()]
    cpu_sibling_groups = get_cpu_sibling_groups()
    if not cpu_sibling_groups:
        ret.append(CPUFreqStats())
        ret.append(CPUIdleStats())
    for cpu_group in cpu_sibling_groups:
        ret.append(CPUFreqStats(cpu_group))
        ret.append(CPUIdleStats(cpu_group))
    return ret


class StatoMatic(object):
    """Class to aggregate and monitor a bunch of power related statistics."""
    def __init__(self):
        self._start_uptime_secs = kernel_trace.KernelTrace.uptime_secs()
        self._astats = [USBSuspendStats(), GPUFreqStats(incremental=False)]
        self._astats.extend(get_available_cpu_stats())
        if os.path.isdir(DevFreqStats._DIR):
            self._astats.extend([DevFreqStats(f) for f in \
                                 os.listdir(DevFreqStats._DIR)])

        self._disk = DiskStateLogger()
        self._disk.start()


    def publish(self):
        """Publishes results of various statistics gathered.

        Returns:
            dict with
              key = string 'percent_<name>_<key>_time'
              value = float in percent
        """
        results = {}
        tot_secs = kernel_trace.KernelTrace.uptime_secs() - \
            self._start_uptime_secs
        for stat_obj in self._astats:
            percent_stats = stat_obj.refresh()
            logging.debug("pstats = %s", percent_stats)
            if stat_obj.name is 'gpu':
                # TODO(tbroch) remove this once GPU freq stats have proved
                # reliable
                stats_secs = sum(stat_obj._stats.itervalues())
                if stats_secs < (tot_secs * 0.9) or \
                        stats_secs > (tot_secs * 1.1):
                    logging.warning('%s stats dont look right.  Not publishing.',
                                 stat_obj.name)
                    continue
            new_res = {}
            AbstractStats.format_results_percent(new_res, stat_obj.name,
                                                 percent_stats)
            wavg = stat_obj.weighted_average()
            if wavg:
                AbstractStats.format_results_wavg(new_res, stat_obj.name, wavg)

            results.update(new_res)

        new_res = {}
        if self._disk.get_error():
            new_res['disk_logging_error'] = str(self._disk.get_error())
        else:
            AbstractStats.format_results_percent(new_res, 'disk',
                                                 self._disk.result())
        results.update(new_res)

        return results


class PowerMeasurement(object):
    """Class to measure power.

    Public attributes:
        domain: String name of the power domain being measured.  Example is
          'system' for total system power

    Public methods:
        refresh: Performs any power/energy sampling and calculation and returns
            power as float in watts.  This method MUST be implemented in
            subclass.
    """

    def __init__(self, domain):
        """Constructor."""
        self.domain = domain


    def refresh(self):
        """Performs any power/energy sampling and calculation.

        MUST be implemented in subclass

        Returns:
            float, power in watts.
        """
        raise NotImplementedError("'refresh' method should be implemented in "
                                  "subclass.")


def parse_power_supply_info():
    """Parses power_supply_info command output.

    Command output from power_manager ( tools/power_supply_info.cc ) looks like
    this:

        Device: Line Power
          path:               /sys/class/power_supply/cros_ec-charger
          ...
        Device: Battery
          path:               /sys/class/power_supply/sbs-9-000b
          ...

    """
    rv = collections.defaultdict(dict)
    dev = None
    for ln in utils.system_output('power_supply_info').splitlines():
        logging.debug("psu: %s", ln)
        result = re.findall(r'^Device:\s+(.*)', ln)
        if result:
            dev = result[0]
            continue
        result = re.findall(r'\s+(.+):\s+(.+)', ln)
        if result and dev:
            kname = re.findall(r'(.*)\s+\(\w+\)', result[0][0])
            if kname:
                rv[dev][kname[0]] = result[0][1]
            else:
                rv[dev][result[0][0]] = result[0][1]

    return rv


class SystemPower(PowerMeasurement):
    """Class to measure system power.

    TODO(tbroch): This class provides a subset of functionality in BatteryStat
    in hopes of minimizing power draw.  Investigate whether its really
    significant and if not, deprecate.

    Private Attributes:
      _voltage_file: path to retrieve voltage in uvolts
      _current_file: path to retrieve current in uamps
    """

    def __init__(self, battery_dir):
        """Constructor.

        Args:
            battery_dir: path to dir containing the files to probe and log.
                usually something like /sys/class/power_supply/BAT0/
        """
        super(SystemPower, self).__init__('system')
        # Files to log voltage and current from
        self._voltage_file = os.path.join(battery_dir, 'voltage_now')
        self._current_file = os.path.join(battery_dir, 'current_now')


    def refresh(self):
        """refresh method.

        See superclass PowerMeasurement for details.
        """
        keyvals = parse_power_supply_info()
        return float(keyvals['Battery']['energy rate'])


class CheckpointLogger(object):
    """Class to log checkpoint data.

    Public attributes:
        checkpoint_data: dictionary of (tname, tlist).
            tname: String of testname associated with these time intervals
            tlist: list of tuples.  Tuple contains:
                tstart: Float of time when subtest started
                tend: Float of time when subtest ended

    Public methods:
        start: records a start timestamp
        checkpoint
        checkblock
        save_checkpoint_data
        load_checkpoint_data

    Static methods:
        load_checkpoint_data_static

    Private attributes:
       _start_time: start timestamp for checkpoint logger
    """

    def __init__(self):
        self.checkpoint_data = collections.defaultdict(list)
        self.start()

    # If multiple MeasurementLoggers call start() on the same CheckpointLogger,
    # the latest one will register start time.
    def start(self):
        """Set start time for CheckpointLogger."""
        self._start_time = time.time()

    @contextlib.contextmanager
    def checkblock(self, tname=''):
        """Check point for the following block with test tname.

        Args:
            tname: String of testname associated with this time interval
        """
        start_time = time.time()
        yield
        self.checkpoint(tname, start_time)

    def checkpoint(self, tname='', tstart=None, tend=None):
        """Check point the times in seconds associated with test tname.

        Args:
            tname: String of testname associated with this time interval
            tstart: Float in seconds of when tname test started. Should be based
                off time.time(). If None, use start timestamp for the checkpoint
                logger.
            tend: Float in seconds of when tname test ended. Should be based
                off time.time(). If None, then value computed in the method.
        """
        if not tstart and self._start_time:
            tstart = self._start_time
        if not tend:
            tend = time.time()
        self.checkpoint_data[tname].append((tstart, tend))
        logging.info('Finished test "%s" between timestamps [%s, %s]',
                     tname, tstart, tend)

    def convert_relative(self, start_time=None):
        """Convert data from power_status.CheckpointLogger object to relative
        checkpoint data dictionary. Timestamps are converted to time in seconds
        since the test started.

        Args:
            start_time: Float in seconds of the desired start time reference.
                Should be based off time.time(). If None, use start timestamp
                for the checkpoint logger.
        """
        if start_time is None:
            start_time = self._start_time

        checkpoint_dict = {}
        for tname, tlist in self.checkpoint_data.iteritems():
            checkpoint_dict[tname] = [(tstart - start_time, tend - start_time)
                    for tstart, tend in tlist]

        return checkpoint_dict

    def save_checkpoint_data(self, resultsdir, fname=CHECKPOINT_LOG_DEFAULT_FNAME):
        """Save checkpoint data.

        Args:
            resultsdir: String, directory to write results to
            fname: String, name of file to write results to
        """
        fname = os.path.join(resultsdir, fname)
        with file(fname, 'wt') as f:
            json.dump(self.checkpoint_data, f, indent=4, separators=(',', ': '))

    def load_checkpoint_data(self, resultsdir,
                             fname=CHECKPOINT_LOG_DEFAULT_FNAME):
        """Load checkpoint data.

        Args:
            resultsdir: String, directory to load results from
            fname: String, name of file to load results from
        """
        fname = os.path.join(resultsdir, fname)
        try:
            with open(fname, 'r') as f:
                self.checkpoint_data = json.load(f,
                                                 object_hook=to_checkpoint_data)
                # Set start time to the earliest start timestamp in file.
                self._start_time = min(
                        ts_pair[0] for ts_pair in itertools.chain.from_iterable(
                                self.checkpoint_data.itervalues()))
        except Exception as exc:
            logging.warning('Failed to load checkpoint data from json file %s, '
                            'see exception: %s', fname, exc)

    @staticmethod
    def load_checkpoint_data_static(resultsdir,
                                    fname=CHECKPOINT_LOG_DEFAULT_FNAME):
        """Load checkpoint data.

        Args:
            resultsdir: String, directory to load results from
            fname: String, name of file to load results from
        """
        fname = os.path.join(resultsdir, fname)
        with file(fname, 'r') as f:
            checkpoint_data = json.load(f)
        return checkpoint_data


def to_checkpoint_data(json_dict):
    """Helper method to translate json object into CheckpointLogger format.

    Args:
        json_dict: a json object in the format of python dict
    Returns:
        a defaultdict in CheckpointLogger data format
    """
    checkpoint_data = collections.defaultdict(list)
    for tname, tlist in json_dict.iteritems():
        checkpoint_data[tname].extend([tuple(ts_pair) for ts_pair in tlist])
    return checkpoint_data


def get_checkpoint_logger_from_file(resultsdir,
                                    fname=CHECKPOINT_LOG_DEFAULT_FNAME):
    """Create a CheckpointLogger and load checkpoint data from file.

    Args:
        resultsdir: String, directory to load results from
        fname: String, name of file to load results from
    Returns:
        CheckpointLogger with data from file
    """
    checkpoint_logger = CheckpointLogger()
    checkpoint_logger.load_checkpoint_data(resultsdir, fname)
    return checkpoint_logger


class MeasurementLogger(threading.Thread):
    """A thread that logs measurement readings.

    Example code snippet:
        my_logger = MeasurementLogger([Measurement1, Measurement2])
        my_logger.start()
        for testname in tests:
            # Option 1: use checkblock
            with my_logger.checkblock(testname):
               # run the test method for testname

            # Option 2: use checkpoint
            start_time = time.time()
            # run the test method for testname
            my_logger.checkpoint(testname, start_time)

        keyvals = my_logger.calc()

    or using CheckpointLogger:
        checkpoint_logger = CheckpointLogger()
        my_logger = MeasurementLogger([Measurement1, Measurement2],
                                      checkpoint_logger)
        my_logger.start()
        for testname in tests:
            # Option 1: use checkblock
            with checkpoint_logger.checkblock(testname):
               # run the test method for testname

            # Option 2: use checkpoint
            start_time = time.time()
            # run the test method for testname
            checkpoint_logger.checkpoint(testname, start_time)

        keyvals = my_logger.calc()

    Public attributes:
        seconds_period: float, probing interval in seconds.
        readings: list of lists of floats of measurements.
        times: list of floats of time (since Epoch) of when measurements
            occurred.  len(time) == len(readings).
        done: flag to stop the logger.
        domains: list of  domain strings being measured

    Public methods:
        run: launches the thread to gather measurements
        refresh: perform data samplings for every measurements
        calc: calculates
        save_results:

    Private attributes:
        _measurements: list of Measurement objects to be sampled.
        _checkpoint_data: dictionary of (tname, tlist).
            tname: String of testname associated with these time intervals
            tlist: list of tuples.  Tuple contains:
                tstart: Float of time when subtest started
                tend: Float of time when subtest ended
        _results: list of results tuples.  Tuple contains:
            prefix: String of subtest
            mean: Float of mean  in watts
            std: Float of standard deviation of measurements
            tstart: Float of time when subtest started
            tend: Float of time when subtest ended
    """
    def __init__(self, measurements, seconds_period=1.0, checkpoint_logger=None):
        """Initialize a logger.

        Args:
            _measurements: list of Measurement objects to be sampled.
            seconds_period: float, probing interval in seconds.  Default 1.0
        """
        threading.Thread.__init__(self)

        self.seconds_period = seconds_period

        self.readings = []
        self.times = []

        self.domains = []
        self._measurements = measurements
        for meas in self._measurements:
            self.domains.append(meas.domain)

        self._checkpoint_logger = \
            checkpoint_logger if checkpoint_logger else CheckpointLogger()

        self.done = False

    def start(self):
        self._checkpoint_logger.start()
        super(MeasurementLogger, self).start()

    def refresh(self):
        """Perform data samplings for every measurements.

        Returns:
            list of sampled data for every measurements.
        """
        readings = []
        for meas in self._measurements:
            readings.append(meas.refresh())
        return readings

    def run(self):
        """Threads run method."""
        loop = 0
        start_time = time.time()
        while(not self.done):
            # TODO (dbasehore): We probably need proper locking in this file
            # since there have been race conditions with modifying and accessing
            # data.
            self.readings.append(self.refresh())
            current_time = time.time()
            self.times.append(current_time)
            loop += 1
            next_measurement_time = start_time + loop * self.seconds_period
            time.sleep(next_measurement_time - current_time)

    @contextlib.contextmanager
    def checkblock(self, tname=''):
        """Check point for the following block with test tname.

        Args:
            tname: String of testname associated with this time interval
        """
        start_time = time.time()
        yield
        self.checkpoint(tname, start_time)

    def checkpoint(self, tname='', tstart=None, tend=None):
        """Just a thin method calling the CheckpointLogger checkpoint method.

        Args:
           tname: String of testname associated with this time interval
           tstart: Float in seconds of when tname test started.  Should be based
                off time.time()
           tend: Float in seconds of when tname test ended.  Should be based
                off time.time().  If None, then value computed in the method.
        """
        self._checkpoint_logger.checkpoint(tname, tstart, tend)

    # TODO(seankao): It might be useful to pull this method to CheckpointLogger,
    # to allow checkpoint usage without an explicit MeasurementLogger.
    def calc(self, mtype=None):
        """Calculate average measurement during each of the sub-tests.

        Method performs the following steps:
            1. Signals the thread to stop running.
            2. Calculates mean, max, min, count on the samples for each of the
               measurements.
            3. Stores results to be written later.
            4. Creates keyvals for autotest publishing.

        Args:
            mtype: string of measurement type.  For example:
                   pwr == power
                   temp == temperature
        Returns:
            dict of keyvals suitable for autotest results.
        """
        if not mtype:
            mtype = 'meas'

        t = numpy.array(self.times)
        keyvals = {}
        results  = [('domain', 'mean', 'std', 'duration (s)', 'start ts',
                     'end ts')]
        # TODO(coconutruben): ensure that values is meaningful i.e. go through
        # the Loggers and add a unit attribute to each so that the raw
        # data is readable.
        raw_results = [('domain', 'values (%s)' % mtype)]

        if not self.done:
            self.done = True
        # times 2 the sleep time in order to allow for readings as well.
        self.join(timeout=self.seconds_period * 2)

        if not self._checkpoint_logger.checkpoint_data:
            self._checkpoint_logger.checkpoint()

        for i, domain_readings in enumerate(zip(*self.readings)):
            meas = numpy.array(domain_readings)
            domain = self.domains[i]

            for tname, tlist in self._checkpoint_logger.checkpoint_data.iteritems():
                if tname:
                    prefix = '%s_%s' % (tname, domain)
                else:
                    prefix = domain
                keyvals[prefix+'_duration'] = 0
                # Select all readings taken between tstart and tend
                # timestamps in tlist.
                masks = []
                for tstart, tend in tlist:
                    keyvals[prefix+'_duration'] += tend - tstart
                    # Try block just in case
                    # code.google.com/p/chromium/issues/detail?id=318892
                    # is not fixed.
                    try:
                        masks.append(numpy.logical_and(tstart < t, t < tend))
                    except ValueError, e:
                        logging.debug('Error logging measurements: %s', str(e))
                        logging.debug('timestamps %d %s', t.len, t)
                        logging.debug('timestamp start, end %f %f', tstart, tend)
                        logging.debug('measurements %d %s', meas.len, meas)
                mask = numpy.logical_or.reduce(masks)
                meas_array = meas[mask]

                # If sub-test terminated early, avoid calculating avg, std and
                # min
                if not meas_array.size:
                    continue
                meas_mean = meas_array.mean()
                meas_std = meas_array.std()

                # Results list can be used for pretty printing and saving as csv
                # TODO(seankao): new results format?
                result = (prefix, meas_mean, meas_std)
                for tstart, tend in tlist:
                    result = result + (tend - tstart, tstart, tend)
                results.append(result)
                raw_results.append((prefix,) + tuple(meas_array.tolist()))

                keyvals[prefix + '_' + mtype + '_avg'] = meas_mean
                keyvals[prefix + '_' + mtype + '_cnt'] = meas_array.size
                keyvals[prefix + '_' + mtype + '_max'] = meas_array.max()
                keyvals[prefix + '_' + mtype + '_min'] = meas_array.min()
                keyvals[prefix + '_' + mtype + '_std'] = meas_std
        self._results = results
        self._raw_results = raw_results
        return keyvals


    def save_results(self, resultsdir, fname_prefix=None):
        """Save computed results in a nice tab-separated format.
        This is useful for long manual runs.

        Args:
            resultsdir: String, directory to write results to
            fname_prefix: prefix to use for fname. If provided outfiles
                          will be [fname]_[raw|summary].txt
        """
        if not fname_prefix:
          fname_prefix = 'meas_results_%.0f' % time.time()
        fname = '%s_summary.txt' % fname_prefix
        raw_fname = fname.replace('summary', 'raw')
        for name, data in [(fname, self._results),
                           (raw_fname, self._raw_results)]:
          with open(os.path.join(resultsdir, name), 'wt') as f:
              # First row contains the headers
              f.write('%s\n' % '\t'.join(data[0]))
              for row in data[1:]:
                  # First column name, rest are numbers. See _calc_power()
                  fmt_row = [row[0]] + ['%.2f' % x for x in row[1:]]
                  f.write('%s\n' % '\t'.join(fmt_row))


class CPUStatsLogger(MeasurementLogger):
    """Class to measure CPU Frequency and CPU Idle Stats.

    CPUStatsLogger derived from MeasurementLogger class but overload data
    samplings method because MeasurementLogger assumed that each sampling is
    independent to each other. However, in this case it is not. For example,
    CPU time spent in C0 state is measure by time not spent in all other states.

    CPUStatsLogger also collects the weight average in each time period if the
    underlying AbstractStats support weight average function.

    Private attributes:
       _stats: list of CPU AbstractStats objects to be sampled.
       _refresh_count: number of times refresh() has been called.
       _last_wavg: dict of wavg when refresh() was last called.
    """
    def __init__(self, seconds_period=1.0, checkpoint_logger=None):
        """Initialize a CPUStatsLogger.

        Args:
            seconds_period: float, probing interval in seconds.  Default 1.0
        """
        # We don't use measurements since CPU stats can't measure separately.
        super(CPUStatsLogger, self).__init__([], seconds_period, checkpoint_logger)

        self._stats = get_available_cpu_stats()
        self._stats.append(GPUFreqStats())
        self.domains = []
        for stat in self._stats:
            self.domains.extend([stat.name + '_' + str(state_name)
                                 for state_name in stat.refresh()])
            if stat.weighted_average():
                self.domains.append('wavg_' + stat.name)
        self._refresh_count = 0
        self._last_wavg = collections.defaultdict(int)

    def refresh(self):
        self._refresh_count += 1
        count = self._refresh_count
        ret = []
        for stat in self._stats:
            ret.extend(stat.refresh().values())
            wavg = stat.weighted_average()
            if wavg:
                if stat.incremental:
                    last_wavg = self._last_wavg[stat.name]
                    self._last_wavg[stat.name] = wavg
                    # Calculate weight average in this period using current
                    # total weight average and last total weight average.
                    # The result will lose some precision with higher number of
                    # count but still good enough for 11 significant digits even
                    # if we logged the data every 1 second for a day.
                    ret.append(wavg * count - last_wavg * (count - 1))
                else:
                    ret.append(wavg)
        return ret

    def save_results(self, resultsdir, fname_prefix=None):
        if not fname_prefix:
            fname_prefix = 'cpu_results_%.0f' % time.time()
        super(CPUStatsLogger, self).save_results(resultsdir, fname_prefix)


class PowerLogger(MeasurementLogger):
    """Class to measure power consumption.
    """
    def save_results(self, resultsdir, fname_prefix=None):
        if not fname_prefix:
            fname_prefix = 'power_results_%.0f' % time.time()
        super(PowerLogger, self).save_results(resultsdir, fname_prefix)


    def calc(self, mtype='pwr'):
        return super(PowerLogger, self).calc(mtype)


class TempMeasurement(object):
    """Class to measure temperature.

    Public attributes:
        domain: String name of the temperature domain being measured.  Example is
          'cpu' for cpu temperature

    Private attributes:
        _path: Path to temperature file to read ( in millidegrees Celsius )

    Public methods:
        refresh: Performs any temperature sampling and calculation and returns
            temperature as float in degrees Celsius.
    """
    def __init__(self, domain, path):
        """Constructor."""
        self.domain = domain
        self._path = path


    def refresh(self):
        """Performs temperature

        Returns:
            float, temperature in degrees Celsius
        """
        return int(utils.read_one_line(self._path)) / 1000.


class BatteryTempMeasurement(TempMeasurement):
    """Class to measure battery temperature."""
    def __init__(self):
        super(BatteryTempMeasurement, self).__init__('battery', 'battery_temp')


    def refresh(self):
        """Perform battery temperature reading.

        Returns:
            float, temperature in degrees Celsius.
        """
        result = utils.run(self._path, timeout=5, ignore_status=True)
        return float(result.stdout)


def has_battery_temp():
    """Determine if DUT can provide battery temperature.

    Returns:
        Boolean, True if battery temperature available.  False otherwise.
    """
    if not power_utils.has_battery():
        return False

    btemp = BatteryTempMeasurement()
    try:
        btemp.refresh()
    except ValueError:
        return False

    return True


class TempLogger(MeasurementLogger):
    """A thread that logs temperature readings in millidegrees Celsius."""
    def __init__(self, measurements, seconds_period=30.0, checkpoint_logger=None):
        if not measurements:
            domains = set()
            measurements = []
            tstats = ThermalStatHwmon()
            for kname in tstats.fields:
                match = re.match(r'(\S+)_temp(\d+)_input', kname)
                if not match:
                    continue
                domain = match.group(1) + '-t' + match.group(2)
                fpath = tstats.fields[kname][0]
                new_meas = TempMeasurement(domain, fpath)
                measurements.append(new_meas)
                domains.add(domain)

            if has_battery_temp():
                measurements.append(BatteryTempMeasurement())

            sysfs_paths = '/sys/class/thermal/thermal_zone*'
            paths = glob.glob(sysfs_paths)
            for path in paths:
                domain_path = os.path.join(path, 'type')
                temp_path = os.path.join(path, 'temp')

                domain = utils.read_one_line(domain_path)

                # Skip when thermal_zone and hwmon have same domain.
                if domain in domains:
                    continue

                domain = domain.replace(' ', '_')
                new_meas = TempMeasurement(domain, temp_path)
                measurements.append(new_meas)

        super(TempLogger, self).__init__(measurements, seconds_period, checkpoint_logger)


    def save_results(self, resultsdir, fname_prefix=None):
        if not fname_prefix:
            fname_prefix = 'temp_results_%.0f' % time.time()
        super(TempLogger, self).save_results(resultsdir, fname_prefix)


    def calc(self, mtype='temp'):
        return super(TempLogger, self).calc(mtype)


class DiskStateLogger(threading.Thread):
    """Records the time percentages the disk stays in its different power modes.

    Example code snippet:
        mylogger = power_status.DiskStateLogger()
        mylogger.start()
        result = mylogger.result()

    Public methods:
        start: Launches the thread and starts measurements.
        result: Stops the thread if it's still running and returns measurements.
        get_error: Returns the exception in _error if it exists.

    Private functions:
        _get_disk_state: Returns the disk's current ATA power mode as a string.

    Private attributes:
        _seconds_period: Disk polling interval in seconds.
        _stats: Dict that maps disk states to seconds spent in them.
        _running: Flag that is True as long as the logger should keep running.
        _time: Timestamp of last disk state reading.
        _device_path: The file system path of the disk's device node.
        _error: Contains a TestError exception if an unexpected error occured
    """
    def __init__(self, seconds_period = 5.0, device_path = None):
        """Initializes a logger.

        Args:
            seconds_period: Disk polling interval in seconds. Default 5.0
            device_path: The path of the disk's device node. Default '/dev/sda'
        """
        threading.Thread.__init__(self)
        self._seconds_period = seconds_period
        self._device_path = device_path
        self._stats = {}
        self._running = False
        self._error = None

        result = utils.system_output('rootdev -s')
        # TODO(tbroch) Won't work for emmc storage and will throw this error in
        # keyvals : 'ioctl(SG_IO) error: [Errno 22] Invalid argument'
        # Lets implement something complimentary for emmc
        if not device_path:
            self._device_path = \
                re.sub('(sd[a-z]|mmcblk[0-9]+)p?[0-9]+', '\\1', result)
        logging.debug("device_path = %s", self._device_path)


    def start(self):
        logging.debug("inside DiskStateLogger.start")
        if os.path.exists(self._device_path):
            logging.debug("DiskStateLogger started")
            super(DiskStateLogger, self).start()


    def _get_disk_state(self):
        """Checks the disk's power mode and returns it as a string.

        This uses the SG_IO ioctl to issue a raw SCSI command data block with
        the ATA-PASS-THROUGH command that allows SCSI-to-ATA translation (see
        T10 document 04-262r8). The ATA command issued is CHECKPOWERMODE1,
        which returns the device's current power mode.
        """

        def _addressof(obj):
            """Shortcut to return the memory address of an object as integer."""
            return ctypes.cast(obj, ctypes.c_void_p).value

        scsi_cdb = struct.pack("12B", # SCSI command data block (uint8[12])
                               0xa1, # SCSI opcode: ATA-PASS-THROUGH
                               3 << 1, # protocol: Non-data
                               1 << 5, # flags: CK_COND
                               0, # features
                               0, # sector count
                               0, 0, 0, # LBA
                               1 << 6, # flags: ATA-USING-LBA
                               0xe5, # ATA opcode: CHECKPOWERMODE1
                               0, # reserved
                               0, # control (no idea what this is...)
                              )
        scsi_sense = (ctypes.c_ubyte * 32)() # SCSI sense buffer (uint8[32])
        sgio_header = struct.pack("iiBBHIPPPIIiPBBBBHHiII", # see <scsi/sg.h>
                                  83, # Interface ID magic number (int32)
                                  -1, # data transfer direction: none (int32)
                                  12, # SCSI command data block length (uint8)
                                  32, # SCSI sense data block length (uint8)
                                  0, # iovec_count (not applicable?) (uint16)
                                  0, # data transfer length (uint32)
                                  0, # data block pointer
                                  _addressof(scsi_cdb), # SCSI CDB pointer
                                  _addressof(scsi_sense), # sense buffer pointer
                                  500, # timeout in milliseconds (uint32)
                                  0, # flags (uint32)
                                  0, # pack ID (unused) (int32)
                                  0, # user data pointer (unused)
                                  0, 0, 0, 0, 0, 0, 0, 0, 0, # output params
                                 )
        try:
            with open(self._device_path, 'r') as dev:
                result = fcntl.ioctl(dev, 0x2285, sgio_header)
        except IOError, e:
            raise error.TestError('ioctl(SG_IO) error: %s' % str(e))
        _, _, _, _, status, host_status, driver_status = \
            struct.unpack("4x4xxx2x4xPPP4x4x4xPBxxxHH4x4x4x", result)
        if status != 0x2: # status: CHECK_CONDITION
            raise error.TestError('SG_IO status: %d' % status)
        if host_status != 0:
            raise error.TestError('SG_IO host status: %d' % host_status)
        if driver_status != 0x8: # driver status: SENSE
            raise error.TestError('SG_IO driver status: %d' % driver_status)

        if scsi_sense[0] != 0x72: # resp. code: current error, descriptor format
            raise error.TestError('SENSE response code: %d' % scsi_sense[0])
        if scsi_sense[1] != 0: # sense key: No Sense
            raise error.TestError('SENSE key: %d' % scsi_sense[1])
        if scsi_sense[7] < 14: # additional length (ATA status is 14 - 1 bytes)
            raise error.TestError('ADD. SENSE too short: %d' % scsi_sense[7])
        if scsi_sense[8] != 0x9: # additional descriptor type: ATA Return Status
            raise error.TestError('SENSE descriptor type: %d' % scsi_sense[8])
        if scsi_sense[11] != 0: # errors: none
            raise error.TestError('ATA error code: %d' % scsi_sense[11])

        if scsi_sense[13] == 0x00:
            return 'standby'
        if scsi_sense[13] == 0x80:
            return 'idle'
        if scsi_sense[13] == 0xff:
            return 'active'
        return 'unknown(%d)' % scsi_sense[13]


    def run(self):
        """The Thread's run method."""
        try:
            self._time = time.time()
            self._running = True
            while(self._running):
                time.sleep(self._seconds_period)
                state = self._get_disk_state()
                new_time = time.time()
                if state in self._stats:
                    self._stats[state] += new_time - self._time
                else:
                    self._stats[state] = new_time - self._time
                self._time = new_time
        except error.TestError, e:
            self._error = e
            self._running = False


    def result(self):
        """Stop the logger and return dict with result percentages."""
        if (self._running):
            self._running = False
            self.join(self._seconds_period * 2)
        return AbstractStats.to_percent(self._stats)


    def get_error(self):
        """Returns the _error exception... please only call after result()."""
        return self._error

def parse_pmc_s0ix_residency_info():
    """
    Parses S0ix residency for PMC based Intel systems
    (skylake/kabylake/apollolake), the debugfs paths might be
    different from platform to platform, yet the format is
    unified in microseconds.

    @returns residency in seconds.
    @raises error.TestNAError if the debugfs file not found.
    """
    info_path = None
    for node in ['/sys/kernel/debug/pmc_core/slp_s0_residency_usec',
                 '/sys/kernel/debug/telemetry/s0ix_residency_usec']:
        if os.path.exists(node):
            info_path = node
            break
    if not info_path:
        raise error.TestNAError('S0ix residency file not found')
    return float(utils.read_one_line(info_path)) * 1e-6


class S0ixResidencyStats(object):
    """
    Measures the S0ix residency of a given board over time.
    """
    def __init__(self):
        self._initial_residency = parse_pmc_s0ix_residency_info()

    def get_accumulated_residency_secs(self):
        """
        @returns S0ix Residency since the class has been initialized.
        """
        return parse_pmc_s0ix_residency_info() - self._initial_residency


class DMCFirmwareStats(object):
    """
    Collect DMC firmware stats of Intel based system (SKL+), (APL+).
    """
    # Intel CPUs only transition to DC6 from DC5. https://git.io/vppcG
    DC6_ENTRY_KEY = 'DC5 -> DC6 count'

    def __init__(self):
        self._initial_stat = DMCFirmwareStats._parse_dmc_info()

    def check_fw_loaded(self):
        """Check that DMC firmware is loaded

        @returns boolean of DMC firmware loaded.
        """
        return self._initial_stat['fw loaded']

    def is_dc6_supported(self):
        """Check that DMC support DC6 state."""
        return self.DC6_ENTRY_KEY in self._initial_stat

    def get_accumulated_dc6_entry(self):
        """Check number of DC6 state entry since the class has been initialized.

        @returns number of DC6 state entry.
        """
        if not self.is_dc6_supported():
            return 0

        key = self.DC6_ENTRY_KEY
        current_stat = DMCFirmwareStats._parse_dmc_info()
        return current_stat[key] - self._initial_stat[key]

    @staticmethod
    def _parse_dmc_info():
        """
        Parses DMC firmware info for Intel based systems.

        @returns dictionary of dmc_fw info
        @raises error.TestFail if the debugfs file not found.
        """
        path = '/sys/kernel/debug/dri/0/i915_dmc_info'
        if not os.path.exists(path):
            raise error.TestFail('DMC info file not found.')

        with open(path, 'r') as f:
            lines = [line.strip() for line in f.readlines()]

        # For pre 4.16 kernel. https://git.io/vhThb
        if lines[0] == 'not supported':
            raise error.TestFail('DMC not supported.')

        ret = dict()
        for line in lines:
            key, val = line.rsplit(': ', 1)

            if key == 'fw loaded':
                val = val == 'yes'
            elif re.match(r'DC\d -> DC\d count', key):
                val = int(val)
            ret[key] = val
        return ret


class RC6ResidencyStats(object):
    """
    Collect RC6 residency stats of Intel based system.
    """
    def __init__(self):
        self._rc6_enable_checked = False
        self._initial_stat = self._parse_rc6_residency_info()

    def get_accumulated_residency_secs(self):
        """Check number of RC6 state entry since the class has been initialized.

        @returns int of RC6 residency in seconds since instantiation.
        """
        current_stat = self._parse_rc6_residency_info()
        return (current_stat - self._initial_stat) * 1e-3

    def _is_rc6_enable(self):
        """
        Verified that RC6 is enable.

        @returns Boolean of RC6 enable status.
        @raises error.TestFail if the sysfs file not found.
        """
        path = '/sys/class/drm/card0/power/rc6_enable'
        if not os.path.exists(path):
            raise error.TestFail('RC6 enable file not found.')

        return int(utils.read_one_line(path)) == 1

    def _parse_rc6_residency_info(self):
        """
        Parses RC6 residency info for Intel based systems.

        @returns int of RC6 residency in millisec since boot.
        @raises error.TestFail if the sysfs file not found or RC6 not enabled.
        """
        if not self._rc6_enable_checked:
            if not self._is_rc6_enable():
                raise error.TestFail('RC6 is not enabled.')
            self._rc6_enable_checked = True

        path = '/sys/class/drm/card0/power/rc6_residency_ms'
        if not os.path.exists(path):
            raise error.TestFail('RC6 residency file not found.')

        return int(utils.read_one_line(path))


class PCHPowergatingStats(object):
    """
    Collect PCH powergating status of intel based system.
    """
    PMC_CORE_PATH = '/sys/kernel/debug/pmc_core/pch_ip_power_gating_status'
    TELEMETRY_PATH = '/sys/kernel/debug/telemetry/soc_states'

    def __init__(self):
        self._stat = {}

    def check_s0ix_requirement(self):
        """
        Check PCH powergating status with S0ix requirement.

        @returns list of PCH IP block name that need to be powergated for low
                 power consumption S0ix, empty list if none.
        """
        # PCH IP block that is on for S0ix. Ignore these IP block.
        S0IX_WHITELIST = set([
                'PMC', 'OPI-DMI', 'SPI / eSPI', 'XHCI', 'xHCI', 'FUSE', 'PCIE0',
                'NPKVRC', 'NPKVNN'])

        # PCH IP block that is on/off for S0ix depend on features enabled.
        # Add log when these IPs state are on.
        S0IX_WARNLIST = set([
                'HDA-PGD0', 'HDA-PGD1', 'HDA-PGD2', 'HDA-PGD3', 'LPSS',
                'AVSPGD1', 'AVSPGD4'])

        # CNV device has 0x31dc as devid .
        if len(utils.system_output('lspci -d :31dc')) > 0:
            S0IX_WHITELIST.add('CNV')

        on_ip = set(ip['name'] for ip in self._stat if ip['state'])
        on_ip -= S0IX_WHITELIST

        if on_ip:
            on_ip_in_warn_list = on_ip & S0IX_WARNLIST
            if on_ip_in_warn_list:
                logging.warn('Found PCH IP that may be able to powergate: %s',
                             ', '.join(on_ip_in_warn_list))
            on_ip -= S0IX_WARNLIST

        if on_ip:
            logging.error('Found PCH IP that need to powergate: %s',
                          ', '.join(on_ip))
            return False
        return True

    def read_pch_powergating_info(self, sleep_seconds=1):
        """
        Read PCH powergating status info for Intel based systems.

        Intel currently shows powergating status in 2 different place in debugfs
        depend on which CPU platform.

        @param sleep_seconds: sleep time to make DUT idle before read the data.

        @raises error.TestFail if the debugfs file not found or parsing error.
        """
        if os.path.exists(self.PMC_CORE_PATH):
            logging.info('Use PCH powergating info at %s', self.PMC_CORE_PATH)
            time.sleep(sleep_seconds)
            self._read_pcm_core_powergating_info()
            return

        if os.path.exists(self.TELEMETRY_PATH):
            logging.info('Use PCH powergating info at %s', self.TELEMETRY_PATH)
            time.sleep(sleep_seconds)
            self._read_telemetry_powergating_info()
            return

        raise error.TestFail('PCH powergating info file not found.')

    def _read_pcm_core_powergating_info(self):
        """
        read_pch_powergating_info() for Intel Core KBL+

        @raises error.TestFail if parsing error.
        """
        with open(self.PMC_CORE_PATH, 'r') as f:
            lines = [line.strip() for line in f.readlines()]

        # Example pattern to match:
        # PCH IP: 0  - PMC                                State: On
        # PCH IP: 1  - SATA                               State: Off
        pattern = r'PCH IP:\s+(?P<id>\d+)\s+' \
                  r'- (?P<name>.*\w)\s+'      \
                  r'State: (?P<state>Off|On)'
        matcher = re.compile(pattern)
        ret = []
        for i, line in enumerate(lines):
            match = matcher.match(line)
            if not match:
                raise error.TestFail('Can not parse PCH powergating info: ',
                                     line)

            index = int(match.group('id'))
            if i != index:
                raise error.TestFail('Wrong index for PCH powergating info: ',
                                     line)

            name = match.group('name')
            state = match.group('state') == 'On'

            ret.append({'name': name, 'state': state})
        self._stat = ret

    def _read_telemetry_powergating_info(self):
        """
        read_pch_powergating_info() for Intel Atom APL+

        @raises error.TestFail if parsing error.
        """
        with open(self.TELEMETRY_PATH, 'r') as f:
            raw_str = f.read()

        # Example pattern to match:
        # --------------------------------------
        # South Complex PowerGate Status
        # --------------------------------------
        # Device           PG
        # LPSS             1
        # SPI              1
        # FUSE             0
        #
        # ---------------------------------------
        trimed_pattern = r'.*South Complex PowerGate Status\n'    \
                         r'-+\n'                                  \
                         r'Device\s+PG\n'                         \
                         r'(?P<trimmed_section>(\w+\s+[0|1]\n)+)' \
                         r'\n-+\n.*'
        trimed_match = re.match(trimed_pattern, raw_str, re.DOTALL)
        if not trimed_match:
            raise error.TestFail('Can not parse PCH powergating info: ',
                                 raw_str)
        trimmed_str = trimed_match.group('trimmed_section').strip()
        lines = [line.strip() for line in trimmed_str.split('\n')]

        matcher = re.compile(r'(?P<name>\w+)\s+(?P<state>[0|1])')
        ret = []
        for line in lines:
            match = matcher.match(line)
            if not match:
                raise error.TestFail('Can not parse PCH powergating info: %s',
                                     line)

            name = match.group('name')
            state = match.group('state') == '0' # 0 means on and 1 means off

            ret.append({'name': name, 'state': state})
        self._stat = ret
