• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 os
6
7from telemetry.internal.backends.chrome import android_browser_finder
8from telemetry.internal.platform import profiler
9
10import py_utils
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      # Note: command must be passed as a string to expand wildcards.
29      self._browser_backend.device.RunShellCommand(
30          'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*'),
31          check_return=True, shell=True)
32    else:
33      self._browser_backend.device.RunShellCommand(
34          ['mkdir', '-p', self._DEFAULT_DEVICE_DIR], check_return=True)
35      self._browser_backend.device.RunShellCommand(
36          ['chmod', '777', self._DEFAULT_DEVICE_DIR], check_return=True)
37
38    self._trace_files = []
39    for pid in self._GetProcessOutputFileMap().iterkeys():
40      device_dump_file = '%s/%s.trace' % (self._DEFAULT_DEVICE_DIR, pid)
41      self._trace_files.append((pid, device_dump_file))
42      self._browser_backend.device.RunShellCommand(
43          ['am', 'profile', str(pid), 'start', device_dump_file],
44          check_return=True)
45
46  @classmethod
47  def name(cls):
48    return 'android-traceview'
49
50  @classmethod
51  def is_supported(cls, browser_type):
52    if browser_type == 'any':
53      return android_browser_finder.CanFindAvailableBrowsers()
54    return browser_type.startswith('android')
55
56  def CollectProfile(self):
57    output_files = []
58    for pid, trace_file in self._trace_files:
59      self._browser_backend.device.RunShellCommand(
60          ['am', 'profile', str(pid), 'stop'], check_return=True)
61      # pylint: disable=cell-var-from-loop
62      py_utils.WaitFor(lambda: self._FileSize(trace_file) > 0, timeout=10)
63      output_files.append(trace_file)
64    self._browser_backend.device.PullFile(
65        self._DEFAULT_DEVICE_DIR, self._output_path)
66    # Note: command must be passed as a string to expand wildcards.
67    self._browser_backend.device.RunShellCommand(
68        'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*'),
69        check_return=True, shell=True)
70    print 'Traceview profiles available in ', self._output_path
71    print 'Use third_party/android_tools/sdk/tools/monitor '
72    print 'then use "File->Open File" to visualize them.'
73    return output_files
74
75  def _FileSize(self, file_name):
76    try:
77      return self._browser_backend.device.FileSize(file_name)
78    except device_errors.CommandFailedError:
79      return 0
80