1# Lint as: python2, python3 2# Copyright 2014 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""This is a server side resolution display test using the Chameleon board.""" 7 8import logging 9import os 10import time 11 12from autotest_lib.client.bin import utils 13from autotest_lib.client.common_lib import error 14from autotest_lib.client.cros.chameleon import chameleon_port_finder 15from autotest_lib.client.cros.chameleon import chameleon_screen_test 16from autotest_lib.client.cros.chameleon import edid 17from autotest_lib.server import test 18from autotest_lib.server.cros.multimedia import remote_facade_factory 19 20 21class display_Resolution(test.test): 22 """Server side external display test. 23 24 This test talks to a Chameleon board and a DUT to set up, run, and verify 25 external display function of the DUT. 26 """ 27 version = 1 28 29 # Allowed timeout for reboot. 30 REBOOT_TIMEOUT = 30 31 # Time to allow lid transition to take effect 32 WAIT_TIME_LID_TRANSITION = 5 33 34 DEFAULT_RESOLUTION_LIST = [ 35 ('EDIDv1', 1280, 800), 36 ('EDIDv1', 1440, 900), 37 ('EDIDv1', 1600, 900), 38 ('EDIDv1', 1680, 1050), 39 ('EDIDv2', 1280, 720), 40 ('EDIDv2', 1920, 1080), 41 ] 42 # These boards are unable to work with servo - crosbug.com/p/27591. 43 INCOMPATIBLE_SERVO_BOARDS = ['daisy', 'falco'] 44 45 # These boards and EDID resolutions are not compatible -crbug.com/905415 46 INCOMPATIBLE_EDID_RESOLUTION_LIST = [ 47 ('EDIDv1', 1280, 800), 48 ('EDIDv1', 1600, 900), 49 ] 50 INCOMPATIBLE_EDID_BOARDS = ['coral', 'eve', 'grunt', 'nami', 'rammus', 51 'zork'] 52 53 def run_once(self, host, test_mirrored=False, test_suspend_resume=False, 54 test_reboot=False, test_lid_close_open=False, 55 resolution_list=None): 56 """Check conditions, do setup and run test. 57 """ 58 59 # Check the servo object. 60 if test_lid_close_open and host.servo is None: 61 raise error.TestError('Invalid servo object found on the host.') 62 if test_lid_close_open and not host.get_board_type() == 'CHROMEBOOK': 63 raise error.TestNAError('DUT is not Chromebook. Test Skipped') 64 if test_mirrored and not host.get_board_type() == 'CHROMEBOOK': 65 raise error.TestNAError('DUT is not Chromebook. Test Skipped') 66 67 # Check for incompatible with servo chromebooks. 68 board_name = host.get_board().split(':')[1] 69 if board_name in self.INCOMPATIBLE_SERVO_BOARDS: 70 raise error.TestNAError( 71 'DUT is incompatible with servo. Skipping test.') 72 73 self.host = host 74 factory = remote_facade_factory.RemoteFacadeFactory(host) 75 display_facade = factory.create_display_facade() 76 chameleon_board = host.chameleon 77 78 chameleon_board.setup_and_reset(self.outputdir) 79 finder = chameleon_port_finder.ChameleonVideoInputFinder( 80 chameleon_board, display_facade) 81 82 errors = [] 83 if resolution_list is None: 84 resolution_list = self.DEFAULT_RESOLUTION_LIST 85 86 # Remove board specific incompatible EDIDs. 87 if board_name.replace('-kernelnext', '') in \ 88 self.INCOMPATIBLE_EDID_BOARDS: 89 for edid_value in self.INCOMPATIBLE_EDID_RESOLUTION_LIST: 90 if edid_value in resolution_list: 91 resolution_list.remove(edid_value) 92 93 chameleon_supported = True 94 for chameleon_port in finder.iterate_all_ports(): 95 screen_test = chameleon_screen_test.ChameleonScreenTest( 96 host, chameleon_port, display_facade, self.outputdir) 97 chameleon_port_name = chameleon_port.get_connector_type() 98 logging.info('Detected %s chameleon port.', chameleon_port_name) 99 for label, width, height in resolution_list: 100 test_resolution = (width, height) 101 test_name = "%s_%dx%d" % ((label,) + test_resolution) 102 103 # The chameleon DP RX doesn't support 4K resolution. 104 # The max supported resolution is 2560x1600. 105 # See crbug/585900 106 if (chameleon_port_name.startswith('DP') and 107 test_resolution > (2560,1600)): 108 chameleon_supported = False 109 110 if not edid.is_edid_supported(host, width, height): 111 logging.info('Skip unsupported EDID: %s', test_name) 112 continue 113 114 if test_lid_close_open: 115 logging.info('Close lid...') 116 host.servo.lid_close() 117 time.sleep(self.WAIT_TIME_LID_TRANSITION) 118 119 if test_reboot: 120 # Unplug the monitor explicitly. Otherwise, the following 121 # use_edid_file() call would expect a valid video signal, 122 # which is not true during reboot. 123 chameleon_port.unplug() 124 logging.info('Reboot...') 125 boot_id = host.get_boot_id() 126 host.reboot(wait=False) 127 host.test_wait_for_shutdown(self.REBOOT_TIMEOUT) 128 129 path = os.path.join(self.bindir, 'test_data', 'edids', 130 test_name) 131 logging.info('Use EDID: %s', test_name) 132 with chameleon_port.use_edid_file(path): 133 if test_lid_close_open: 134 logging.info('Open lid...') 135 host.servo.lid_open() 136 time.sleep(self.WAIT_TIME_LID_TRANSITION) 137 138 if test_reboot: 139 host.test_wait_for_boot(boot_id) 140 chameleon_port.plug() 141 142 utils.wait_for_value_changed( 143 display_facade.get_external_connector_name, 144 old_value=False) 145 146 logging.info('Set mirrored: %s', test_mirrored) 147 display_facade.set_mirrored(test_mirrored) 148 if test_suspend_resume: 149 if test_mirrored: 150 # magic sleep to wake up nyan_big in mirrored mode 151 # TODO: find root cause 152 time.sleep(6) 153 logging.info('Going to suspend...') 154 display_facade.suspend_resume() 155 logging.info('Resumed back') 156 157 screen_test.test_screen_with_image(test_resolution, 158 test_mirrored, errors, chameleon_supported) 159 160 if errors: 161 raise error.TestFail('; '.join(set(errors))) 162 163 def cleanup(self): 164 """Test cleanup""" 165 # Keep device in lid open sate. 166 if self.host.servo: 167 logging.info('Open lid...') 168 self.host.servo.lid_open() 169 time.sleep(self.WAIT_TIME_LID_TRANSITION) 170