Chameleon: Introduce Chameleon Measurers for measurement tests

Create 2 classes for measurement, LocalChameleonMeasurer and
RemoteChameleonMeasurer, for client tests and server tests.

It does the setup work to make DUT into a ready state, like pluging
the external display and setting to mirrored mode.

BUG=b:28885370
TEST=Pending

Change-Id: I559178082babf07aba73150c3e58768284599551
Reviewed-on: https://chromium-review.googlesource.com/349300
Commit-Ready: Tom Tam <waihong@google.com>
Tested-by: Tom Tam <waihong@google.com>
Reviewed-by: Tom Tam <waihong@google.com>
diff --git a/client/cros/chameleon/chameleon_measurer.py b/client/cros/chameleon/chameleon_measurer.py
new file mode 100644
index 0000000..7cc35b6
--- /dev/null
+++ b/client/cros/chameleon/chameleon_measurer.py
@@ -0,0 +1,75 @@
+# Copyright 2016 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.
+
+import logging
+import time
+from contextlib import contextmanager
+
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.cros.chameleon import chameleon
+from autotest_lib.client.cros.chameleon import chameleon_port_finder
+from autotest_lib.client.cros.multimedia import local_facade_factory
+
+
+class _BaseChameleonMeasurer(object):
+    """Base class of performing measurement using Chameleon."""
+
+    def __init__(self, cros_host, outputdir=None):
+        """Initializes the object."""
+        raise NotImplementedError('_BaseChameleonMeasurer.__init__')
+
+
+    @contextmanager
+    def start_mirrored_mode_measurement(self):
+        """Starts the mirrored mode to measure.
+
+        It iterates the connection ports between DUT and Chameleon and uses
+        the first port. Sets DUT into the mirrored mode. Then yields the
+        connected ports.
+
+        It is used via a with statement, like the following:
+
+            measurer = LocalChameleonMeasurer(cros_host, args, chrome)
+            with measure.start_mirrored_mode_measurement() as chameleon_port:
+                # chameleon_port is automatically plugged before this line.
+                do_some_test_on(chameleon_port)
+                # chameleon_port is automatically unplugged after this line.
+
+        @yields the first connected ChameleonVideoInput which is ensured plugged
+                before yielding.
+
+        @raises TestFail if no connected video port.
+        """
+        finder = chameleon_port_finder.ChameleonVideoInputFinder(
+                self.chameleon, self.display_facade)
+        with finder.use_first_port() as chameleon_port:
+            logging.info('Used Chameleon port: %s',
+                         chameleon_port.get_connector_type())
+
+            logging.info('Setting to mirrored mode')
+            self.display_facade.set_mirrored(True)
+
+            # Get the resolution to make sure Chameleon in a good state.
+            resolution = chameleon_port.get_resolution()
+            logging.info('Detected the resolution: %dx%d', *resolution)
+
+            yield chameleon_port
+
+
+class LocalChameleonMeasurer(_BaseChameleonMeasurer):
+    """A simple tool to measure using Chameleon for a client test.
+
+    This class can only be used in a client test. For a server test, use the
+    RemoteChameleonMeasurer in server/cros/chameleon/chameleon_measurer.py.
+
+    """
+
+    def __init__(self, cros_host, args, chrome, outputdir=None):
+        """Initializes the object."""
+        factory = local_facade_factory.LocalFacadeFactory(chrome)
+        self.display_facade = factory.create_display_facade()
+
+        self.chameleon = chameleon.create_chameleon_board(cros_host.hostname,
+                                                          args)
+        self.chameleon.setup_and_reset(outputdir)
diff --git a/server/cros/chameleon/__init__.py b/server/cros/chameleon/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/server/cros/chameleon/__init__.py
diff --git a/server/cros/chameleon/chameleon_measurer.py b/server/cros/chameleon/chameleon_measurer.py
new file mode 100644
index 0000000..0d114f1
--- /dev/null
+++ b/server/cros/chameleon/chameleon_measurer.py
@@ -0,0 +1,23 @@
+# Copyright 2016 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.
+
+from autotest_lib.client.cros.chameleon import chameleon_measurer
+from autotest_lib.server.cros.multimedia import remote_facade_factory
+
+
+class RemoteChameleonMeasurer(chameleon_measurer._BaseChameleonMeasurer):
+    """A simple tool to measure using Chameleon for a server test.
+
+    This class can only be used in a server test. For a client test, use the
+    LocalChameleonMeasurer in client/cros/chameleon/chameleon_measurer.py.
+
+    """
+
+    def __init__(self, cros_host, outputdir=None):
+        """Initializes the object."""
+        factory = remote_facade_factory.RemoteFacadeFactory(cros_host)
+        self.display_facade = factory.create_display_facade()
+
+        self.chameleon = cros_host.chameleon
+        self.chameleon.setup_and_reset(outputdir)