aboutsummaryrefslogtreecommitdiff
path: root/catapult/devil/devil/android/perf/thermal_throttle.py
blob: 9b8dc07b7ae8a8c196c4e88af4c644ea6b036e23 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging

logger = logging.getLogger(__name__)


class OmapThrottlingDetector(object):
  """Class to detect and track thermal throttling on an OMAP 4."""
  OMAP_TEMP_FILE = ('/sys/devices/platform/omap/omap_temp_sensor.0/'
                    'temperature')

  @staticmethod
  def IsSupported(device):
    return device.FileExists(OmapThrottlingDetector.OMAP_TEMP_FILE)

  def __init__(self, device):
    self._device = device

  @staticmethod
  def BecameThrottled(log_line):
    return 'omap_thermal_throttle' in log_line

  @staticmethod
  def BecameUnthrottled(log_line):
    return 'omap_thermal_unthrottle' in log_line

  @staticmethod
  def GetThrottlingTemperature(log_line):
    if 'throttle_delayed_work_fn' in log_line:
      return float([s for s in log_line.split() if s.isdigit()][0]) / 1000.0

  def GetCurrentTemperature(self):
    tempdata = self._device.ReadFile(OmapThrottlingDetector.OMAP_TEMP_FILE)
    return float(tempdata) / 1000.0


class ExynosThrottlingDetector(object):
  """Class to detect and track thermal throttling on an Exynos 5."""

  @staticmethod
  def IsSupported(device):
    return device.FileExists('/sys/bus/exynos5-core')

  def __init__(self, device):
    pass

  @staticmethod
  def BecameThrottled(log_line):
    return 'exynos_tmu: Throttling interrupt' in log_line

  @staticmethod
  def BecameUnthrottled(log_line):
    return 'exynos_thermal_unthrottle: not throttling' in log_line

  @staticmethod
  def GetThrottlingTemperature(_log_line):
    return None

  @staticmethod
  def GetCurrentTemperature():
    return None


class ThermalThrottle(object):
  """Class to detect and track thermal throttling.

  Usage:
    Wait for IsThrottled() to be False before running test
    After running test call HasBeenThrottled() to find out if the
    test run was affected by thermal throttling.
  """

  def __init__(self, device):
    self._device = device
    self._throttled = False
    self._detector = None
    # pylint: disable=redefined-variable-type
    if OmapThrottlingDetector.IsSupported(device):
      self._detector = OmapThrottlingDetector(device)
    elif ExynosThrottlingDetector.IsSupported(device):
      self._detector = ExynosThrottlingDetector(device)

  def HasBeenThrottled(self):
    """True if there has been any throttling since the last call to
       HasBeenThrottled or IsThrottled.
    """
    return self._ReadLog()

  def IsThrottled(self):
    """True if currently throttled."""
    self._ReadLog()
    return self._throttled

  def _ReadLog(self):
    if not self._detector:
      return False
    has_been_throttled = False
    serial_number = str(self._device)
    log = self._device.RunShellCommand(['dmesg', '-c'],
                                       large_output=True,
                                       check_return=True)
    degree_symbol = unichr(0x00B0)
    for line in log:
      if self._detector.BecameThrottled(line):
        if not self._throttled:
          logger.warning('>>> Device %s thermally throttled', serial_number)
        self._throttled = True
        has_been_throttled = True
      elif self._detector.BecameUnthrottled(line):
        if self._throttled:
          logger.warning('>>> Device %s thermally unthrottled', serial_number)
        self._throttled = False
        has_been_throttled = True
      temperature = self._detector.GetThrottlingTemperature(line)
      if temperature is not None:
        logger.info(u'Device %s thermally throttled at %3.1f%sC', serial_number,
                    temperature, degree_symbol)

    if logger.isEnabledFor(logging.DEBUG):
      # Print current temperature of CPU SoC.
      temperature = self._detector.GetCurrentTemperature()
      if temperature is not None:
        logger.debug(u'Current SoC temperature of %s = %3.1f%sC', serial_number,
                     temperature, degree_symbol)

      # Print temperature of battery, to give a system temperature
      dumpsys_log = self._device.RunShellCommand(['dumpsys', 'battery'],
                                                 check_return=True)
      for line in dumpsys_log:
        if 'temperature' in line:
          btemp = float([s for s in line.split() if s.isdigit()][0]) / 10.0
          logger.debug(u'Current battery temperature of %s = %3.1f%sC',
                       serial_number, btemp, degree_symbol)

    return has_been_throttled