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