touch_firmware_test: add major/minor in linechart

Draw major/minor in linechart

BUG=None
TEST=manual

Change-Id: Ia9e5bd7c0a827156be5ca4b6f41ad1e2e8854c68
Reviewed-on: https://chromium-review.googlesource.com/1043045
Commit-Ready: Jingkui Wang <jkwang@google.com>
Tested-by: Jingkui Wang <jkwang@google.com>
Reviewed-by: Jingkui Wang <jkwang@google.com>
diff --git a/remote/mt/event.py b/remote/mt/event.py
index 6db41ad..3a6e3d1 100644
--- a/remote/mt/event.py
+++ b/remote/mt/event.py
@@ -59,6 +59,10 @@
     """ Is this event ABS_MT_TOUCH_MAJOR? """
     return self.event_type == EV_ABS and self.event_code == ABS_MT_TOUCH_MAJOR
 
+  def is_ABS_MT_TOUCH_MINOR(self):
+    """ Is this event ABS_MT_TOUCH_MINOR? """
+    return self.event_type == EV_ABS and self.event_code == ABS_MT_TOUCH_MINOR
+
   def is_ABS_MT_DISTANCE(self):
     """ Is this event ABS_MT_DISTANCE? """
     return self.event_type == EV_ABS and self.event_code == ABS_MT_DISTANCE
diff --git a/remote/mt/state_machine.py b/remote/mt/state_machine.py
index 15a13e0..0ffc9f0 100644
--- a/remote/mt/state_machine.py
+++ b/remote/mt/state_machine.py
@@ -6,7 +6,8 @@
 from event import MtEvent, EV_ABS, ABS_MT_TRACKING_ID
 
 MtFinger = namedtuple('MtFinger', ['tid', 'syn_time', 'x', 'y', 'pressure',\
-                                   'tilt_x', 'tilt_y'])
+                                   'tilt_x', 'tilt_y', 'touch_major',\
+                                   'touch_minor'])
 MtSnapshot = namedtuple('MtSnapshot', ['syn_time', 'button_pressed',
                                        'fingers', 'raw_events'])
 
@@ -77,7 +78,8 @@
     # Clear out the state for the current fingers
     self.fingers_data = []
     self.raw_events_since_last_syn = []
-    self.tid = self.x = self.y = self.pressure = self.touch_major = None
+    self.tid = self.x = self.y = self.pressure = self.touch_major \
+        = self.touch_minor = None
 
   def add_event(self, event):
     self.raw_events_since_last_syn.append(event)
@@ -86,10 +88,10 @@
     if event.is_SYN_REPORT():
       # First build up the snapshot
       fingers = []
-      for tid, x, y, touch_major in self.fingers_data:
+      for tid, x, y, p, touch_major, touch_minor in self.fingers_data:
         mapped_tid = self.tid_mappings[tid]
         fingers.append(MtFinger(mapped_tid, event.timestamp, x, y,
-                                touch_major, 0, 0))
+                                p, 0, 0, touch_major, touch_minor))
       self.last_snapshot = MtSnapshot(event.timestamp, self.button_pressed,
                                       fingers, self.raw_events_since_last_syn)
 
@@ -117,7 +119,14 @@
         pressure = self.pressure
 
       if all([v is not None for v in (self.tid, self.x, self.y, pressure)]):
-        self.fingers_data.append((self.tid, self.x, self.y, pressure))
+        touch_major = 0
+        touch_minor = 0
+        if self.touch_major is not None:
+          touch_major = self.touch_major
+        if self.touch_minor is not None:
+          touch_minor = self.touch_minor
+        self.fingers_data.append((self.tid, self.x, self.y, pressure,\
+                                  touch_major, touch_minor))
 
     # Otherwise, check what information it's giving us and store it
     elif event.is_ABS_MT_TRACKING_ID():
@@ -133,6 +142,8 @@
       self.pressure = event.value
     elif event.is_ABS_MT_TOUCH_MAJOR():
       self.touch_major = event.value
+    elif event.is_ABS_MT_TOUCH_MINOR():
+      self.touch_minor = event.value
     elif event.is_BTN_LEFT():
       self.button_pressed = (event.value == 1)
 
@@ -170,6 +181,7 @@
     self.distance = {}
     self.pressure = {}
     self.touch_major = {}
+    self.touch_minor = {}
     self.syn_time = None
     self.leaving_slots = []
     self.button_pressed = False
