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.
10 from profile_chrome
import controllers
12 from pylib
.device
import device_errors
13 from pylib
.device
import intent
16 _HEAP_PROFILE_MMAP_PROPERTY
= 'heapprof.mmap'
18 class ChromeTracingController(controllers
.BaseController
):
19 def __init__(self
, device
, package_info
,
20 categories
, ring_buffer
, trace_memory
=False):
21 controllers
.BaseController
.__init
__(self
)
23 self
._package
_info
= package_info
24 self
._categories
= categories
25 self
._ring
_buffer
= ring_buffer
26 self
._logcat
_monitor
= self
._device
.GetLogcatMonitor()
27 self
._trace
_file
= None
28 self
._trace
_interval
= None
29 self
._trace
_memory
= trace_memory
30 self
._is
_tracing
= False
31 self
._trace
_start
_re
= \
32 re
.compile(r
'Logging performance trace to file')
33 self
._trace
_finish
_re
= \
34 re
.compile(r
'Profiler finished[.] Results are in (.*)[.]')
40 def GetCategories(device
, package_info
):
41 with device
.GetLogcatMonitor() as logmon
:
42 device
.BroadcastIntent(intent
.Intent(
43 action
='%s.GPU_PROFILER_LIST_CATEGORIES' % package_info
.package
))
45 json_category_list
= logmon
.WaitFor(
46 re
.compile(r
'{"traceCategoriesList(.*)'), timeout
=5).group(0)
47 except device_errors
.CommandTimeoutError
:
48 raise RuntimeError('Performance trace category list marker not found. '
49 'Is the correct version of the browser running?')
51 record_categories
= set()
52 disabled_by_default_categories
= set()
53 json_data
= json
.loads(json_category_list
)['traceCategoriesList']
54 for item
in json_data
:
55 for category
in item
.split(','):
56 if category
.startswith('disabled-by-default'):
57 disabled_by_default_categories
.add(category
)
59 record_categories
.add(category
)
61 return list(record_categories
), list(disabled_by_default_categories
)
63 def StartTracing(self
, interval
):
64 self
._trace
_interval
= interval
65 self
._logcat
_monitor
.Start()
66 start_extras
= {'categories': ','.join(self
._categories
)}
68 start_extras
['continuous'] = None
69 self
._device
.BroadcastIntent(intent
.Intent(
70 action
='%s.GPU_PROFILER_START' % self
._package
_info
.package
,
73 if self
._trace
_memory
:
74 self
._device
.EnableRoot()
75 self
._device
.SetProp(_HEAP_PROFILE_MMAP_PROPERTY
, 1)
77 # Chrome logs two different messages related to tracing:
79 # 1. "Logging performance trace to file"
80 # 2. "Profiler finished. Results are in [...]"
82 # The first one is printed when tracing starts and the second one indicates
83 # that the trace file is ready to be pulled.
85 self
._logcat
_monitor
.WaitFor(self
._trace
_start
_re
, timeout
=5)
86 self
._is
_tracing
= True
87 except device_errors
.CommandTimeoutError
:
88 raise RuntimeError('Trace start marker not found. Is the correct version '
89 'of the browser running?')
91 def StopTracing(self
):
93 self
._device
.BroadcastIntent(intent
.Intent(
94 action
='%s.GPU_PROFILER_STOP' % self
._package
_info
.package
))
95 self
._trace
_file
= self
._logcat
_monitor
.WaitFor(
96 self
._trace
_finish
_re
, timeout
=120).group(1)
97 self
._is
_tracing
= False
98 if self
._trace
_memory
:
99 self
._device
.SetProp(_HEAP_PROFILE_MMAP_PROPERTY
, 0)
102 # Wait a bit for the browser to finish writing the trace file.
103 time
.sleep(self
._trace
_interval
/ 4 + 1)
105 trace_file
= self
._trace
_file
.replace('/storage/emulated/0/', '/sdcard/')
106 host_file
= os
.path
.join(os
.path
.curdir
, os
.path
.basename(trace_file
))
107 self
._device
.PullFile(trace_file
, host_file
)