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