@@ -216,6 +228,8 @@
       self.pressure[self.slot] = event.value
     elif event.is_ABS_MT_TOUCH_MAJOR():
       self.touch_major[self.slot] = event.value
+    elif event.is_ABS_MT_TOUCH_MINOR():
+      self.touch_minor[self.slot] = event.value
     elif event.is_ABS_MT_DISTANCE():
       self.distance[self.slot] = event.value
 
@@ -235,6 +249,8 @@
       x = self.x.get(slot, None)
       y = self.y.get(slot, None)
       distance = self.distance.get(slot, None)
+      major = self.touch_major.get(slot, 0)
+      minor = self.touch_minor.get(slot, 0)
 
       # Skip any fingers that are hovering (they have a distance)
       if distance:
@@ -250,7 +266,8 @@
       data_ready = all([v is not None for v in
                         (x, y, pressure, tid, self.syn_time)])
       if data_ready:
-        finger = MtFinger(tid, self.syn_time, x, y, pressure, 0, 0)
+        finger = MtFinger(tid, self.syn_time, x, y, pressure, 0, 0,
+                          major, minor)
         current_fingers.append(finger)
 
     current_snapshot = MtSnapshot(self.syn_time, self.button_pressed,
@@ -304,7 +321,7 @@
       current_fingers = None
       if self.btn_touch:
         current_fingers = [MtFinger(0, event.timestamp, self.x, self.y, self.p,
-                                    self.tilt_x, self.tilt_y)]
+                                    self.tilt_x, self.tilt_y, 0, 0)]
         self.last_report_was_empty = False
       elif not self.last_report_was_empty:
         current_fingers = []
diff --git a/remote/remote.py b/remote/remote.py
index 6955fa1..7826d1f 100644
--- a/remote/remote.py
+++ b/remote/remote.py
@@ -99,6 +99,12 @@
   def RangeTiltY(self):
     return self._tilt_y_min, self._tilt_y_max
 
+  def RangeMajor(self):
+    return self._major_min, self._major_max
+
+  def RangeMinor(self):
+    return self._minor_min, self._minor_max
+
   def _GetDimensions(self):
     """ Ask the device for the dimensions, the x/y resolution, and the range
     of pressure values should be reported.
diff --git a/remote/remote_in_system.py b/remote/remote_in_system.py
index 0c85e4c..5521a00 100644
--- a/remote/remote_in_system.py
+++ b/remote/remote_in_system.py
@@ -57,7 +57,7 @@
     self._InitializeEventGatheringSubprocess()
 
     # Determine the ranges/resolutions of the various attributes of fingers
-    x, y, p, tilt_x, tilt_y = self._GetDimensions()
+    x, y, p, tilt_x, tilt_y, major, minor = self._GetDimensions()
     self._x_min, self._x_max, self._x_res = x['min'], x['max'], x['resolution']
     self._y_min, self._y_max, self._y_res = y['min'], y['max'], y['resolution']
     self._p_min, self._p_max = p.get('min', None), p.get('max', None)
@@ -65,6 +65,11 @@
     self._tilt_x_max = tilt_x.get('max', 0);
     self._tilt_y_min = tilt_y.get('min', 0);
     self._tilt_y_max = tilt_y.get('max', 0);
+    self._major_min = major.get('min', 0);
+    self._major_max = major.get('max', 0);
+    self._minor_min = minor.get('min', 0);
+    self._minor_max = minor.get('max', 0);
+
 
     # Determine which kind of state machine should be used with this device
     self.protocol = self._GetMtProtocol() if protocol == 'auto' else protocol
@@ -351,7 +356,8 @@
     separate step before returning.  To see how we compute resolution
     information for Android, look in that function.
     """
-    x = y = p = touch_major = None
+    x = y = p = None
+    touch_major = touch_minor = {}
     cmd = 'getevent -p /dev/input/event%d' % self.device_num
     output = self._RunRemoteCmd(cmd).stdout.read()
     for line in output.split('\n'):
@@ -370,13 +376,16 @@
         p = {'min': min_value, 'max': max_value}
       elif code is linux_input.ABS_MT_TOUCH_MAJOR:
         touch_major = {'min': min_value, 'max': max_value}
+      elif code is linux_input.ABS_MT_TOUCH_MINOR:
+        touch_minor = {'min': min_value, 'max': max_value}
 
     p = self._CheckForAlternativePressureSources(p, touch_major)
 
     resolution = self._GetResolution()
     x['resolution'] = resolution
     y['resolution'] = resolution
