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 5from telemetry.core.platform import cros_device 6from telemetry.core.platform import cros_interface 7from telemetry.core.platform import linux_based_platform_backend 8from telemetry.core.platform import ps_util 9from telemetry.core.platform.power_monitor import cros_power_monitor 10 11 12class CrosPlatformBackend( 13 linux_based_platform_backend.LinuxBasedPlatformBackend): 14 15 def __init__(self, device=None): 16 super(CrosPlatformBackend, self).__init__(device) 17 if device: 18 self._cri = cros_interface.CrOSInterface( 19 device.host_name, device.ssh_identity) 20 self._cri.TryLogin() 21 else: 22 self._cri = cros_interface.CrOSInterface() 23 self._powermonitor = cros_power_monitor.CrosPowerMonitor(self) 24 25 @classmethod 26 def SupportsDevice(cls, device): 27 return isinstance(device, cros_device.CrOSDevice) 28 29 @property 30 def cri(self): 31 return self._cri 32 33 def StartRawDisplayFrameRateMeasurement(self): 34 raise NotImplementedError() 35 36 def StopRawDisplayFrameRateMeasurement(self): 37 raise NotImplementedError() 38 39 def GetRawDisplayFrameRateMeasurements(self): 40 raise NotImplementedError() 41 42 def IsThermallyThrottled(self): 43 raise NotImplementedError() 44 45 def HasBeenThermallyThrottled(self): 46 raise NotImplementedError() 47 48 def RunCommand(self, args): 49 return self._cri.RunCmdOnDevice(args)[0] 50 51 def GetFileContents(self, filename): 52 try: 53 return self.RunCommand(['cat', filename]) 54 except AssertionError: 55 return '' 56 57 @staticmethod 58 def ParseCStateSample(sample): 59 sample_stats = {} 60 for cpu in sample: 61 values = sample[cpu].splitlines() 62 # There are three values per state after excluding the single time value. 63 num_states = (len(values) - 1) / 3 64 names = values[:num_states] 65 times = values[num_states:2 * num_states] 66 latencies = values[2 * num_states:] 67 # The last line in the sample contains the time. 68 cstates = {'C0': int(values[-1]) * 10 ** 6} 69 for i, state in enumerate(names): 70 if names[i] == 'POLL' and not int(latencies[i]): 71 # C0 state. Kernel stats aren't right, so calculate by 72 # subtracting all other states from total time (using epoch 73 # timer since we calculate differences in the end anyway). 74 # NOTE: Only x86 lists C0 under cpuidle, ARM does not. 75 continue 76 cstates['C0'] -= int(times[i]) 77 if names[i] == '<null>': 78 # Kernel race condition that can happen while a new C-state gets 79 # added (e.g. AC->battery). Don't know the 'name' of the state 80 # yet, but its 'time' would be 0 anyway. 81 continue 82 cstates[state] = int(times[i]) 83 sample_stats[cpu] = cstates 84 return sample_stats 85 86 def GetIOStats(self, pid): 87 # There is no '/proc/<pid>/io' file on CrOS platforms 88 # Returns empty dict as it does in PlatformBackend. 89 return {} 90 91 def GetOSName(self): 92 return 'chromeos' 93 94 def GetOSVersionName(self): 95 return '' # TODO: Implement this. 96 97 def GetChildPids(self, pid): 98 """Returns a list of child pids of |pid|.""" 99 all_process_info = self._cri.ListProcesses() 100 processes = [(curr_pid, curr_ppid, curr_state) 101 for curr_pid, _, curr_ppid, curr_state in all_process_info] 102 return ps_util.GetChildPids(processes, pid) 103 104 def GetCommandLine(self, pid): 105 procs = self._cri.ListProcesses() 106 return next((proc[1] for proc in procs if proc[0] == pid), None) 107 108 def CanFlushIndividualFilesFromSystemCache(self): 109 return True 110 111 def FlushEntireSystemCache(self): 112 raise NotImplementedError() 113 114 def FlushSystemCacheForDirectory(self, directory, ignoring=None): 115 raise NotImplementedError() 116 117 def CanMonitorPower(self): 118 return self._powermonitor.CanMonitorPower() 119 120 def StartMonitoringPower(self, browser): 121 self._powermonitor.StartMonitoringPower(browser) 122 123 def StopMonitoringPower(self): 124 return self._powermonitor.StopMonitoringPower() 125