| 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 ede131789d70faca081d3810e5ccafb659adfb07..73cf95c53608591365b0335ff1aca2218f03d4d4 100644 | 
| --- a/build/android/pylib/perf/perf_control.py | 
| +++ b/build/android/pylib/perf/perf_control.py | 
| @@ -10,9 +10,7 @@ from pylib.device import device_utils | 
|  | 
| class PerfControl(object): | 
| """Provides methods for setting the performance mode of a device.""" | 
| -  _SCALING_GOVERNOR_FMT = ( | 
| -      '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor') | 
| -  _CPU_ONLINE_FMT = '/sys/devices/system/cpu/cpu%d/online' | 
| +  _CPU_PATH = '/sys/devices/system/cpu' | 
| _KERNEL_MAX = '/sys/devices/system/cpu/kernel_max' | 
|  | 
| def __init__(self, device): | 
| @@ -20,11 +18,12 @@ class PerfControl(object): | 
| if isinstance(device, android_commands.AndroidCommands): | 
| device = device_utils.DeviceUtils(device) | 
| self._device = device | 
| -    cpu_files = self._device.RunShellCommand( | 
| -      'ls -d /sys/devices/system/cpu/cpu[0-9]*') | 
| -    self._num_cpu_cores = len(cpu_files) | 
| -    assert self._num_cpu_cores > 0, 'Failed to detect CPUs.' | 
| -    logging.info('Number of CPUs: %d', self._num_cpu_cores) | 
| +    # this will raise an AdbShellCommandFailedError 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): | 
| @@ -84,22 +83,41 @@ class PerfControl(object): | 
| 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') | 
| + | 
| def _SetScalingGovernorInternal(self, value): | 
| -    cpu_cores = ' '.join([str(x) for x in range(self._num_cpu_cores)]) | 
| -    script = ('for CPU in %s; do\n' | 
| -        '  FILE="/sys/devices/system/cpu/cpu$CPU/cpufreq/scaling_governor"\n' | 
| -        '  test -e $FILE && echo %s > $FILE\n' | 
| -        'done\n') % (cpu_cores, value) | 
| -    logging.info('Setting scaling governor mode: %s', value) | 
| -    self._device.RunShellCommand(script, as_root=True) | 
| +    self._WriteEachCpuFile('cpufreq/scaling_governor', value) | 
|  | 
| def _SetScalingMaxFreq(self, value): | 
| -    cpu_cores = ' '.join([str(x) for x in range(self._num_cpu_cores)]) | 
| -    script = ('for CPU in %s; do\n' | 
| -        '  FILE="/sys/devices/system/cpu/cpu$CPU/cpufreq/scaling_max_freq"\n' | 
| -        '  test -e $FILE && echo %d > $FILE\n' | 
| -        'done\n') % (cpu_cores, value) | 
| -    self._device.RunShellCommand(script, as_root=True) | 
| +    self._WriteEachCpuFile('cpufreq/scaling_max_freq', '%d' % value) | 
|  | 
| def _SetMaxGpuClock(self, value): | 
| self._device.WriteFile('/sys/class/kgsl/kgsl-3d0/max_gpuclk', | 
| @@ -107,14 +125,12 @@ class PerfControl(object): | 
| as_root=True) | 
|  | 
| def _AllCpusAreOnline(self): | 
| -    for cpu in range(1, self._num_cpu_cores): | 
| -      online_path = PerfControl._CPU_ONLINE_FMT % cpu | 
| -      # TODO(epenner): Investigate why file may be missing | 
| -      # (http://crbug.com/397118) | 
| -      if not self._device.FileExists(online_path) or \ | 
| -            self._device.ReadFile(online_path)[0] == '0': | 
| -        return False | 
| -    return True | 
| +    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. | 
| @@ -132,15 +148,10 @@ class PerfControl(object): | 
| """ | 
| if self._have_mpdecision: | 
| script = 'stop mpdecision' if force_online else 'start mpdecision' | 
| -      self._device.RunShellCommand(script, as_root=True) | 
| +      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 not force_online: | 
| -      return | 
| - | 
| -    for cpu in range(self._num_cpu_cores): | 
| -      online_path = PerfControl._CPU_ONLINE_FMT % cpu | 
| -      self._device.WriteFile(online_path, '1', as_root=True) | 
| - | 
| +    if force_online: | 
| +      self._ForEachCpu('echo 1 > "$CPU/online"') | 
|  |