-    return x, y, p, {'min':0, 'max':0}, {'min':0, 'max':0}
+    return x, y, p, {'min':0, 'max':0}, {'min':0, 'max':0}, touch_major,\
+        touch_minor
 
   def _ToSignedInt(self, x, bits):
     return x if x & (1 << (bits - 1)) == 0 else x - (1 << bits)
@@ -466,7 +475,8 @@
             dim[attribute] = value
       return dim
 
-    x = y = p = tilt_x = tilt_y = touch_major = None
+    x = y = p = tilt_x = tilt_y = None
+    touch_major = touch_minor = {}
     while not all([x, y, p, tilt_x, tilt_y]):
       line = self._GetNextLine(timeout=2)
       if line is None:
@@ -484,6 +494,10 @@
         tilt_y = _GetDimensions_Aux(['min', 'max'])
       elif 'Event code 48 (ABS_MT_TOUCH_MAJOR)' in line:
         touch_major = _GetDimensions_Aux(['min', 'max'])
+      elif 'Event code 48 (ABS_MT_TOUCH_MINOR)' in line:
+        touch_minor = _GetDimensions_Aux(['min', 'max'])
+
+
 
     p = self._CheckForAlternativePressureSources(p, touch_major)
 
@@ -492,7 +506,7 @@
     if not tilt_y:
         tilt_y = {'min':0, 'max':0}
 
