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