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.
4
5import os
6import StringIO
7import subprocess
8import zipfile
9
10from telemetry.core import util
11from telemetry.core.backends.chrome import android_browser_finder
12from telemetry.core.platform import profiler
13from telemetry.core.platform import tracing_options
14
15_SYSTRACE_CATEGORIES = [
16    'gfx',
17    'input',
18    'view',
19    'sched',
20    'freq',
21]
22
23class AndroidSystraceProfiler(profiler.Profiler):
24  """Collects a Systrace on Android."""
25
26  def __init__(self, browser_backend, platform_backend, output_path, state):
27    super(AndroidSystraceProfiler, self).__init__(
28        browser_backend, platform_backend, output_path, state)
29    assert self._browser_backend.supports_tracing
30    self._output_path = output_path + '-trace.zip'
31    self._systrace_output_path = output_path + '.systrace'
32
33    # Use telemetry's own tracing backend instead the combined mode in
34    # adb_profile_chrome because some benchmarks also do tracing of their own
35    # and the two methods conflict.
36    options = tracing_options.TracingOptions()
37    options.enable_chrome_trace = True
38    self._browser_backend.StartTracing(options, timeout=10)
39    self._profiler = subprocess.Popen(
40        ['python', os.path.join(util.GetChromiumSrcDir(), 'tools',
41                                'profile_chrome.py'),
42         '--categories', '', '--continuous', '--output',
43         self._systrace_output_path, '--json', '--systrace',
44         ','.join(_SYSTRACE_CATEGORIES)],
45        stdin=subprocess.PIPE, stdout=subprocess.PIPE)
46
47  @classmethod
48  def name(cls):
49    return 'android-systrace'
50
51  @classmethod
52  def is_supported(cls, browser_type):
53    if browser_type == 'any':
54      return android_browser_finder.CanFindAvailableBrowsers()
55    return browser_type.startswith('android')
56
57  def CollectProfile(self):
58    self._profiler.communicate(input='\n')
59    trace_result = self._browser_backend.StopTracing()
60
61    trace_file = StringIO.StringIO()
62    trace_result.Serialize(trace_file)
63
64    # Merge the chrome and systraces into a zip file.
65    with zipfile.ZipFile(self._output_path, 'w', zipfile.ZIP_DEFLATED) as z:
66      z.writestr('trace.json', trace_file.getvalue())
67      z.write(self._systrace_output_path, 'systrace')
68      os.unlink(self._systrace_output_path)
69
70    print 'Systrace saved as %s' % self._output_path
71    print 'To view, open in chrome://tracing'
72    return [self._output_path]
73