aboutsummaryrefslogtreecommitdiff
path: root/catapult/systrace/systrace/tracing_agents/android_cgroup_agent.py
diff options
context:
space:
mode:
Diffstat (limited to 'catapult/systrace/systrace/tracing_agents/android_cgroup_agent.py')
-rw-r--r--catapult/systrace/systrace/tracing_agents/android_cgroup_agent.py96
1 files changed, 96 insertions, 0 deletions
diff --git a/catapult/systrace/systrace/tracing_agents/android_cgroup_agent.py b/catapult/systrace/systrace/tracing_agents/android_cgroup_agent.py
new file mode 100644
index 00000000..75e0872d
--- /dev/null
+++ b/catapult/systrace/systrace/tracing_agents/android_cgroup_agent.py
@@ -0,0 +1,96 @@
+# Copyright 2020 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.
+
+# Tracing agent that captures cgroup information from /dev/cpuset on
+# an Android device.
+
+import stat
+import py_utils
+
+from devil.android import device_utils
+from systrace import tracing_agents
+from systrace import trace_result
+
+# identify this as trace of cgroup state
+TRACE_HEADER = 'CGROUP DUMP\n'
+
+def add_options(parser): # pylint: disable=unused-argument
+ return None
+
+def try_create_agent(config):
+ if config.target != 'android':
+ return None
+ if not config.atrace_categories:
+ return None
+ # 'sched' contains cgroup events
+ if 'sched' not in config.atrace_categories:
+ return None
+ if config.from_file is not None:
+ return None
+ return AndroidCgroupAgent()
+
+def get_config(options):
+ return options
+
+def parse_proc_cgroups(cgroups, subsys):
+ for line in cgroups.split('\n'):
+ if line.startswith(subsys):
+ return line.split()[1]
+ return '-1'
+
+class AndroidCgroupAgent(tracing_agents.TracingAgent):
+ def __init__(self):
+ super(AndroidCgroupAgent, self).__init__()
+ self._config = None
+ self._device_utils = None
+ self._trace_data = ""
+
+ def __repr__(self):
+ return 'cgroup_data'
+
+ @py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
+ def StartAgentTracing(self, config, timeout=None):
+ self._config = config
+ self._device_utils = device_utils.DeviceUtils(
+ self._config.device_serial_number)
+
+ if not self._device_utils.HasRoot():
+ return False
+
+ self._trace_data += self._get_cgroup_info()
+ return True
+
+ @py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
+ def StopAgentTracing(self, timeout=None):
+ return True
+
+ @py_utils.Timeout(tracing_agents.GET_RESULTS_TIMEOUT)
+ def GetResults(self, timeout=None):
+ result = TRACE_HEADER + self._trace_data
+ return trace_result.TraceResult('cgroupDump', result)
+
+ def SupportsExplicitClockSync(self):
+ return False
+
+ def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback):
+ pass
+
+ def _get_cgroup_info(self):
+ data = []
+ CGROUP_SUBSYS = 'cpuset'
+ CGROUP_ROOT = '/dev/cpuset/'
+
+ cgroups = self._device_utils.ReadFile('/proc/cgroups')
+ header = '# cgroup task attachment\n'
+
+ root_id = parse_proc_cgroups(cgroups, CGROUP_SUBSYS)
+
+ for cgrp in self._device_utils.StatDirectory(CGROUP_ROOT):
+ if not stat.S_ISDIR(cgrp['st_mode']):
+ continue
+ tasks_file = CGROUP_ROOT + cgrp['filename'] + '/tasks'
+ tasks = self._device_utils.ReadFile(tasks_file).split('\n')
+ cgrp_info = '/%s (root=%s) : ' % (cgrp['filename'], root_id)
+ data.append(cgrp_info + ' '.join(tasks))
+ return cgroups + header + '\n'.join(data) + '\n'