-    return x, y, p, tilt_x, tilt_y
+    return x, y, p, tilt_x, tilt_y, touch_major, touch_minor
 
   def _ParseMtEvent(self, line):
     """ How to parse out the ChromeOS-specific event format
diff --git a/webplot/linechart/linechart.html b/webplot/linechart/linechart.html
index 2a0ad36..a842300 100644
--- a/webplot/linechart/linechart.html
+++ b/webplot/linechart/linechart.html
@@ -8,6 +8,12 @@
 <head>
   <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
   <script src="linechart/linechart.js"></script>
+  <style>
+    .buttons {
+        margin-top: 50px;
+        margin-left: 100px;
+    }
+  </style>
 </head>
 
 <body style="margin:0; padding:0;"
@@ -26,9 +32,31 @@
   <div id="tiltMaxX" hidden>%(tiltMaxX)s</div>
   <div id="tiltMinY" hidden>%(tiltMinY)s</div>
   <div id="tiltMaxY" hidden>%(tiltMaxY)s</div>
+  <div id="majorMin" hidden>%(majorMin)s</div>
+  <div id="majorMax" hidden>%(majorMax)s</div>
+  <div id="minorMin" hidden>%(minorMin)s</div>
+  <div id="minorMax" hidden>%(minorMax)s</div>
+  <div class="buttons">
+    <button onclick="toggleChart('xyChart')">Toggle xy Chart</button>
+    <button onclick="toggleChart('tiltChart')">Toggle tilt Chart</button>
+    <button onclick="toggleChart('pressureChart')">Toggle pressure Chart</button>
+    <button onclick="toggleChart('touchMajorChart')">Toggle major Chart</button>
+    <button onclick="toggleChart('touchMinorChart')">Toggle minor Chart</button>
+  </div>
   <div id="xyChart"> </div>
   <div id="tiltChart"> </div>
   <div id="pressureChart"> </div>
-
+  <div id="touchMajorChart"> </div>
+  <div id="touchMinorChart"> </div>
+  <script>
+    function toggleChart(div) {
+      var x = document.getElementById(div);
+      if (x.style.display === "none") {
+        x.style.display = "block";
+      } else {
+        x.style.display = "none";
+      }
+    }
+  </script>
 </body>
 </html>
diff --git a/webplot/linechart/linechart.js b/webplot/linechart/linechart.js
index ba2231e..46877bc 100644
--- a/webplot/linechart/linechart.js
+++ b/webplot/linechart/linechart.js
@@ -64,7 +64,7 @@
  * This function generate csv file of the events and then download it.
  */
 PointerEventBuffer.prototype.saveEventsToCSV = function() {
-  var text = "syn_time, x, y, tilt_x, tilt_y, pressure \n";
+  var text = "syn_time, x, y, tilt_x, tilt_y, pressure, major, minor \n";
   for (var i = 0; i < this.data.length; i++) {
     text += this.data[i].syn_time;
     text += ",";
@@ -77,6 +77,10 @@
     text += this.data[i].tilt_y;
     text += ",";
     text += this.data[i].pressure;
+    text += ",";
+    text += this.data[i].touch_major;
+    text += ",";
+    text += this.data[i].touch_minor;
     text += "\n";
   }
   var element = document.createElement('a');
@@ -97,6 +101,8 @@
  * @param {Element} xyChartDiv the div to draw xy chart.
  * @param {Element} tiltChartDiv the div to draw tilt chart.
  * @param {Element} pressureChartDiv the div to draw pressure chart.
+ * @param {Element} majorChartDiv the div to draw major chart.
+ * @param {Element} minorChartDiv the div to draw minor chart.
  * @param {int} touchMinX the min x value of the touch device.
  * @param {int} touchMaxX the max x value of the touch device.
  * @param {int} touchMinY the min y value of the touch device.
@@ -107,20 +113,30 @@
  * @param {int} tiltMaxX the max tilt x value of the touch device.
  * @param {int} tiltMinY the min tilt y value of the touch device.
  * @param {int} tiltMaxY the max tilt y value of the touch device.
+ * @param {int} majorMin the min major value of the touch device.
+ * @param {int} majorMax the max major value of the touch device.
+ * @param {int} minorMin the min minor value of the touch device.
+ * @param {int} minorMax the max minor value of the touch device.
  */
-function TouchLineChart(xyChartDiv, tiltChartDiv, pressureChartDiv, touchMinX,
+function TouchLineChart(xyChartDiv, tiltChartDiv, pressureChartDiv,
+    majorChartDiv, minorChartDiv, touchMinX,
     touchMaxX, touchMinY, touchMaxY, touchMinPressure, touchMaxPressure,
-    tiltMinX, tiltMaxX, tiltMinY, tiltMaxY) {
+    tiltMinX, tiltMaxX, tiltMinY, tiltMaxY, majorMin, majorMax, minorMin,
+    minorMax) {
   this.xyChartMin = Math.min(touchMinX, touchMinY);
   this.xyChartMax = Math.min(touchMaxX, touchMaxY);
   this.tiltChartMin = Math.min(tiltMinX, tiltMinY);
   this.tiltChartMax = Math.min(tiltMaxX, tiltMaxY);
   this.pressureChartMin = touchMinPressure;
   this.pressureChartMax = touchMaxPressure;
-
+  this.majorMin = majorMin;
+  this.majorMax = majorMax;
+  this.minorMin = minorMin;
+  this.minorMax = minorMax;
   this.eventBuffer = new PointerEventBuffer();
 
-  this.initCharts(xyChartDiv, tiltChartDiv, pressureChartDiv);
+  this.initCharts(xyChartDiv, tiltChartDiv, pressureChartDiv, majorChartDiv,
+      minorChartDiv);
   this.drawCharts();
 }
 
@@ -155,9 +171,11 @@
  * @param {Element} xyChartDiv div for the xy chart.
  * @param {Element} tiltChartDiv div for the tilt chart.
  * @param {Element} pressureChartDiv div for the pressure chart.
+ * @param {Element} majorChartDiv div for the major chart.
+ * @param {Element} minorChartDiv div for the minor chart.
  */
 TouchLineChart.prototype.initCharts = function(xyChartDiv, tiltChartDiv,
-  pressureChartDiv) {
+  pressureChartDiv, majorChartDiv, minorChartDiv) {
   this.xyChart = new google.visualization.LineChart(xyChartDiv);
   this.xyChartOption = this.getChartOptions("Position", this.xyChartMin,
       this.xyChartMax);
@@ -170,6 +188,16 @@
       new google.visualization.LineChart(pressureChartDiv);
   this.pressureChartOption = this.getChartOptions("Pressure",
       this.pressureChartMin, this.pressureChartMax);
+
+  this.majorChart =
+      new google.visualization.LineChart(majorChartDiv);
+  this.majorOptions = this.getChartOptions("Major",
+      this.majorMin, this.majorMax);
+
+  this.minorChart =
+      new google.visualization.LineChart(minorChartDiv);
+  this.minorOptions = this.getChartOptions("Minor",
+      this.minorMin, this.minorMax);
 }
 
 /**
@@ -184,6 +212,12 @@
 
   this.pressureChart.draw(this.eventBuffer.getDataTableForColumns(['pressure']),
       this.pressureChartOption);
+
+  this.majorChart.draw(this.eventBuffer.getDataTableForColumns(['touch_major']),
+      this.majorOptions);
+
+  this.minorChart.draw(this.eventBuffer.getDataTableForColumns(['touch_minor']),
+      this.minorOptions);
 }
 
 /**
@@ -255,6 +289,10 @@
   var tiltMaxX = document.getElementById('tiltMaxX').innerText;
   var tiltMinY = document.getElementById('tiltMinY').innerText;
   var tiltMaxY = document.getElementById('tiltMaxY').innerText;
+  var majorMin = document.getElementById('majorMin').innerText;
+  var majorMax = document.getElementById('majorMax').innerText;
+  var minorMin = document.getElementById('minorMin').innerText;
+  var minorMax = document.getElementById('minorMax').innerText;
 
   if (window.WebSocket) {
     ws = new WebSocket(websocket);
@@ -273,6 +311,8 @@
   touchLineChart = new TouchLineChart(document.getElementById('xyChart'),
                         document.getElementById('tiltChart'),
                         document.getElementById('pressureChart'),
+                        document.getElementById('touchMajorChart'),
+                        document.getElementById('touchMinorChart'),
                         touchMinX, touchMaxX, touchMinY, touchMaxY,
                         touchMinPressure, touchMaxPressure, tiltMinX, tiltMaxX,
                         tiltMinY, tiltMaxY);
diff --git a/webplot/webplot.py b/webplot/webplot.py
index f712fd9..12b1ecd 100755
--- a/webplot/webplot.py
+++ b/webplot/webplot.py
@@ -221,7 +221,8 @@
 
   def __init__(self, ip, port, touch_min_x, touch_max_x, touch_min_y,
                touch_max_y, touch_min_pressure, touch_max_pressure,
-               tilt_min_x, tilt_max_x, tilt_min_y, tilt_max_y):
+               tilt_min_x, tilt_max_x, tilt_min_y, tilt_max_y,
+               major_min, major_max, minor_min, minor_max):
     self.ip = ip
     self.port = port
     self.touch_min_x = touch_min_x
@@ -234,6 +235,10 @@
     self.tilt_max_x = tilt_max_x
     self.tilt_min_y = tilt_min_y
     self.tilt_max_y = tilt_max_y
+    self.major_min = major_min
+    self.major_max = major_max
+    self.minor_min = minor_min
+    self.minor_max = minor_max
     self.scheme = 'ws'
     cherrypy.log('Root address: (%s, %s)' % (ip, str(port)))
     cherrypy.log('scheme: %s' % self.scheme)
@@ -274,6 +279,10 @@
       'tiltMaxX': str(self.tilt_max_x),
       'tiltMinY': str(self.tilt_min_y),
       'tiltMaxY': str(self.tilt_max_y),
+      'majorMin': str(self.major_min),
+      'majorMax': str(self.major_max),
+      'minorMin': str(self.minor_min),
+      'minorMax': str(self.minor_max),
     }
     root_page = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                              'linechart/linechart.html')
@@ -419,9 +428,13 @@
       p_min, p_max = self._device.RangeP()
       tilt_x_min, tilt_x_max = self._device.RangeTiltX()
       tilt_y_min, tilt_y_max = self._device.RangeTiltY()
+      major_min, major_max = self._device.RangeMajor()
+      minor_min, minor_max = self._device.RangeMinor()
+
       root = TouchRoot(self._server_addr, self._server_port,
                        x_min, x_max, y_min, y_max, p_min, p_max, tilt_x_min,
-                       tilt_x_max, tilt_y_min, tilt_y_max)
+                       tilt_x_max, tilt_y_min, tilt_y_max,
+                       major_min, major_max, minor_min, minor_max,)
     else:
       data_scale = self._device.data_scale
       data_offset = self._device.data_offset
@@ -599,7 +612,7 @@
                             'rule to iptables to allow incoming traffic to '
                             'the webserver.  If you are running webplot on '
                             'a chromebook, this is needed.'))
-  parser.add_argument('-s', '--server_addr', default='127.0.0.1',
+  parser.add_argument('-s', '--server_addr', default='0.0.0.0',
                       help='the address the webplot http server listens to')
   parser.add_argument('-t', '--dut_type', default='chromeos', type=str.lower,
                       help='dut type: chromeos, android, centroiding')