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