| Index: build/android/pylib/perf/perf_control.py
 | 
| diff --git a/build/android/pylib/perf/perf_control.py b/build/android/pylib/perf/perf_control.py
 | 
| index af1d52c3880e5dacf53e363c7ea12a4cf36f4ad7..d95d7b76bb017e86e3c4c98dfbdfa43a989d418d 100644
 | 
| --- a/build/android/pylib/perf/perf_control.py
 | 
| +++ b/build/android/pylib/perf/perf_control.py
 | 
| @@ -1,156 +1,8 @@
 | 
| -# Copyright 2013 The Chromium Authors. All rights reserved.
 | 
| +# Copyright 2015 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 atexit
 | 
| -import logging
 | 
| +# pylint: disable=unused-wildcard-import
 | 
| +# pylint: disable=wildcard-import
 | 
|  
 | 
| -from devil.android import device_errors
 | 
| -
 | 
| -
 | 
| -class PerfControl(object):
 | 
| -  """Provides methods for setting the performance mode of a device."""
 | 
| -  _CPU_PATH = '/sys/devices/system/cpu'
 | 
| -  _KERNEL_MAX = '/sys/devices/system/cpu/kernel_max'
 | 
| -
 | 
| -  def __init__(self, device):
 | 
| -    self._device = device
 | 
| -    # this will raise an AdbCommandFailedError if no CPU files are found
 | 
| -    self._cpu_files = self._device.RunShellCommand(
 | 
| -        'ls -d cpu[0-9]*', cwd=self._CPU_PATH, check_return=True, as_root=True)
 | 
| -    assert self._cpu_files, 'Failed to detect CPUs.'
 | 
| -    self._cpu_file_list = ' '.join(self._cpu_files)
 | 
| -    logging.info('CPUs found: %s', self._cpu_file_list)
 | 
| -    self._have_mpdecision = self._device.FileExists('/system/bin/mpdecision')
 | 
| -
 | 
| -  def SetHighPerfMode(self):
 | 
| -    """Sets the highest stable performance mode for the device."""
 | 
| -    try:
 | 
| -      self._device.EnableRoot()
 | 
| -    except device_errors.CommandFailedError:
 | 
| -      message = 'Need root for performance mode. Results may be NOISY!!'
 | 
| -      logging.warning(message)
 | 
| -      # Add an additional warning at exit, such that it's clear that any results
 | 
| -      # may be different/noisy (due to the lack of intended performance mode).
 | 
| -      atexit.register(logging.warning, message)
 | 
| -      return
 | 
| -
 | 
| -    product_model = self._device.product_model
 | 
| -    # TODO(epenner): Enable on all devices (http://crbug.com/383566)
 | 
| -    if 'Nexus 4' == product_model:
 | 
| -      self._ForceAllCpusOnline(True)
 | 
| -      if not self._AllCpusAreOnline():
 | 
| -        logging.warning('Failed to force CPUs online. Results may be NOISY!')
 | 
| -      self._SetScalingGovernorInternal('performance')
 | 
| -    elif 'Nexus 5' == product_model:
 | 
| -      self._ForceAllCpusOnline(True)
 | 
| -      if not self._AllCpusAreOnline():
 | 
| -        logging.warning('Failed to force CPUs online. Results may be NOISY!')
 | 
| -      self._SetScalingGovernorInternal('performance')
 | 
| -      self._SetScalingMaxFreq(1190400)
 | 
| -      self._SetMaxGpuClock(200000000)
 | 
| -    else:
 | 
| -      self._SetScalingGovernorInternal('performance')
 | 
| -
 | 
| -  def SetPerfProfilingMode(self):
 | 
| -    """Enables all cores for reliable perf profiling."""
 | 
| -    self._ForceAllCpusOnline(True)
 | 
| -    self._SetScalingGovernorInternal('performance')
 | 
| -    if not self._AllCpusAreOnline():
 | 
| -      if not self._device.HasRoot():
 | 
| -        raise RuntimeError('Need root to force CPUs online.')
 | 
| -      raise RuntimeError('Failed to force CPUs online.')
 | 
| -
 | 
| -  def SetDefaultPerfMode(self):
 | 
| -    """Sets the performance mode for the device to its default mode."""
 | 
| -    if not self._device.HasRoot():
 | 
| -      return
 | 
| -    product_model = self._device.product_model
 | 
| -    if 'Nexus 5' == product_model:
 | 
| -      if self._AllCpusAreOnline():
 | 
| -        self._SetScalingMaxFreq(2265600)
 | 
| -        self._SetMaxGpuClock(450000000)
 | 
| -
 | 
