1# Copyright 2014 The Chromium OS 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"""Classes to do resolution comparison."""
6
7import logging
8import xmlrpclib
9
10
11class ExactMatchResolutionComparer(object):
12    """A class to compare the resolutions by using exact match.
13
14    Calling its member method compare() does the comparison.
15
16    """
17
18    def __init__(self, chameleon_port, display_facade):
19        """Initializes the ExactMatchResolutionComparer objects."""
20        self._chameleon_port = chameleon_port
21        self._display_facade = display_facade
22
23
24    def compare(self, expected_resolution):
25        """Compares the resolutions among the given one, Chameleon's, and CrOS'.
26
27        This method first checks if CrOS is under mirrored mode or not.
28
29        If under extended mode, checks the resolutions of both CrOS and
30        Chameleon exactly match the expected one.
31
32        If under mirror mode, only checks the resolution of CrOS exactly
33        matches the one of Chameleon.
34
35        @param expected_resolution: A tuple (width, height) for the expected
36                                    resolution.
37        @return: None if the check passes; otherwise, a string of error message.
38        """
39        try:
40            chameleon_resolution = self._chameleon_port.get_resolution()
41        except xmlrpclib.Fault as e:
42            logging.exception(e)
43            return str(e)
44        cros_resolution = self._display_facade.get_external_resolution()
45
46        logging.info('Checking the resolutions of Chameleon and CrOS...')
47        if expected_resolution != cros_resolution or (
48                chameleon_resolution != cros_resolution):
49            message = ('Detected mis-matched resolutions: '
50                       'CrOS %r; Chameleon %r; Expected %r.' %
51                       (cros_resolution, chameleon_resolution,
52                        expected_resolution))
53            # Note: In mirrored mode, the device may be in hardware mirror
54            # (as opposed to software mirror). If so, the actual resolution
55            # could be different from the expected one. So we skip the check
56            # in mirrored mode. The resolution of the CrOS and Chameleon
57            # should be same no matter the device in mirror mode or not.
58            if chameleon_resolution != cros_resolution or (
59                    not self._display_facade.is_mirrored_enabled()):
60                logging.error(message)
61                return message
62            else:
63                logging.warn(message)
64        else:
65            logging.info('Resolutions across CrOS and Chameleon match: %dx%d',
66                         *expected_resolution)
67        return None
68
69
70class VgaResolutionComparer(object):
71    """A class to compare the resolutions for VGA interface.
72
73    Calling its member method compare() does the comparison.
74
75    """
76
77    def __init__(self, chameleon_port, display_facade):
78        """Initializes the VgaResolutionComparer objects."""
79        self._chameleon_port = chameleon_port
80        self._display_facade = display_facade
81
82
83    def compare(self, expected_resolution):
84        """Compares the resolutions among the given one, Chameleon's, and CrOS'.
85
86        There is no DE (data enable) signal in the VGA standard, the captured
87        image of Chameleon side is larger than the expected image.
88
89        It checks the resolution of CrOS matches the expected one and
90        the resolution of Chameleon is larger than or equal to the one of CrOS.
91
92        @param expected_resolution: A tuple (width, height) of the expected
93                                    resolution.
94        @return: None if the check passes; otherwise, a string of error message.
95        """
96        try:
97            chameleon_resolution = self._chameleon_port.get_resolution()
98        except xmlrpclib.Fault as e:
99            logging.exception(e)
100            return str(e)
101        cros_resolution = self._display_facade.get_external_resolution()
102
103        logging.info('Checking the resolutions of Chameleon and CrOS...')
104        if expected_resolution != cros_resolution or (
105                chameleon_resolution[0] < cros_resolution[0] or
106                chameleon_resolution[1] < cros_resolution[1]):
107            message = ('Detected mis-matched VGA resolutions: '
108                       'CrOS %r; Chameleon %r; Expected %r.' %
109                       (cros_resolution, chameleon_resolution,
110                        expected_resolution))
111            logging.error(message)
112            return message
113        else:
114            logging.info('Detected VGA resolutions: '
115                         'CrOS: %dx%d; Chameleon: %dx%d.',
116                         *(cros_resolution + chameleon_resolution))
117        return None
118