• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2013 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6
7logger = logging.getLogger(__name__)
8
9
10class OmapThrottlingDetector(object):
11  """Class to detect and track thermal throttling on an OMAP 4."""
12  OMAP_TEMP_FILE = ('/sys/devices/platform/omap/omap_temp_sensor.0/'
13                    'temperature')
14
15  @staticmethod
16  def IsSupported(device):
17    return device.FileExists(OmapThrottlingDetector.OMAP_TEMP_FILE)
18
19  def __init__(self, device):
20    self._device = device
21
22  @staticmethod
23  def BecameThrottled(log_line):
24    return 'omap_thermal_throttle' in log_line
25
26  @staticmethod
27  def BecameUnthrottled(log_line):
28    return 'omap_thermal_unthrottle' in log_line
29
30  @staticmethod
31  def GetThrottlingTemperature(log_line):
32    if 'throttle_delayed_work_fn' in log_line:
33      return float([s for s in log_line.split() if s.isdigit()][0]) / 1000.0
34
35  def GetCurrentTemperature(self):
36    tempdata = self._device.ReadFile(OmapThrottlingDetector.OMAP_TEMP_FILE)
37    return float(tempdata) / 1000.0
38
39
40class ExynosThrottlingDetector(object):
41  """Class to detect and track thermal throttling on an Exynos 5."""
42  @staticmethod
43  def IsSupported(device):
44    return device.FileExists('/sys/bus/exynos5-core')
45
46  def __init__(self, device):
47    pass
48
49  @staticmethod
50  def BecameThrottled(log_line):
51    return 'exynos_tmu: Throttling interrupt' in log_line
52
53  @staticmethod
54  def BecameUnthrottled(log_line):
55    return 'exynos_thermal_unthrottle: not throttling' in log_line
56
57  @staticmethod
58  def GetThrottlingTemperature(_log_line):
59    return None
60
61  @staticmethod
62  def GetCurrentTemperature():
63    return None
64
65
66class ThermalThrottle(object):
67  """Class to detect and track thermal throttling.
68
69  Usage:
70    Wait for IsThrottled() to be False before running test
71    After running test call HasBeenThrottled() to find out if the
72    test run was affected by thermal throttling.
73  """
74
75  def __init__(self, device):
76    self._device = device
77    self._throttled = False
78    self._detector = None
79    if OmapThrottlingDetector.IsSupported(device):
80      self._detector = OmapThrottlingDetector(device)
81    elif ExynosThrottlingDetector.IsSupported(device):
82      self._detector = ExynosThrottlingDetector(device)
83
84  def HasBeenThrottled(self):
85    """True if there has been any throttling since the last call to
86       HasBeenThrottled or IsThrottled.
87    """
88    return self._ReadLog()
89
90  def IsThrottled(self):
91    """True if currently throttled."""
92    self._ReadLog()
93    return self._throttled
94
95  def _ReadLog(self):
96    if not self._detector:
97      return False
98    has_been_throttled = False
99    serial_number = str(self._device)
100    log = self._device.RunShellCommand(
101        ['dmesg', '-c'], large_output=True, check_return=True)
102    degree_symbol = unichr(0x00B0)
103    for line in log:
104      if self._detector.BecameThrottled(line):
105        if not self._throttled:
106          logger.warning('>>> Device %s thermally throttled', serial_number)
107        self._throttled = True
108        has_been_throttled = True
109      elif self._detector.BecameUnthrottled(line):
110        if self._throttled:
111          logger.warning('>>> Device %s thermally unthrottled', serial_number)
112        self._throttled = False
113        has_been_throttled = True
114      temperature = self._detector.GetThrottlingTemperature(line)
115      if temperature is not None:
116        logger.info(u'Device %s thermally throttled at %3.1f%sC',
117                    serial_number, temperature, degree_symbol)
118
119    if logger.isEnabledFor(logging.DEBUG):
120      # Print current temperature of CPU SoC.
121      temperature = self._detector.GetCurrentTemperature()
122      if temperature is not None:
123        logger.debug(u'Current SoC temperature of %s = %3.1f%sC',
124                     serial_number, temperature, degree_symbol)
125
126      # Print temperature of battery, to give a system temperature
127      dumpsys_log = self._device.RunShellCommand(
128          ['dumpsys', 'battery'], check_return=True)
129      for line in dumpsys_log:
130        if 'temperature' in line:
131          btemp = float([s for s in line.split() if s.isdigit()][0]) / 10.0
132          logger.debug(u'Current battery temperature of %s = %3.1f%sC',
133                       serial_number, btemp, degree_symbol)
134
135    return has_been_throttled
136