| -    governor_mode = {
 | 
| -        'GT-I9300': 'pegasusq',
 | 
| -        'Galaxy Nexus': 'interactive',
 | 
| -        'Nexus 4': 'ondemand',
 | 
| -        'Nexus 5': 'ondemand',
 | 
| -        'Nexus 7': 'interactive',
 | 
| -        'Nexus 10': 'interactive'
 | 
| -    }.get(product_model, 'ondemand')
 | 
| -    self._SetScalingGovernorInternal(governor_mode)
 | 
| -    self._ForceAllCpusOnline(False)
 | 
| -
 | 
| -  def GetCpuInfo(self):
 | 
| -    online = (output.rstrip() == '1' and status == 0
 | 
| -              for (_, output, status) in self._ForEachCpu('cat "$CPU/online"'))
 | 
| -    governor = (output.rstrip() if status == 0 else None
 | 
| -                for (_, output, status)
 | 
| -                in self._ForEachCpu('cat "$CPU/cpufreq/scaling_governor"'))
 | 
| -    return zip(self._cpu_files, online, governor)
 | 
| -
 | 
| -  def _ForEachCpu(self, cmd):
 | 
| -    script = '; '.join([
 | 
| -        'for CPU in %s' % self._cpu_file_list,
 | 
| -        'do %s' % cmd,
 | 
| -        'echo -n "%~%$?%~%"',
 | 
| -        'done'
 | 
| -    ])
 | 
| -    output = self._device.RunShellCommand(
 | 
| -        script, cwd=self._CPU_PATH, check_return=True, as_root=True)
 | 
| -    output = '\n'.join(output).split('%~%')
 | 
| -    return zip(self._cpu_files, output[0::2], (int(c) for c in output[1::2]))
 | 
| -
 | 
| -  def _WriteEachCpuFile(self, path, value):
 | 
| -    results = self._ForEachCpu(
 | 
| -        'test -e "$CPU/{path}" && echo {value} > "$CPU/{path}"'.format(
 | 
| -            path=path, value=value))
 | 
| -    cpus = ' '.join(cpu for (cpu, _, status) in results if status == 0)
 | 
| -    if cpus:
 | 
| -      logging.info('Successfully set %s to %r on: %s', path, value, cpus)
 | 
| -    else:
 | 
| -      logging.warning('Failed to set %s to %r on any cpus', path, value)
 | 
| -
 | 
| -  def _SetScalingGovernorInternal(self, value):
 | 
| -    self._WriteEachCpuFile('cpufreq/scaling_governor', value)
 | 
| -
 | 
| -  def _SetScalingMaxFreq(self, value):
 | 
| -    self._WriteEachCpuFile('cpufreq/scaling_max_freq', '%d' % value)
 | 
| -
 | 
| -  def _SetMaxGpuClock(self, value):
 | 
| -    self._device.WriteFile('/sys/class/kgsl/kgsl-3d0/max_gpuclk',
 | 
| -                           str(value),
 | 
| -                           as_root=True)
 | 
| -
 | 
| -  def _AllCpusAreOnline(self):
 | 
| -    results = self._ForEachCpu('cat "$CPU/online"')
 | 
| -    # TODO(epenner): Investigate why file may be missing
 | 
| -    # (http://crbug.com/397118)
 | 
| -    return all(output.rstrip() == '1' and status == 0
 | 
| -               for (cpu, output, status) in results
 | 
| -               if cpu != 'cpu0')
 | 
| -
 | 
| -  def _ForceAllCpusOnline(self, force_online):
 | 
| -    """Enable all CPUs on a device.
 | 
| -
 | 
| -    Some vendors (or only Qualcomm?) hot-plug their CPUs, which can add noise
 | 
| -    to measurements:
 | 
| -    - In perf, samples are only taken for the CPUs that are online when the
 | 
| -      measurement is started.
 | 
| -    - The scaling governor can't be set for an offline CPU and frequency scaling
 | 
| -      on newly enabled CPUs adds noise to both perf and tracing measurements.
 | 
| -
 | 
| -    It appears Qualcomm is the only vendor that hot-plugs CPUs, and on Qualcomm
 | 
| -    this is done by "mpdecision".
 | 
| -
 | 
| -    """
 | 
| -    if self._have_mpdecision:
 | 
| -      script = 'stop mpdecision' if force_online else 'start mpdecision'
 | 
| -      self._device.RunShellCommand(script, check_return=True, as_root=True)
 | 
| -
 | 
| -    if not self._have_mpdecision and not self._AllCpusAreOnline():
 | 
| -      logging.warning('Unexpected cpu hot plugging detected.')
 | 
| -
 | 
| -    if force_online:
 | 
| -      self._ForEachCpu('echo 1 > "$CPU/online"')
 | 
| +from devil.android.perf.perf_control import *
 | 
| 
 |