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
import pexpect
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
._trace
_file
= None
27 self
._trace
_interval
= None
28 self
._trace
_memory
= trace_memory
29 self
._is
_tracing
= False
30 self
._trace
_start
_re
= \
31 re
.compile(r
'Logging performance trace to file')
32 self
._trace
_finish
_re
= \
33 re
.compile(r
'Profiler finished[.] Results are in (.*)[.]')
34 self
._device
.old_interface
.StartMonitoringLogcat(clear
=False)
40 def GetCategories(device
, package_info
):
41 device
.BroadcastIntent(intent
.Intent(
42 action
='%s.GPU_PROFILER_LIST_CATEGORIES' % package_info
.package
))
44 json_category_list
= device
.old_interface
.WaitForLogMatch(
45 re
.compile(r
'{"traceCategoriesList(.*)'), None, timeout
=5).group(0)
46 except pexpect
.TIMEOUT
:
47 raise RuntimeError('Performance trace category list marker not found. '
48 'Is the correct version of the browser running?')
50 record_categories
= set()
51 disabled_by_default_categories
= set()
52 json_data
= json
.loads(json_category_list
)['traceCategoriesList']
53 for item
in json_data
:
54 for category
in item
.split(','):
55 if category
.startswith('disabled-by-default'):
56 disabled_by_default_categories
.add(category
)
58 record_categories
.add(category
)
60 return list(record_categories
), list(disabled_by_default_categories
)
62 def StartTracing(self
, interval
):
63 self
._trace
_interval
= interval
64 self
._device
.old_interface
.SyncLogCat()
65 start_extras
= {'categories': ','.join(self
._categories
)}
67 start_extras
['continuous'] = None
68 self
._device
.BroadcastIntent(intent
.Intent(
69 action
='%s.GPU_PROFILER_START' % self
._package
_info
.package
,
72 if self
._trace
_memory
:
73 self
._device
.old_interface
.EnableAdbRoot()
74 self
._device
.SetProp(_HEAP_PROFILE_MMAP_PROPERTY
, 1)
76 # Chrome logs two different messages related to tracing:
78 # 1. "Logging performance trace to file"
79 # 2. "Profiler finished. Results are in [...]"
81 # The first one is printed when tracing starts and the second one indicates
82 # that the trace file is ready to be pulled.
84 self
._device
.old_interface
.WaitForLogMatch(
85 self
._trace
_start
_re
, None, timeout
=5)
86 self
._is
_tracing
= True
87 except pexpect
.TIMEOUT
:
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
._device
.old_interface
.WaitForLogMatch(
96 self
._trace
_finish
_re
, None, 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
)