1 # Copyright 2013 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 telemetry.core import exceptions
11 from telemetry.core import util
12 from telemetry.core.platform import profiler
14 sys.path.append(os.path.join(util.GetTelemetryDir(), 'third_party', 'internal'))
16 import monsoon # pylint: disable=F0401
21 def _CollectData(output_path, is_collecting):
22 mon = monsoon.Monsoon(wait=False)
23 mon.SetMaxCurrent(2.0)
24 # Note: Telemetry requires the device to be connected by USB, but that
25 # puts it in charging mode. This increases the power consumption.
26 mon.SetUsbPassthrough(1)
27 # Nominal Li-ion voltage is 3.7V, but it puts out 4.2V at max capacity. Use
28 # 4.0V to simulate a "~80%" charged battery. Google "li-ion voltage curve".
29 # This is true only for a single cell. (Most smartphones, some tablets.)
34 mon.StartDataCollection()
35 # Do one CollectData() to make the Monsoon set up, which takes about
36 # 0.3 seconds, and only signal that we've started after that.
39 while is_collecting.is_set():
40 samples += mon.CollectData()
42 mon.StopDataCollection()
45 plot_data = [(i / 5000., sample) for i, sample in enumerate(samples)]
48 with open(output_path, 'w') as output_file:
49 output_writer = csv.writer(output_file)
50 output_writer.writerows(plot_data)
53 print 'To view the Monsoon profile, run:'
54 print (' echo "set datafile separator \',\'; plot \'%s\' with lines" | '
55 'gnuplot --persist' % output_path)
58 class MonsoonProfiler(profiler.Profiler):
59 """Profiler that tracks current using Monsoon Power Monitor.
61 http://www.msoon.com/LabEquipment/PowerMonitor/
62 The Monsoon device measures current in amps at 5000 samples/second.
64 def __init__(self, browser_backend, platform_backend, output_path, state):
65 super(MonsoonProfiler, self).__init__(
66 browser_backend, platform_backend, output_path, state)
67 # We collect the data in a separate process, so we can continuously
68 # read the samples from the USB port while running the test.
69 self._is_collecting = multiprocessing.Event()
70 self._collector = multiprocessing.Process(
71 target=_CollectData, args=(output_path, self._is_collecting))
72 self._collector.start()
73 if not self._is_collecting.wait(timeout=0.5):
74 self._collector.terminate()
75 raise exceptions.ProfilingException('Failed to start data collection.')
82 def is_supported(cls, browser_type):
86 monsoon.Monsoon(wait=False)
92 def CollectProfile(self):
93 self._is_collecting.clear()
94 self._collector.join()
95 return [self._output_path]