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 network_controller
12 from telemetry.core.platform import platform_backend as platform_backend_module
13 from telemetry.core.platform import profiling_controller
14 from telemetry.core.platform import tracing_controller
18 # Remote platform is a dictionary from device ids to remote platform instances.
19 _remote_platforms = {}
22 def _IsRunningOnCrosDevice():
23 """Returns True if we're on a ChromeOS device."""
24 lsb_release = '/etc/lsb-release'
25 if sys.platform.startswith('linux') and os.path.exists(lsb_release):
26 with open(lsb_release, 'r') as f:
28 if res.count('CHROMEOS_RELEASE_NAME'):
33 def _InitHostPlatformIfNeeded():
37 if _IsRunningOnCrosDevice():
38 from telemetry.core.platform import cros_platform_backend
39 backend = cros_platform_backend.CrosPlatformBackend()
40 elif sys.platform.startswith('linux'):
41 from telemetry.core.platform import linux_platform_backend
42 backend = linux_platform_backend.LinuxPlatformBackend()
43 elif sys.platform == 'darwin':
44 from telemetry.core.platform import mac_platform_backend
45 backend = mac_platform_backend.MacPlatformBackend()
46 elif sys.platform == 'win32':
47 from telemetry.core.platform import win_platform_backend
48 backend = win_platform_backend.WinPlatformBackend()
50 raise NotImplementedError()
52 _host_platform = Platform(backend)
55 def GetHostPlatform():
56 _InitHostPlatformIfNeeded()
60 def GetPlatformForDevice(device, logging=real_logging):
61 """ Returns a platform instance for the device.
63 device: a device.Device instance.
65 if device.guid in _remote_platforms:
66 return _remote_platforms[device.guid]
68 platform_backend = None
69 platform_dir = os.path.dirname(os.path.realpath(__file__))
70 for platform_backend_class in discover.DiscoverClasses(
71 platform_dir, util.GetTelemetryDir(),
72 platform_backend_module.PlatformBackend).itervalues():
73 if platform_backend_class.SupportsDevice(device):
74 platform_backend = platform_backend_class(device)
75 _remote_platforms[device.guid] = Platform(platform_backend)
76 return _remote_platforms[device.guid]
79 logging.error('Fail to create platform instance for %s.', device.name)
83 class Platform(object):
84 """The platform that the target browser is running on.
86 Provides a limited interface to interact with the platform itself, where
87 possible. It's important to note that platforms may not provide a specific
88 API, so check with IsFooBar() for availability.
90 def __init__(self, platform_backend):
91 self._platform_backend = platform_backend
92 self._platform_backend.SetPlatform(self)
93 self._network_controller = network_controller.NetworkController(
94 self._platform_backend.network_controller_backend)
95 self._tracing_controller = tracing_controller.TracingController(
96 self._platform_backend.tracing_controller_backend)
97 self._profiling_controller = profiling_controller.ProfilingController(
98 self._platform_backend.profiling_controller_backend)
101 def network_controller(self):
102 """Control network settings and servers to simulate the Web."""
103 return self._network_controller
106 def tracing_controller(self):
107 return self._tracing_controller
110 def profiling_controller(self):
111 return self._profiling_controller
113 def IsRawDisplayFrameRateSupported(self):
114 """Platforms may be able to collect GL surface stats."""
115 return self._platform_backend.IsRawDisplayFrameRateSupported()
117 def StartRawDisplayFrameRateMeasurement(self):
118 """Start measuring GL surface stats."""
119 return self._platform_backend.StartRawDisplayFrameRateMeasurement()
121 def StopRawDisplayFrameRateMeasurement(self):
122 """Stop measuring GL surface stats."""
123 return self._platform_backend.StopRawDisplayFrameRateMeasurement()
125 class RawDisplayFrameRateMeasurement(object):
126 def __init__(self, name, value, unit):
143 def GetRawDisplayFrameRateMeasurements(self):
144 """Returns a list of RawDisplayFrameRateMeasurement."""
145 return self._platform_backend.GetRawDisplayFrameRateMeasurements()
147 def CanMonitorThermalThrottling(self):
148 """Platforms may be able to detect thermal throttling.
150 Some fan-less computers go into a reduced performance mode when their heat
151 exceeds a certain threshold. Performance tests in particular should use this
152 API to detect if this has happened and interpret results accordingly.
154 return self._platform_backend.CanMonitorThermalThrottling()
156 def IsThermallyThrottled(self):
157 """Returns True if the device is currently thermally throttled."""
158 return self._platform_backend.IsThermallyThrottled()
160 def HasBeenThermallyThrottled(self):
161 """Returns True if the device has been thermally throttled."""
162 return self._platform_backend.HasBeenThermallyThrottled()
164 def GetArchName(self):
165 """Returns a string description of the Platform architecture.
167 Examples: x86_64 (posix), AMD64 (win), armeabi-v7a, x86"""
168 return self._platform_backend.GetArchName()
171 """Returns a string description of the Platform OS.
173 Examples: WIN, MAC, LINUX, CHROMEOS"""
174 return self._platform_backend.GetOSName()
176 def GetOSVersionName(self):
177 """Returns a logically sortable, string-like description of the Platform OS
180 Examples: VISTA, WIN7, LION, MOUNTAINLION"""
181 return self._platform_backend.GetOSVersionName()
183 def CanFlushIndividualFilesFromSystemCache(self):
184 """Returns true if the disk cache can be flushed for specific files."""
185 return self._platform_backend.CanFlushIndividualFilesFromSystemCache()
187 def FlushEntireSystemCache(self):
188 """Flushes the OS's file cache completely.
190 This function may require root or administrator access."""
191 return self._platform_backend.FlushEntireSystemCache()
193 def FlushSystemCacheForDirectory(self, directory, ignoring=None):
194 """Flushes the OS's file cache for the specified directory.
196 Any files or directories inside |directory| matching a name in the
197 |ignoring| list will be skipped.
199 This function does not require root or administrator access."""
200 return self._platform_backend.FlushSystemCacheForDirectory(
201 directory, ignoring=ignoring)
203 def FlushDnsCache(self):
204 """Flushes the OS's DNS cache completely.
206 This function may require root or administrator access."""
207 return self._platform_backend.FlushDnsCache()
209 def LaunchApplication(self, application, parameters=None,
210 elevate_privilege=False):
211 """"Launches the given |application| with a list of |parameters| on the OS.
213 Set |elevate_privilege| to launch the application with root or admin rights.
216 A popen style process handle for host platforms.
218 return self._platform_backend.LaunchApplication(
219 application, parameters, elevate_privilege=elevate_privilege)
221 def IsApplicationRunning(self, application):
222 """Returns whether an application is currently running."""
223 return self._platform_backend.IsApplicationRunning(application)
225 def CanLaunchApplication(self, application):
226 """Returns whether the platform can launch the given application."""
227 return self._platform_backend.CanLaunchApplication(application)
229 def InstallApplication(self, application):
230 """Installs the given application."""
231 return self._platform_backend.InstallApplication(application)
233 def CanCaptureVideo(self):
234 """Returns a bool indicating whether the platform supports video capture."""
235 return self._platform_backend.CanCaptureVideo()
237 def StartVideoCapture(self, min_bitrate_mbps):
238 """Starts capturing video.
240 Outer framing may be included (from the OS, browser window, and webcam).
243 min_bitrate_mbps: The minimum capture bitrate in MegaBits Per Second.
244 The platform is free to deliver a higher bitrate if it can do so
245 without increasing overhead.
248 ValueError if the required |min_bitrate_mbps| can't be achieved.
250 return self._platform_backend.StartVideoCapture(min_bitrate_mbps)
252 def StopVideoCapture(self):
253 """Stops capturing video.
256 A telemetry.core.video.Video object.
258 return self._platform_backend.StopVideoCapture()
260 def CanMonitorPower(self):
261 """Returns True iff power can be monitored asynchronously via
262 StartMonitoringPower() and StopMonitoringPower().
264 return self._platform_backend.CanMonitorPower()
266 def CanMeasurePerApplicationPower(self):
267 """Returns True if the power monitor can measure power for the target
268 application in isolation. False if power measurement is for full system
269 energy consumption."""
270 return self._platform_backend.CanMeasurePerApplicationPower()
273 def StartMonitoringPower(self, browser):
274 """Starts monitoring power utilization statistics.
277 browser: The browser to monitor.
279 assert self._platform_backend.CanMonitorPower()
280 self._platform_backend.StartMonitoringPower(browser)
282 def StopMonitoringPower(self):
283 """Stops monitoring power utilization and returns stats
286 None if power measurement failed for some reason, otherwise a dict of
287 power utilization statistics containing: {
288 # An identifier for the data provider. Allows to evaluate the precision
289 # of the data. Example values: monsoon, powermetrics, ds2784
290 'identifier': identifier,
292 # The instantaneous power (voltage * current) reading in milliwatts at
294 'power_samples_mw': [mw0, mw1, ..., mwN],
296 # The full system energy consumption during the sampling period in
297 # milliwatt hours. May be estimated by integrating power samples or may
298 # be exact on supported hardware.
299 'energy_consumption_mwh': mwh,
301 # The target application's energy consumption during the sampling period
302 # in milliwatt hours. Should be returned iff
303 # CanMeasurePerApplicationPower() return true.
304 'application_energy_consumption_mwh': mwh,
306 # A platform-specific dictionary of additional details about the
307 # utilization of individual hardware components.
308 component_utilization: {
310 # Platform-specific data not attributed to any particular hardware
314 # Device-specific onboard temperature sensor.
315 'average_temperature_c': c,
324 return self._platform_backend.StopMonitoringPower()