1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
11 from telemetry.core.platform import profiler
12 from telemetry.core.platform.profiler import android_prebuilt_profiler_helper
14 _TCP_DUMP_BASE_OPTS = ['-i', 'any', '-p', '-s', '0', '-w']
17 class _TCPDumpProfilerAndroid(object):
18 """An internal class to collect TCP dumps on android.
20 This profiler uses pre-built binaries from AOSP.
21 See more details in prebuilt/android/README.txt.
24 _DEVICE_DUMP_FILE = '/sdcard/tcpdump_profiles/capture.pcap'
26 def __init__(self, adb, output_path):
28 self._output_path = output_path
29 self._adb.RunShellCommand('mkdir -p ' +
30 os.path.dirname(self._DEVICE_DUMP_FILE))
31 self._proc = subprocess.Popen(
32 ['adb', '-s', self._adb.device_serial(),
33 'shell', android_prebuilt_profiler_helper.GetDevicePath('tcpdump')] +
35 [self._DEVICE_DUMP_FILE])
37 def CollectProfile(self):
38 tcpdump_pid = self._adb.ExtractPid('tcpdump')
39 if not tcpdump_pid or not tcpdump_pid[0]:
40 raise Exception('Unable to find TCPDump. Check your device is rooted '
41 'and tcpdump is installed at ' +
42 android_prebuilt_profiler_helper.GetDevicePath('tcpdump'))
43 self._adb.RunShellCommand('kill -term ' + tcpdump_pid[0])
44 self._proc.terminate()
45 host_dump = os.path.join(self._output_path,
46 os.path.basename(self._DEVICE_DUMP_FILE))
47 self._adb.device().old_interface.Adb().Pull(self._DEVICE_DUMP_FILE,
49 print 'TCP dump available at: %s ' % host_dump
50 print 'Use Wireshark to open it.'
54 class _TCPDumpProfilerLinux(object):
55 """An internal class to collect TCP dumps on linux desktop."""
57 _DUMP_FILE = 'capture.pcap'
59 def __init__(self, output_path):
60 if not os.path.exists(output_path):
61 os.makedirs(output_path)
62 self._dump_file = os.path.join(output_path, self._DUMP_FILE)
63 self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0)
65 self._proc = subprocess.Popen(
66 ['tcpdump'] + _TCP_DUMP_BASE_OPTS + [self._dump_file],
67 stdout=self._tmp_output_file, stderr=subprocess.STDOUT)
69 raise Exception('Unable to execute TCPDump, please check your '
70 'installation. ' + str(e))
72 def CollectProfile(self):
73 self._proc.send_signal(signal.SIGINT)
74 exit_code = self._proc.wait()
78 'tcpdump failed with exit code %d. Output:\n%s' %
79 (exit_code, self._GetStdOut()))
81 self._tmp_output_file.close()
82 print 'TCP dump available at: ', self._dump_file
83 print 'Use Wireshark to open it.'
84 return self._dump_file
87 self._tmp_output_file.flush()
89 with open(self._tmp_output_file.name) as f:
95 class TCPDumpProfiler(profiler.Profiler):
96 """A Factory to instantiate the platform-specific profiler."""
97 def __init__(self, browser_backend, platform_backend, output_path, state):
98 super(TCPDumpProfiler, self).__init__(
99 browser_backend, platform_backend, output_path, state)
100 if platform_backend.GetOSName() == 'android':
101 android_prebuilt_profiler_helper.InstallOnDevice(
102 browser_backend.adb.device(), 'tcpdump')
103 self._platform_profiler = _TCPDumpProfilerAndroid(
104 browser_backend.adb, output_path)
106 self._platform_profiler = _TCPDumpProfilerLinux(output_path)
113 def is_supported(cls, browser_type):
114 if browser_type.startswith('cros'):
116 if sys.platform.startswith('linux'):
118 return browser_type.startswith('android')
120 def CollectProfile(self):
121 return self._platform_profiler.CollectProfile()