blob: e11d51f99e8572479057a82ad51606cf4e27ee59 [file] [log] [blame]
# Copyright 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging as real_logging
import os
import sys
from telemetry.core import discover
from telemetry.core import util
from telemetry.core.platform import network_controller
from telemetry.core.platform import platform_backend as platform_backend_module
from telemetry.core.platform import profiling_controller
from telemetry.core.platform import tracing_controller
_host_platform = None
# Remote platform is a dictionary from device ids to remote platform instances.
_remote_platforms = {}
def _IsRunningOnCrosDevice():
"""Returns True if we're on a ChromeOS device."""
lsb_release = '/etc/lsb-release'
if sys.platform.startswith('linux') and os.path.exists(lsb_release):
with open(lsb_release, 'r') as f:
res = f.read()
if res.count('CHROMEOS_RELEASE_NAME'):
return True
return False
def _InitHostPlatformIfNeeded():
global _host_platform
if _host_platform:
return
if _IsRunningOnCrosDevice():
from telemetry.core.platform import cros_platform_backend
backend = cros_platform_backend.CrosPlatformBackend()
elif sys.platform.startswith('linux'):
from telemetry.core.platform import linux_platform_backend
backend = linux_platform_backend.LinuxPlatformBackend()
elif sys.platform == 'darwin':
from telemetry.core.platform import mac_platform_backend
backend = mac_platform_backend.MacPlatformBackend()
elif sys.platform == 'win32':
from telemetry.core.platform import win_platform_backend
backend = win_platform_backend.WinPlatformBackend()
else:
raise NotImplementedError()
_host_platform = Platform(backend)
def GetHostPlatform():
_InitHostPlatformIfNeeded()
return _host_platform
def GetPlatformForDevice(device, logging=real_logging):
""" Returns a platform instance for the device.
Args:
device: a device.Device instance.
"""
if device.guid in _remote_platforms:
return _remote_platforms[device.guid]
try:
platform_backend = None
platform_dir = os.path.dirname(os.path.realpath(__file__))
for platform_backend_class in discover.DiscoverClasses(
platform_dir, util.GetTelemetryDir(),
platform_backend_module.PlatformBackend).itervalues():
if platform_backend_class.SupportsDevice(device):
platform_backend = platform_backend_class(device)
_remote_platforms[device.guid] = Platform(platform_backend)
return _remote_platforms[device.guid]
return None
except Exception:
logging.error('Fail to create platform instance for %s.', device.name)
raise
class Platform(object):
"""The platform that the target browser is running on.
Provides a limited interface to interact with the platform itself, where
possible. It's important to note that platforms may not provide a specific
API, so check with IsFooBar() for availability.
"""
def __init__(self, platform_backend):
self._platform_backend = platform_backend
self._platform_backend.SetPlatform(self)
self._network_controller = network_controller.NetworkController(
self._platform_backend.network_controller_backend)
self._tracing_controller = tracing_controller.TracingController(
self._platform_backend.tracing_controller_backend)
self._profiling_controller = profiling_controller.ProfilingController(
self._platform_backend.profiling_controller_backend)
@property
def network_controller(self):
"""Control network settings and servers to simulate the Web."""
return self._network_controller
@property
def tracing_controller(self):
return self._tracing_controller
@property
def profiling_controller(self):
return self._profiling_controller
def IsRawDisplayFrameRateSupported(self):
"""Platforms may be able to collect GL surface stats."""
return self._platform_backend.IsRawDisplayFrameRateSupported()
def StartRawDisplayFrameRateMeasurement(self):
"""Start measuring GL surface stats."""
return self._platform_backend.StartRawDisplayFrameRateMeasurement()
def StopRawDisplayFrameRateMeasurement(self):
"""Stop measuring GL surface stats."""
return self._platform_backend.StopRawDisplayFrameRateMeasurement()
class RawDisplayFrameRateMeasurement(object):
def __init__(self, name, value, unit):
self._name = name
self._value = value
self._unit = unit
@property
def name(self):
return self._name
@property
def value(self):
return self._value
@property
def unit(self):
return self._unit
def GetRawDisplayFrameRateMeasurements(self):
"""Returns a list of RawDisplayFrameRateMeasurement."""
return self._platform_backend.GetRawDisplayFrameRateMeasurements()
def CanMonitorThermalThrottling(self):
"""Platforms may be able to detect thermal throttling.
Some fan-less computers go into a reduced performance mode when their heat
exceeds a certain threshold. Performance tests in particular should use this
API to detect if this has happened and interpret results accordingly.
"""
return self._platform_backend.CanMonitorThermalThrottling()
def IsThermallyThrottled(self):
"""Returns True if the device is currently thermally throttled."""
return self._platform_backend.IsThermallyThrottled()
def HasBeenThermallyThrottled(self):
"""Returns True if the device has been thermally throttled."""
return self._platform_backend.HasBeenThermallyThrottled()
def GetArchName(self):
"""Returns a string description of the Platform architecture.
Examples: x86_64 (posix), AMD64 (win), armeabi-v7a, x86"""
return self._platform_backend.GetArchName()
def GetOSName(self):
"""Returns a string description of the Platform OS.
Examples: WIN, MAC, LINUX, CHROMEOS"""
return self._platform_backend.GetOSName()
def GetOSVersionName(self):
"""Returns a logically sortable, string-like description of the Platform OS
version.
Examples: VISTA, WIN7, LION, MOUNTAINLION"""
return self._platform_backend.GetOSVersionName()
def CanFlushIndividualFilesFromSystemCache(self):
"""Returns true if the disk cache can be flushed for specific files."""
return self._platform_backend.CanFlushIndividualFilesFromSystemCache()
def FlushEntireSystemCache(self):
"""Flushes the OS's file cache completely.
This function may require root or administrator access."""
return self._platform_backend.FlushEntireSystemCache()
def FlushSystemCacheForDirectory(self, directory, ignoring=None):
"""Flushes the OS's file cache for the specified directory.
Any files or directories inside |directory| matching a name in the
|ignoring| list will be skipped.
This function does not require root or administrator access."""
return self._platform_backend.FlushSystemCacheForDirectory(
directory, ignoring=ignoring)
def FlushDnsCache(self):
"""Flushes the OS's DNS cache completely.
This function may require root or administrator access."""
return self._platform_backend.FlushDnsCache()
def LaunchApplication(self, application, parameters=None,
elevate_privilege=False):
""""Launches the given |application| with a list of |parameters| on the OS.
Set |elevate_privilege| to launch the application with root or admin rights.
Returns:
A popen style process handle for host platforms.
"""
return self._platform_backend.LaunchApplication(
application, parameters, elevate_privilege=elevate_privilege)
def IsApplicationRunning(self, application):
"""Returns whether an application is currently running."""
return self._platform_backend.IsApplicationRunning(application)
def CanLaunchApplication(self, application):
"""Returns whether the platform can launch the given application."""
return self._platform_backend.CanLaunchApplication(application)
def InstallApplication(self, application):
"""Installs the given application."""
return self._platform_backend.InstallApplication(application)
def CanCaptureVideo(self):
"""Returns a bool indicating whether the platform supports video capture."""
return self._platform_backend.CanCaptureVideo()
def StartVideoCapture(self, min_bitrate_mbps):
"""Starts capturing video.
Outer framing may be included (from the OS, browser window, and webcam).
Args:
min_bitrate_mbps: The minimum capture bitrate in MegaBits Per Second.
The platform is free to deliver a higher bitrate if it can do so
without increasing overhead.
Raises:
ValueError if the required |min_bitrate_mbps| can't be achieved.
"""
return self._platform_backend.StartVideoCapture(min_bitrate_mbps)
def StopVideoCapture(self):
"""Stops capturing video.
Returns:
A telemetry.core.video.Video object.
"""
return self._platform_backend.StopVideoCapture()
def CanMonitorPower(self):
"""Returns True iff power can be monitored asynchronously via
StartMonitoringPower() and StopMonitoringPower().
"""
return self._platform_backend.CanMonitorPower()
def CanMeasurePerApplicationPower(self):
"""Returns True if the power monitor can measure power for the target
application in isolation. False if power measurement is for full system
energy consumption."""
return self._platform_backend.CanMeasurePerApplicationPower()
def StartMonitoringPower(self, browser):
"""Starts monitoring power utilization statistics.
Args:
browser: The browser to monitor.
"""
assert self._platform_backend.CanMonitorPower()
self._platform_backend.StartMonitoringPower(browser)
def StopMonitoringPower(self):
"""Stops monitoring power utilization and returns stats
Returns:
None if power measurement failed for some reason, otherwise a dict of
power utilization statistics containing: {
# An identifier for the data provider. Allows to evaluate the precision
# of the data. Example values: monsoon, powermetrics, ds2784
'identifier': identifier,
# The instantaneous power (voltage * current) reading in milliwatts at
# each sample.
'power_samples_mw': [mw0, mw1, ..., mwN],
# The full system energy consumption during the sampling period in
# milliwatt hours. May be estimated by integrating power samples or may
# be exact on supported hardware.
'energy_consumption_mwh': mwh,
# The target application's energy consumption during the sampling period
# in milliwatt hours. Should be returned iff
# CanMeasurePerApplicationPower() return true.
'application_energy_consumption_mwh': mwh,
# A platform-specific dictionary of additional details about the
# utilization of individual hardware components.
component_utilization: {
# Platform-specific data not attributed to any particular hardware
# component.
whole_package: {
# Device-specific onboard temperature sensor.
'average_temperature_c': c,
...
}
...
}
}
"""
return self._platform_backend.StopMonitoringPower()