| Index: tools/telemetry/telemetry/internal/platform/android_platform_backend.py
|
| diff --git a/tools/telemetry/telemetry/internal/platform/android_platform_backend.py b/tools/telemetry/telemetry/internal/platform/android_platform_backend.py
|
| index dc93b3062b0beea845ab095754244023b6c78d81..eaeb52e6969d55b66e41255ee010d7c1e3447021 100644
|
| --- a/tools/telemetry/telemetry/internal/platform/android_platform_backend.py
|
| +++ b/tools/telemetry/telemetry/internal/platform/android_platform_backend.py
|
| @@ -27,6 +27,7 @@ from telemetry.internal.platform.power_monitor import power_monitor_controller
|
| from telemetry.internal.platform.profiler import android_prebuilt_profiler_helper
|
| from telemetry.internal.util import exception_formatter
|
| from telemetry.internal.util import external_modules
|
| +from telemetry.util import process_statistic_timeline_data
|
|
|
| psutil = external_modules.ImportOptionalModule('psutil')
|
| util.AddDirToPythonPath(util.GetChromiumSrcDir(),
|
| @@ -264,7 +265,11 @@ class AndroidPlatformBackend(
|
| if not self._can_access_protected_file_contents:
|
| logging.warning('CPU stats cannot be retrieved on non-rooted device.')
|
| return {}
|
| - return super(AndroidPlatformBackend, self).GetCpuStats(pid)
|
| + results = super(AndroidPlatformBackend, self).GetCpuStats(pid)
|
| + idle_wakeup_count = self._GetIdleWakeupCount(pid)
|
| + if idle_wakeup_count:
|
| + results.update({'IdleWakeupCount': idle_wakeup_count})
|
| + return results
|
|
|
| def GetCpuTimestamp(self):
|
| if not self._can_access_protected_file_contents:
|
| @@ -432,6 +437,9 @@ class AndroidPlatformBackend(
|
| def CanMonitorPower(self):
|
| return self._power_monitor.CanMonitorPower()
|
|
|
| + def CanMeasureIdleWakeUps(self):
|
| + return True
|
| +
|
| def StartMonitoringPower(self, browser):
|
| self._power_monitor.StartMonitoringPower(browser)
|
|
|
| @@ -454,9 +462,14 @@ class AndroidPlatformBackend(
|
| return self._device.ReadFile(fname, as_root=True)
|
|
|
| def GetPsOutput(self, columns, pid=None):
|
| + return self._GetPsOutput(columns=columns, pid=pid)
|
| +
|
| + def _GetPsOutput(self, columns, list_threads=False, pid=None):
|
| assert columns == ['pid', 'name'] or columns == ['pid'], \
|
| 'Only know how to return pid and name. Requested: ' + columns
|
| command = 'ps'
|
| + if list_threads:
|
| + command += ' -t'
|
| if pid:
|
| command += ' -p %d' % pid
|
| ps = self._device.RunShellCommand(command, large_output=True)[1:]
|
| @@ -699,6 +712,42 @@ class AndroidPlatformBackend(
|
| """
|
| return '/data/data/%s/' % package
|
|
|
| +
|
| + def _GetIdleWakeupCount(self, pid):
|
| + """Find the given pid in the timer_stats and sum up the wake-up count.
|
| +
|
| + Each row is in the form of: wake_up_count, pid process_name reason
|
| + Due to possibly multiple reasons, a given pid can appear in multiple rows.
|
| + """
|
| + contents = self.GetFileContents('/proc/timer_stats')
|
| + if not contents:
|
| + return None
|
| + count = 0
|
| + split_lines = contents.splitlines()
|
| + matching_pids = []
|
| + # The pid listed by timer_stats is the *kernel* pid (potentially different
|
| + # for each thread), which may differ from the provided process pid. Use ps
|
| + # to map each thread pid back to the proper process pid (tgid).
|
| + for matching_pid in self._GetPsOutput(['pid'], list_threads=True,
|
| + pid=int(pid)):
|
| + matching_pids.append(matching_pid[0])
|
| + for line in split_lines[:-1]:
|
| + line_split = line.split(',', 1)
|
| + if len(line_split) < 2:
|
| + continue
|
| + count_str, rest_str = line_split
|
| + current_pid = rest_str.strip().split(' ')[0]
|
| + if current_pid == pid or current_pid in matching_pids:
|
| + # The "D" suffix on the count indicates a "deferrable" timer.
|
| + count += int(count_str.strip().rstrip('D'))
|
| + return process_statistic_timeline_data.IdleWakeupTimelineData(pid, count)
|
| +
|
| + def _EnableTimerStatsCollection(self, enable):
|
| + """Writes to /proc/timer_stats to start/stop measuring process wakeups."""
|
| + parameter = 1 if enable else 0
|
| + cmd = 'echo %d > /proc/timer_stats' % parameter
|
| + self._device.RunShellCommand(cmd, as_root=True)
|
| +
|
| def SetDebugApp(self, package):
|
| """Set application to debugging.
|
|
|
|
|