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