1 # Copyright 2012 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.
5 import logging as real_logging
9 from telemetry.core import discover
10 from telemetry.core import util
11 from telemetry.core.platform import platform_backend as platform_backend_module
12 from telemetry.core.platform import profiling_controller
13 from telemetry.core.platform import tracing_controller
17 # Remote platform is a dictionary from device ids to remote platform instances.
18 _remote_platforms = {}
21 def _IsRunningOnCrosDevice():
22 """Returns True if we're on a ChromeOS device."""
23 lsb_release = '/etc/lsb-release'
24 if sys.platform.startswith('linux') and os.path.exists(lsb_release):
25 with open(lsb_release, 'r') as f:
27 if res.count('CHROMEOS_RELEASE_NAME'):
32 def _InitHostPlatformIfNeeded():
36 if _IsRunningOnCrosDevice():
37 from telemetry.core.platform import cros_platform_backend
38 backend = cros_platform_backend.CrosPlatformBackend()
39 elif sys.platform.startswith('linux'):
40 from telemetry.core.platform import linux_platform_backend
41 backend = linux_platform_backend.LinuxPlatformBackend()
42 elif sys.platform == 'darwin':
43 from telemetry.core.platform import mac_platform_backend
44 backend = mac_platform_backend.MacPlatformBackend()
45 elif sys.platform == 'win32':
46 from telemetry.core.platform import win_platform_backend
47 backend = win_platform_backend.WinPlatformBackend()
49 raise NotImplementedError()
51 _host_platform = Platform(backend)
54 def GetHostPlatform():
55 _InitHostPlatformIfNeeded()
59 def GetPlatformForDevice(device, logging=real_logging):
60 """ Returns a platform instance for the device.
62 device: a device.Device instance.
64 if device.guid in _remote_platforms:
65 return _remote_platforms[device.guid]
67 platform_backend = None
68 platform_dir = os.path.dirname(os.path.realpath(__file__))
69 for platform_backend_class in discover.DiscoverClasses(
70 platform_dir, util.GetTelemetryDir(),
71 platform_backend_module.PlatformBackend).itervalues():
72 if platform_backend_class.SupportsDevice(device):
73 platform_backend = platform_backend_class(device)
74 _remote_platforms[device.guid] = Platform(platform_backend)
75 return _remote_platforms[device.guid]
78 logging.error('Fail to create platform instance for %s.', device.name)
82 class Platform(object):
83 """The platform that the target browser is running on.
85 Provides a limited interface to interact with the platform itself, where
86 possible. It's important to note that platforms may not provide a specific
87 API, so check with IsFooBar() for availability.
89 def __init__(self, platform_backend):
90 self._platform_backend = platform_backend
91 self._platform_backend.SetPlatform(self)
92 self._tracing_controller = tracing_controller.TracingController(
93 self._platform_backend.tracing_controller_backend)
94 self._profiling_controller = profiling_controller.ProfilingController(
95 self._platform_backend.profiling_controller_backend)
98 def tracing_controller(self):
99 return self._tracing_controller
102 def profiling_controller(self):
103 return self._profiling_controller
105 def IsRawDisplayFrameRateSupported(self):
106 """Platforms may be able to collect GL surface stats."""
107 return self._platform_backend.IsRawDisplayFrameRateSupported()
109 def StartRawDisplayFrameRateMeasurement(self):
110 """Start measuring GL surface stats."""
111 return self._platform_backend.StartRawDisplayFrameRateMeasurement()
113 def StopRawDisplayFrameRateMeasurement(self):
114 """Stop measuring GL surface stats."""
115 return self._platform_backend.StopRawDisplayFrameRateMeasurement()
117 class RawDisplayFrameRateMeasurement(object):
118 def __init__(self, name, value, unit):
135 def GetRawDisplayFrameRateMeasurements(self):
136 """Returns a list of RawDisplayFrameRateMeasurement."""
137 return self._platform_backend.GetRawDisplayFrameRateMeasurements()
139 def CanMonitorThermalThrottling(self):
140 """Platforms may be able to detect thermal throttling.
142 Some fan-less computers go into a reduced performance mode when their heat
143 exceeds a certain threshold. Performance tests in particular should use this
144 API to detect if this has happened and interpret results accordingly.
146 return self._platform_backend.CanMonitorThermalThrottling()
148 def IsThermallyThrottled(self):
149 """Returns True if the device is currently thermally throttled."""
150 return self._platform_backend.IsThermallyThrottled()
152 def HasBeenThermallyThrottled(self):
153 """Returns True if the device has been thermally throttled."""
154 return self._platform_backend.HasBeenThermallyThrottled()
157 """Returns a string description of the Platform OS.
159 Examples: WIN, MAC, LINUX, CHROMEOS"""
160 return self._platform_backend.GetOSName()
162 def GetOSVersionName(self):
163 """Returns a logically sortable, string-like description of the Platform OS
166 Examples: VISTA, WIN7, LION, MOUNTAINLION"""
167 return self._platform_backend.GetOSVersionName()
169 def CanFlushIndividualFilesFromSystemCache(self):
170 """Returns true if the disk cache can be flushed for specific files."""
171 return self._platform_backend.CanFlushIndividualFilesFromSystemCache()
173 def FlushEntireSystemCache(self):
174 """Flushes the OS's file cache completely.
176 This function may require root or administrator access."""
177 return self._platform_backend.FlushEntireSystemCache()
179 def FlushSystemCacheForDirectory(self, directory, ignoring=None):
180 """Flushes the OS's file cache for the specified directory.
182 Any files or directories inside |directory| matching a name in the
183 |ignoring| list will be skipped.
185 This function does not require root or administrator access."""
186 return self._platform_backend.FlushSystemCacheForDirectory(
187 directory, ignoring=ignoring)
189 def FlushDnsCache(self):
190 """Flushes the OS's DNS cache completely.
192 This function may require root or administrator access."""
193 return self._platform_backend.FlushDnsCache()
195 def LaunchApplication(self, application, parameters=None,
196 elevate_privilege=False):
197 """"Launches the given |application| with a list of |parameters| on the OS.
199 Set |elevate_privilege| to launch the application with root or admin rights.
202 A popen style process handle for host platforms.
204 return self._platform_backend.LaunchApplication(
205 application, parameters, elevate_privilege=elevate_privilege)
207 def IsApplicationRunning(self, application):
208 """Returns whether an application is currently running."""
209 return self._platform_backend.IsApplicationRunning(application)
211 def CanLaunchApplication(self, application):
212 """Returns whether the platform can launch the given application."""
213 return self._platform_backend.CanLaunchApplication(application)
215 def InstallApplication(self, application):
216 """Installs the given application."""
217 return self._platform_backend.InstallApplication(application)
219 def CanCaptureVideo(self):
220 """Returns a bool indicating whether the platform supports video capture."""
221 return self._platform_backend.CanCaptureVideo()
223 def StartVideoCapture(self, min_bitrate_mbps):
224 """Starts capturing video.
226 Outer framing may be included (from the OS, browser window, and webcam).
229 min_bitrate_mbps: The minimum capture bitrate in MegaBits Per Second.
230 The platform is free to deliver a higher bitrate if it can do so
231 without increasing overhead.
234 ValueError if the required |min_bitrate_mbps| can't be achieved.
236 return self._platform_backend.StartVideoCapture(min_bitrate_mbps)
238 def StopVideoCapture(self):
239 """Stops capturing video.
242 A telemetry.core.video.Video object.
244 return self._platform_backend.StopVideoCapture()
246 def CanMonitorPower(self):
247 """Returns True iff power can be monitored asynchronously via
248 StartMonitoringPower() and StopMonitoringPower().
250 return self._platform_backend.CanMonitorPower()
252 def CanMeasurePerApplicationPower(self):
253 """Returns True if the power monitor can measure power for the target
254 application in isolation. False if power measurement is for full system
255 energy consumption."""
256 return self._platform_backend.CanMeasurePerApplicationPower()
259 def StartMonitoringPower(self, browser):
260 """Starts monitoring power utilization statistics.
263 browser: The browser to monitor.
265 assert self._platform_backend.CanMonitorPower()
266 self._platform_backend.StartMonitoringPower(browser)
268 def StopMonitoringPower(self):
269 """Stops monitoring power utilization and returns stats
272 None if power measurement failed for some reason, otherwise a dict of
273 power utilization statistics containing: {
274 # An identifier for the data provider. Allows to evaluate the precision
275 # of the data. Example values: monsoon, powermetrics, ds2784
276 'identifier': identifier,
278 # The instantaneous power (voltage * current) reading in milliwatts at
280 'power_samples_mw': [mw0, mw1, ..., mwN],
282 # The full system energy consumption during the sampling period in
283 # milliwatt hours. May be estimated by integrating power samples or may
284 # be exact on supported hardware.
285 'energy_consumption_mwh': mwh,
287 # The target application's energy consumption during the sampling period
288 # in milliwatt hours. Should be returned iff
289 # CanMeasurePerApplicationPower() return true.
290 'application_energy_consumption_mwh': mwh,
292 # A platform-specific dictionary of additional details about the
293 # utilization of individual hardware components.
294 component_utilization: {
296 # Platform-specific data not attributed to any particular hardware
300 # Device-specific onboard temperature sensor.
301 'average_temperature_c': c,
310 return self._platform_backend.StopMonitoringPower()