1 # Copyright 2014 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.
8 from profile_chrome
import controllers
9 from profile_chrome
import util
11 from pylib
import cmd_helper
15 # Compress the trace before sending it over USB.
17 # Use a large trace buffer to increase the polling interval.
21 # Interval in seconds for sampling systrace data.
22 _SYSTRACE_INTERVAL
= 15
25 class SystraceController(controllers
.BaseController
):
26 def __init__(self
, device
, categories
, ring_buffer
):
27 controllers
.BaseController
.__init
__(self
)
29 self
._categories
= categories
30 self
._ring
_buffer
= ring_buffer
31 self
._done
= threading
.Event()
33 self
._trace
_data
= None
39 def GetCategories(device
):
40 return device
.RunShellCommand('atrace --list_categories')
42 def StartTracing(self
, _
):
43 self
._thread
= threading
.Thread(target
=self
._CollectData
)
46 def StopTracing(self
):
53 output_name
= 'systrace-%s' % util
.GetTraceTimestamp()
54 with
open(output_name
, 'w') as out
:
55 out
.write(self
._trace
_data
)
58 def _RunATraceCommand(self
, command
):
59 # We use a separate interface to adb because the one from AndroidCommands
61 # TODO(jbudorick) Look at providing a way to unhandroll this once the
62 # adb rewrite has fully landed.
63 device_param
= (['-s', str(self
._device
)] if str(self
._device
) else [])
64 cmd
= ['adb'] + device_param
+ ['shell', 'atrace', '--%s' % command
] + \
65 _SYSTRACE_OPTIONS
+ self
._categories
66 return cmd_helper
.GetCmdOutput(cmd
)
68 def _CollectData(self
):
70 self
._RunATraceCommand
('async_start')
72 while not self
._done
.is_set():
73 self
._done
.wait(_SYSTRACE_INTERVAL
)
74 if not self
._ring
_buffer
or self
._done
.is_set():
76 self
._DecodeTraceData
(self
._RunATraceCommand
('async_dump')))
79 self
._DecodeTraceData
(self
._RunATraceCommand
('async_stop')))
80 self
._trace
_data
= ''.join([zlib
.decompress(d
) for d
in trace_data
])
83 def _DecodeTraceData(trace_data
):
85 trace_start
= trace_data
.index('TRACE:')
87 raise RuntimeError('Systrace start marker not found')
88 trace_data
= trace_data
[trace_start
+ 6:]
90 # Collapse CRLFs that are added by adb shell.
91 if trace_data
.startswith('\r\n'):
92 trace_data
= trace_data
.replace('\r\n', '\n')
94 # Skip the initial newline.