| # Copyright 2015 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import optparse |
| import os |
| import re |
| |
| import py_utils |
| |
| from profile_chrome import util |
| from systrace import trace_result |
| from systrace import tracing_agents |
| |
| |
| _DDMS_SAMPLING_FREQUENCY_US = 100 |
| |
| |
| class DdmsAgent(tracing_agents.TracingAgent): |
| def __init__(self, device, package_info): |
| tracing_agents.TracingAgent.__init__(self) |
| self._device = device |
| self._package = package_info.package |
| self._output_file = None |
| self._supports_sampling = self._SupportsSampling() |
| |
| def __repr__(self): |
| return 'ddms profile' |
| |
| def _SupportsSampling(self): |
| for line in self._device.RunShellCommand( |
| ['am', '--help'], check_return=True): |
| if re.match(r'.*am profile start.*--sampling', line): |
| return True |
| return False |
| |
| @py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT) |
| def StartAgentTracing(self, config, timeout=None): |
| self._output_file = ( |
| '/data/local/tmp/ddms-profile-%s' % util.GetTraceTimestamp()) |
| cmd = ['am', 'profile', 'start'] |
| if self._supports_sampling: |
| cmd.extend(['--sampling', str(_DDMS_SAMPLING_FREQUENCY_US)]) |
| cmd.extend([self._package, self._output_file]) |
| self._device.RunShellCommand(cmd, check_return=True) |
| return True |
| |
| @py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT) |
| def StopAgentTracing(self, timeout=None): |
| self._device.RunShellCommand( |
| ['am', 'profile', 'stop', self._package], check_return=True) |
| return True |
| |
| @py_utils.Timeout(tracing_agents.GET_RESULTS_TIMEOUT) |
| def GetResults(self, timeout=None): |
| with open(self._PullTrace(), 'r') as f: |
| trace_data = f.read() |
| return trace_result.TraceResult('ddms', trace_data) |
| |
| def _PullTrace(self): |
| if not self._output_file: |
| return None |
| |
| host_file = os.path.join( |
| os.path.curdir, os.path.basename(self._output_file)) |
| self._device.PullFile(self._output_file, host_file) |
| return host_file |
| |
| def SupportsExplicitClockSync(self): |
| return False |
| |
| def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback): |
| # pylint: disable=unused-argument |
| assert self.SupportsExplicitClockSync(), ('Clock sync marker cannot be ' |
| 'recorded since explicit clock sync is not supported.') |
| |
| |
| class DdmsConfig(tracing_agents.TracingConfig): |
| def __init__(self, device, package_info, ddms): |
| tracing_agents.TracingConfig.__init__(self) |
| self.device = device |
| self.package_info = package_info |
| self.ddms = ddms |
| |
| |
| def try_create_agent(config): |
| if config.ddms: |
| return DdmsAgent(config.device, config.package_info) |
| return None |
| |
| def add_options(parser): |
| options = optparse.OptionGroup(parser, 'Java tracing') |
| options.add_option('--ddms', help='Trace Java execution using DDMS ' |
| 'sampling.', action='store_true') |
| return options |
| |
| def get_config(options): |
| return DdmsConfig(options.device, options.package_info, options.ddms) |