- add sources.
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / platform / profiler / monsoon_profiler.py
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.
4
5 import csv
6 import multiprocessing
7 import os
8 import sys
9
10 from telemetry.core import exceptions
11 from telemetry.core import util
12 from telemetry.core.platform import profiler
13
14 sys.path.append(os.path.join(util.GetTelemetryDir(), 'third_party', 'internal'))
15 try:
16   import monsoon  # pylint: disable=F0401
17 except ImportError:
18   monsoon = None
19
20
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.)
30   mon.SetVoltage(4.0)
31
32   samples = []
33   try:
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.
37     mon.CollectData()
38     is_collecting.set()
39     while is_collecting.is_set():
40       samples += mon.CollectData()
41   finally:
42     mon.StopDataCollection()
43
44   # Add x-axis labels.
45   plot_data = [(i / 5000., sample) for i, sample in enumerate(samples)]
46
47   # Print data in csv.
48   with open(output_path, 'w') as output_file:
49     output_writer = csv.writer(output_file)
50     output_writer.writerows(plot_data)
51     output_file.flush()
52
53   print 'To view the Monsoon profile, run:'
54   print ('  echo "set datafile separator \',\'; plot \'%s\' with lines" | '
55       'gnuplot --persist' % output_path)
56
57
58 class MonsoonProfiler(profiler.Profiler):
59   """Profiler that tracks current using Monsoon Power Monitor.
60
61   http://www.msoon.com/LabEquipment/PowerMonitor/
62   The Monsoon device measures current in amps at 5000 samples/second.
63   """
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.')
76
77   @classmethod
78   def name(cls):
79     return 'monsoon'
80
81   @classmethod
82   def is_supported(cls, browser_type):
83     if not monsoon:
84       return False
85     try:
86       monsoon.Monsoon(wait=False)
87     except IOError:
88       return False
89     else:
90       return True
91
92   def CollectProfile(self):
93     self._is_collecting.clear()
94     self._collector.join()
95     return [self._output_path]