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. 4 5import logging 6import os 7 8from telemetry.core import util 9from telemetry.internal.backends.chrome import android_browser_finder 10from telemetry.internal.platform import profiler 11 12try: 13 from devil.android import device_errors # pylint: disable=import-error 14except ImportError: 15 device_errors = None 16 17 18class AndroidTraceviewProfiler(profiler.Profiler): 19 """Collects a Traceview on Android.""" 20 21 _DEFAULT_DEVICE_DIR = '/data/local/tmp/traceview' 22 23 def __init__(self, browser_backend, platform_backend, output_path, state): 24 super(AndroidTraceviewProfiler, self).__init__( 25 browser_backend, platform_backend, output_path, state) 26 27 if self._browser_backend.device.FileExists(self._DEFAULT_DEVICE_DIR): 28 self._browser_backend.device.RunShellCommand( 29 'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*')) 30 else: 31 self._browser_backend.device.RunShellCommand( 32 'mkdir -p ' + self._DEFAULT_DEVICE_DIR) 33 self._browser_backend.device.RunShellCommand( 34 'chmod 777 ' + self._DEFAULT_DEVICE_DIR) 35 36 self._trace_files = [] 37 for pid in self._GetProcessOutputFileMap().iterkeys(): 38 device_dump_file = '%s/%s.trace' % (self._DEFAULT_DEVICE_DIR, pid) 39 self._trace_files.append((pid, device_dump_file)) 40 self._browser_backend.device.RunShellCommand('am profile %s start %s' % 41 (pid, device_dump_file)) 42 43 44 @classmethod 45 def name(cls): 46 return 'android-traceview' 47 48 @classmethod 49 def is_supported(cls, browser_type): 50 if browser_type == 'any': 51 return android_browser_finder.CanFindAvailableBrowsers() 52 return browser_type.startswith('android') 53 54 def CollectProfile(self): 55 output_files = [] 56 for pid, trace_file in self._trace_files: 57 self._browser_backend.device.RunShellCommand('am profile %s stop' % pid) 58 # pylint: disable=cell-var-from-loop 59 util.WaitFor(lambda: self._FileSize(trace_file) > 0, timeout=10) 60 output_files.append(trace_file) 61 try: 62 self._browser_backend.device.PullFile( 63 self._DEFAULT_DEVICE_DIR, self._output_path) 64 except: 65 logging.exception('New exception caused by DeviceUtils conversion') 66 raise 67 self._browser_backend.device.RunShellCommand( 68 'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*')) 69 print 'Traceview profiles available in ', self._output_path 70 print 'Use third_party/android_tools/sdk/tools/monitor ' 71 print 'then use "File->Open File" to visualize them.' 72 return output_files 73 74 def _FileSize(self, file_name): 75 try: 76 return self._browser_backend.device.Stat(file_name).st_size 77 except device_errors.CommandFailedError: 78 return 0 79