Update sdk/platform-tools to version 26.0.0.
[android_tools.git] / sdk / platform-tools / systrace / catapult / telemetry / telemetry / internal / platform / profiler / tcpdump_profiler.py
bloba8527cb0417d593fa50c4d4e436f2f19f9f8091c
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.
5 import os
6 import signal
7 import subprocess
8 import sys
9 import tempfile
11 from telemetry.internal.platform import profiler
12 from telemetry.internal.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.
22 """
24 _DEVICE_DUMP_FILE = '/sdcard/tcpdump_profiles/capture.pcap'
26 def __init__(self, device, output_path):
27 self._device = device
28 self._output_path = output_path
29 self._device.RunShellCommand(
30 ['mkdir', '-p', os.path.dirname(self._DEVICE_DUMP_FILE)],
31 check_return=True)
32 self._proc = subprocess.Popen(
33 [self._device.adb.GetAdbPath(),
34 '-s', self._device.adb.GetDeviceSerial(),
35 'shell', android_prebuilt_profiler_helper.GetDevicePath('tcpdump')] +
36 _TCP_DUMP_BASE_OPTS +
37 [self._DEVICE_DUMP_FILE])
39 def CollectProfile(self):
40 tcpdump_pid = self._device.GetPids('tcpdump')
41 if not tcpdump_pid or not 'tcpdump' in tcpdump_pid:
42 raise Exception('Unable to find TCPDump. Check your device is rooted '
43 'and tcpdump is installed at ' +
44 android_prebuilt_profiler_helper.GetDevicePath('tcpdump'))
45 if len(tcpdump_pid['tcpdump']) > 1:
46 raise Exception(
47 'At most one instance of process tcpdump expected but found pids: '
48 '%s' % tcpdump_pid)
49 tcpdump_pid = int(tcpdump_pid['tcpdump'][0])
50 self._device.RunShellCommand(
51 ['kill', '-term', str(tcpdump_pid)], check_return=True)
52 self._proc.terminate()
53 host_dump = os.path.join(self._output_path,
54 os.path.basename(self._DEVICE_DUMP_FILE))
55 self._device.PullFile(self._DEVICE_DUMP_FILE, host_dump)
56 print 'TCP dump available at: %s ' % host_dump
57 print 'Use Wireshark to open it.'
58 return host_dump
61 class _TCPDumpProfilerLinux(object):
62 """An internal class to collect TCP dumps on linux desktop."""
64 _DUMP_FILE = 'capture.pcap'
66 def __init__(self, output_path):
67 if not os.path.exists(output_path):
68 os.makedirs(output_path)
69 self._dump_file = os.path.join(output_path, self._DUMP_FILE)
70 self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0)
71 try:
72 self._proc = subprocess.Popen(
73 ['tcpdump'] + _TCP_DUMP_BASE_OPTS + [self._dump_file],
74 stdout=self._tmp_output_file, stderr=subprocess.STDOUT)
75 except OSError as e:
76 raise Exception('Unable to execute TCPDump, please check your '
77 'installation. ' + str(e))
79 def CollectProfile(self):
80 self._proc.send_signal(signal.SIGINT)
81 exit_code = self._proc.wait()
82 try:
83 if exit_code:
84 raise Exception(
85 'tcpdump failed with exit code %d. Output:\n%s' %
86 (exit_code, self._GetStdOut()))
87 finally:
88 self._tmp_output_file.close()
89 print 'TCP dump available at: ', self._dump_file
90 print 'Use Wireshark to open it.'
91 return self._dump_file
93 def _GetStdOut(self):
94 self._tmp_output_file.flush()
95 try:
96 with open(self._tmp_output_file.name) as f:
97 return f.read()
98 except IOError:
99 return ''
102 class TCPDumpProfiler(profiler.Profiler):
103 """A Factory to instantiate the platform-specific profiler."""
104 def __init__(self, browser_backend, platform_backend, output_path, state):
105 super(TCPDumpProfiler, self).__init__(
106 browser_backend, platform_backend, output_path, state)
107 if platform_backend.GetOSName() == 'android':
108 android_prebuilt_profiler_helper.InstallOnDevice(
109 browser_backend.device, 'tcpdump')
110 self._platform_profiler = _TCPDumpProfilerAndroid(
111 browser_backend.device, output_path)
112 else:
113 self._platform_profiler = _TCPDumpProfilerLinux(output_path)
115 @classmethod
116 def name(cls):
117 return 'tcpdump'
119 @classmethod
120 def is_supported(cls, browser_type):
121 if browser_type.startswith('cros'):
122 return False
123 if sys.platform.startswith('linux'):
124 return True
125 return browser_type.startswith('android')
127 def CollectProfile(self):
128 return self._platform_profiler.CollectProfile()