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