1#!/usr/bin/python
2#
3# Copyright (c) 2010 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7__author__ = 'kdlucas@chromium.org (Kelly Lucas)'
8
9import logging, re
10
11from autotest_lib.client.bin import test, utils
12from autotest_lib.client.common_lib import error
13from autotest_lib.client.cros.graphics import graphics_utils
14
15_SUPPORTED_LVDS_RESOLUTIONS = ['1280x800', '1366x768']
16
17_MODETEST_COMMAND = 'modetest -c'
18_MODETEST_CONNECTED = 'connected'
19_MODETEST_CONNECTOR_LVDS = 'LVDS'
20# The list of connectors in this regex pattern comes from an array called
21# connector_type_names in the libdrm file caled modetest.c .
22_MODETEST_CONNECTOR_PATTERN = (r'\d+\s+\d+\s+(connected|disconnected)\s+'
23                               r'(unknown|VGA|DVI-I|DVI-D|DVI-A|composite|'
24                               r's-video|LVDS|component|9-pin DIN|HDMI-A|'
25                               r'HDMI-B|TV|eDP)\s+\d+x\d+\s+\d+\s+\d+')
26_MODETEST_MODE_PATTERN = (r'\s+.+\d+\s+(\d+)\s+\d+\s+\d+\s+\d+\s+(\d+)\s+\d+\s+'
27                          r'\d+\s+\d+\s+flags:')
28
29_LVDS_UNSUPPORTED_MESSAGE = '%s is not a supported LVDS resolution'
30
31class hardware_Resolution(test.test):
32    """
33    Verify the current screen resolution is supported.
34    """
35    version = 1
36
37    def is_lvds_res(self, res, xrandr_output):
38        """
39        Returns True if the supplied resolution is associated with
40        an LVDS connection.
41        """
42        search_str = r'LVDS\d+ connected ' + res
43        for line in xrandr_output:
44            if re.match(search_str, line):
45                return True
46
47        return False
48
49    def get_current_res(self, xrandr_output):
50        """
51        Get the current video resolution.
52        Returns:
53            string: represents the video resolution.
54        """
55        for line in xrandr_output:
56            if 'Screen 0' in line:
57                sections = line.split(',')
58                for item in sections:
59                    if 'current' in item:
60                        res = item.split()
61                        return '%s%s%s' % (res[1], res[2], res[3])
62
63        return None
64
65    def run_x(self):
66        xrandr_output = graphics_utils.call_xrandr().split('\n')
67
68        res = self.get_current_res(xrandr_output)
69        if not res or not re.match(r'\d+x\d+$', res):
70            raise error.TestFail('%s is not a valid resolution' % res)
71
72        if self.is_lvds_res(res, xrandr_output) and \
73           res not in _SUPPORTED_LVDS_RESOLUTIONS:
74            raise error.TestFail(_LVDS_UNSUPPORTED_MESSAGE % res)
75
76    def run_freon(self):
77        modetest_output = utils.system_output(_MODETEST_COMMAND)
78        logging.info('modetest output: \n{0}'.format(modetest_output))
79
80        # True if the information being read is about a connected LVDS
81        # connector, False otherwise
82        connected_lvds = False
83
84        for line in modetest_output.splitlines():
85            connector_match = re.match(_MODETEST_CONNECTOR_PATTERN, line)
86            if connector_match is not None:
87                connected_lvds = False
88                if connector_match.group(1) == _MODETEST_CONNECTED:
89                    if connector_match.group(2) == _MODETEST_CONNECTOR_LVDS:
90                        connected_lvds = True
91
92            if connected_lvds:
93                mode_match = re.match(_MODETEST_MODE_PATTERN, line)
94                if mode_match is not None:
95                    res = '{0}x{1}'.format(int(mode_match.group(1)),
96                                           int(mode_match.group(2)))
97                    if res not in _SUPPORTED_LVDS_RESOLUTIONS:
98                        raise error.TestFail(_LVDS_UNSUPPORTED_MESSAGE % res)
99
100    def run_once(self):
101        if utils.is_freon():
102            self.run_freon()
103        else:
104            self.run_x()
105