• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2015 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 optparse
7import os
8import re
9
10import py_utils
11
12from devil.android import flag_changer
13from devil.android.constants import webapk
14from devil.android.perf import cache_control
15from devil.android.sdk import intent
16
17from systrace import trace_result
18from systrace import tracing_agents
19
20
21class ChromeStartupTracingAgent(tracing_agents.TracingAgent):
22  def __init__(self, device, package_info, webapk_package, cold, url,
23               trace_time=None):
24    tracing_agents.TracingAgent.__init__(self)
25    self._device = device
26    self._package_info = package_info
27    self._webapk_package = webapk_package
28    self._cold = cold
29    self._logcat_monitor = self._device.GetLogcatMonitor()
30    self._url = url
31    self._trace_time = trace_time
32    self._trace_file = None
33    self._trace_finish_re = re.compile(r' Completed startup tracing to (.*)')
34    self._flag_changer = flag_changer.FlagChanger(
35      self._device, self._package_info.cmdline_file)
36
37  def __repr__(self):
38    return 'Browser Startup Trace'
39
40  def _SetupTracing(self):
41    # TODO(lizeb): Figure out how to clean up the command-line file when
42    # _TearDownTracing() is not executed in StopTracing().
43    flags = ['--trace-startup']
44    if self._trace_time is not None:
45      flags.append('--trace-startup-duration={}'.format(self._trace_time))
46    self._flag_changer.AddFlags(flags)
47    self._device.ForceStop(self._package_info.package)
48    if self._webapk_package:
49      self._device.ForceStop(self._webapk_package)
50      logging.warning('Forces to stop the WebAPK and the browser provided by '
51                      '--browser: %s. Please make sure that this browser '
52                      'matches the host browser of the WebAPK %s. ',
53                      self._package_info.package,
54                      self._webapk_package)
55    if self._cold:
56      self._device.EnableRoot()
57      cache_control.CacheControl(self._device).DropRamCaches()
58    launch_intent = None
59    if self._webapk_package:
60      launch_intent = intent.Intent(
61          package=self._webapk_package,
62          activity=webapk.WEBAPK_MAIN_ACTIVITY,
63          data=self._url)
64    elif self._url == '':
65      launch_intent = intent.Intent(
66          action='android.intent.action.MAIN',
67          package=self._package_info.package,
68          activity=self._package_info.activity)
69    else:
70      launch_intent = intent.Intent(
71          package=self._package_info.package,
72          activity=self._package_info.activity,
73          data=self._url,
74          extras={'create_new_tab': True})
75    self._logcat_monitor.Start()
76    self._device.StartActivity(launch_intent, blocking=True)
77
78  def _TearDownTracing(self):
79    self._flag_changer.Restore()
80
81  @py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
82  def StartAgentTracing(self, config, timeout=None):
83    self._SetupTracing()
84    return True
85
86  @py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
87  def StopAgentTracing(self, timeout=None):
88    try:
89      self._trace_file = self._logcat_monitor.WaitFor(
90          self._trace_finish_re).group(1)
91    finally:
92      self._TearDownTracing()
93    return True
94
95  @py_utils.Timeout(tracing_agents.GET_RESULTS_TIMEOUT)
96  def GetResults(self, timeout=None):
97    with open(self._PullTrace(), 'r') as f:
98      trace_data = f.read()
99    return trace_result.TraceResult('traceEvents', trace_data)
100
101  def _PullTrace(self):
102    trace_file = self._trace_file.replace('/storage/emulated/0/', '/sdcard/')
103    host_file = os.path.join(os.path.curdir, os.path.basename(trace_file))
104    self._device.PullFile(trace_file, host_file)
105    return host_file
106
107  def SupportsExplicitClockSync(self):
108    return False
109
110  def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback):
111    # pylint: disable=unused-argument
112    assert self.SupportsExplicitClockSync(), ('Clock sync marker cannot be '
113        'recorded since explicit clock sync is not supported.')
114
115
116class ChromeStartupConfig(tracing_agents.TracingConfig):
117  def __init__(self, device, package_info, webapk_package, cold, url,
118               chrome_categories, trace_time):
119    tracing_agents.TracingConfig.__init__(self)
120    self.device = device
121    self.package_info = package_info
122    self.webapk_package = webapk_package
123    self.cold = cold
124    self.url = url
125    self.chrome_categories = chrome_categories
126    self.trace_time = trace_time
127
128
129def try_create_agent(config):
130  return ChromeStartupTracingAgent(config.device, config.package_info,
131                                   config.webapk_package,
132                                   config.cold, config.url, config.trace_time)
133
134def add_options(parser):
135  options = optparse.OptionGroup(parser, 'Chrome startup tracing')
136  options.add_option('--url', help='URL to visit on startup. Default: '
137                     'https://www.google.com. An empty URL launches Chrome '
138                     'with a MAIN action instead of VIEW.',
139                     default='https://www.google.com', metavar='URL')
140  options.add_option('--cold', help='Flush the OS page cache before starting '
141                     'the browser. Note that this require a device with root '
142                     'access.', default=False, action='store_true')
143  options.add_option('--webapk-package', help='Specify the package name '
144                     'of the WebAPK to launch the given URL. An empty URL '
145                     'laucnhes the host browser of the WebAPK with an new '
146                     'tab.', default=None)
147
148  return options
149
150def get_config(options):
151  return ChromeStartupConfig(options.device, options.package_info,
152                             options.webapk_package, options.cold,
153                             options.url, options.chrome_categories,
154                             options.trace_time)
155