Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(200)

Unified Diff: tools/telemetry/telemetry/internal/platform/android_platform_backend.py

Issue 1242943005: [Android] Support idle wakeup measurement with /proc/timer_stats (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Working test Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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.

Powered by Google App Engine
This is Rietveld 408576698