blob: 7826d1f51a344ac8e84aa088c39fbb2777a5a67c [file] [log] [blame]
# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
class RemoteTouchDevice:
""" An abstract base class to define access to touch events on remote devices
To enable running touch device firmware testing on devices of various types
of platforms this module introduces a RemoteTouchDevice interface. One can
create subclasses that fill out how to stream touch events from a remote
touch device and then they can be substituted seamlessly, leveraging the test
suite's common code.
The basic work flow for a RemoteTouchDevice is this:
1. Create the device (specifics may vary depending on DUT type)
2. Call the device's FlushSnapshotBuffer() method to consume any events
that occurred since the last time you called NextSnapshot() or created
the connection. This needs only to get called if you want to flush the
buffer of events.
3. Repeatedly call NextSnapshot(), which will block until another MtSnapshot
arrives. These are little structures defined in mt/state_machine.py and
contain finger data from one SYN event.
For example, you would instantiate objects for various types then use them
exactly the same way:
# Initialize your remote touch devices depending on what the DUT is
touch_dev = ChromeOSTouchDevice(addr='192.168.0.3', is_touchscreen=False)
touch_dev = AndroidTouchDevice(addr=None, is_touchscreen=True)
# Do some work here...
# Flush any events that are buffered and print the next 100 snapshots
touch_dev.FlushSnapshotBuffer()()
for i in range(100):
print touch_dev.NextSnapshot()
"""
not_implemented_msg = 'Must be implemented by a subclass.'
def __init__(self):
self.warnings = []
def Warn(self, warning_message):
""" Display a warning on stdout as well as storing it in a member variable
for later use.
"""
print '\033[1;31mWARNING (remote touch device): %s\033[0m' % warning_message
self.warnings.append(warning_message)
def FlushSnapshotBuffer(self, wait_until_no_fingers_present=False):
while True:
snapshot = self.NextSnapshot(timeout=self.flush_timeout)
while snapshot:
snapshot = self.NextSnapshot(timeout=self.flush_timeout)
if not wait_until_no_fingers_present:
return
elif (not self.most_recent_snapshot or
len(self.most_recent_snapshot.fingers) == 0):
return
def NextSnapshot(self, timeout=None):
""" Consume MtEvents from the touch device until a complete snapshot has
come in. This maintains the state machine and returns the next MtSnapshot
or None in the case that connection is lost.
If it ever has to wait more than the specified timeout (in seconds) for
the next MtEvent it will return None instead of a MtSnapshot. The default
timeout value of None indicates that it should wait forever.
"""
event = self._NextEvent(timeout)
while event:
self.state_machine.add_event(event)
if event.is_SYN_REPORT():
self.most_recent_snapshot = self.state_machine.get_current_snapshot()
if self.most_recent_snapshot:
return self.most_recent_snapshot
event = self._NextEvent(timeout)
return None
def ResolutionX(self):
return self._x_res
def ResolutionY(self):
return self._y_res
def RangeX(self):
return self._x_min, self._x_max
def RangeY(self):
return self._y_min, self._y_max
def RangeP(self):
return self._p_min, self._p_max
def RangeTiltX(self):
return self._tilt_x_min, self._tilt_x_max
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.
if the device doesn't report the lower bound, the lower bound zero should
be reported.
This function should return three dictionaries of the following form:
(x, y, p)
where x and why have 'min' 'max' and 'resolution' defined, and p has only
'min' and 'max.
This is called automatically in the constructor to set the ranges for all
of the various dimensions of the device.
"""
raise NotImplementedError(RemoteTouchDevice.not_implemented_msg)
# Below are functions common to all RemoteTouchDevices and do not need to
# be overridden by subclasses
def PxToMm_X(self, x):
return float(x) / float(self.ResolutionX())
def PxToMm_Y(self, x):
return float(x) / float(self.ResolutionY())
def PxToMm(self, (x, y)):
return self.PxToMm_X(x), self.PxToMm_Y(y)