Add script to extract format files
Adds a Python script which extracts all files matching:
/sys/kernel/debug/tracing/events/*/*/format
From an Android device into a directory named:
android_productname_buildid_kernelversion
(e.g. android_seed_N2F62_3.10.49)
The layout of the directory matches
/sys/kernel/debug/tracing/events except it only contains the
'format' files.
Usage:
$ .tools/extract_formats.py
$ ls
android_seed_N2F62_3.10.49
$ find . -type f | grep sched_switch
android_seed_N2F62_3.10.49/perf_trace_counters/sched_switch_with_ctrs/format
android_seed_N2F62_3.10.49/sched/sched_switch/format
Change-Id: If5beb4ea98bd7f7f710bcb6ca5d33a919339a4fc
diff --git a/tools/pull_ftrace_format_files.py b/tools/pull_ftrace_format_files.py
new file mode 100755
index 0000000..8cd27f6
--- /dev/null
+++ b/tools/pull_ftrace_format_files.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import print_function
+import argparse
+import datetime
+import os
+import subprocess
+import sys
+
+"""Pulls all format files from an Android device.
+
+Usage: ./tools/pull_ftrace_format_files.py [-s serial] [-p directory_prefix]
+"""
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+ADB_PATH = os.path.join(ROOT_DIR, 'buildtools/android_sdk/platform-tools/adb')
+
+def adb(*cmd, **kwargs):
+ serial = kwargs.get('serial', None)
+ prefix = [ADB_PATH]
+ if serial:
+ prefix += ['-s', serial]
+ cmd = prefix + list(cmd)
+ output = subprocess.check_output(cmd)
+ return output
+
+
+def get_devices():
+ # adb devices output looks like:
+ # List of devices attached
+ # 557dccd8\tdevice
+ # With a trailing newline.
+ serials = [s.split('\t')[0] for s in adb('devices').split('\n')[1:] if s]
+ return serials
+
+
+def ensure_output_directory_empty(path):
+ if os.path.isfile(path):
+ print('The output directory {} exists as a file.'.format(path))
+ sys.exit(1)
+
+ if os.path.isdir(path) and os.listdir(path):
+ print('The output directory {} exists but is not empty.'.format(path))
+ sys.exit(1)
+
+ if not os.path.isdir(path):
+ os.makedirs(path)
+
+
+def ensure_dir(path):
+ try:
+ os.makedirs(path)
+ except OSError:
+ if not os.path.isdir(path):
+ raise
+
+
+def ensure_single_device(serial):
+ serials = get_devices()
+ if serial is None and len(serials) == 1:
+ return serials[0]
+
+ if serial in serials:
+ return serial
+
+ if not serials:
+ print('No devices connected.')
+ elif serial is None:
+ print('More than one device connected, use -s.')
+ else:
+ print('No device with serial {} found.'.format(serial))
+ sys.exit(1)
+
+
+def pull_format_files(serial, output_directory):
+ # Pulling each file individually is 100x slower so we pipe all together then
+ # split them on the host.
+ cmd = "find /sys/kernel/debug/tracing/events/ " \
+ "-name format -o " \
+ "-name header_event -o " \
+ "-name header_page | " \
+ "while read f; do echo 'path:' $f; cat $f; done"
+
+ output = adb('shell', cmd, serial=serial)
+ sections = output.split('path: /sys/kernel/debug/tracing/events/')
+ for section in sections:
+ if not section:
+ continue
+ path, rest = section.split('\n', 1)
+ path = os.path.join(output_directory, path)
+ ensure_dir(os.path.dirname(path))
+ with open(path, 'wb') as f:
+ f.write(rest)
+
+
+# Produces output of the form: prefix_android_seed_N2F62_3.10.49
+def get_output_directory(prefix=None):
+ build_id = adb('shell', 'getprop', 'ro.build.id').replace('\n', '')
+ product = adb('shell', 'getprop', 'ro.build.product').replace('\n', '')
+ kernel = adb('shell', 'uname', '-r').split('-')[0]
+ parts = ['android', product, build_id, kernel]
+ if prefix:
+ parts = [prefix] + parts
+ return '_'.join(parts)
+
+
+def main():
+ parser = argparse.ArgumentParser(description='Pull format files.')
+ parser.add_argument('-p', dest='prefix', default=None,
+ help='the output directory prefix')
+ parser.add_argument('-s', dest='serial', default=None,
+ help='use device with the given serial')
+ args = parser.parse_args()
+
+ prefix = args.prefix
+ serial = args.serial
+
+ serial = ensure_single_device(serial)
+ output_directory = get_output_directory(prefix)
+
+ ensure_output_directory_empty(output_directory)
+ pull_format_files(serial, output_directory)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
+