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"""This test remotely emulates noisy HPD line when connecting to an external 6display in extended mode using the Chameleon board.""" 7 8import logging 9import time 10 11from autotest_lib.client.bin import utils 12from autotest_lib.client.common_lib import error 13from autotest_lib.client.cros.chameleon import chameleon_port_finder 14from autotest_lib.client.cros.chameleon import chameleon_screen_test 15from autotest_lib.server import test 16from autotest_lib.server.cros.multimedia import remote_facade_factory 17 18 19class display_HotPlugNoisy(test.test): 20 """Noisy display HPD test. 21 22 This test talks to a Chameleon board and a DUT to set up, run, and verify 23 DUT behavior in response to noisy HPD line. 24 """ 25 version = 1 26 PLUG_CONFIGS = [ 27 # (plugged_before_noise, plugged_after_noise) 28 29 (False, False), 30 (False, True), 31 (True, False), 32 (True, True), 33 ] 34 35 # pulse segments in msec that end with plugged state 36 PULSES_PLUGGED = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] 37 # pulse segments in msec that end with unplugged state 38 PULSES_UNPLUGGED = PULSES_PLUGGED + [2048] 39 40 REPLUG_DELAY_SEC = 1 41 42 43 def run_once(self, host, test_mirrored=False): 44 if test_mirrored and not host.get_board_type() == 'CHROMEBOOK': 45 raise error.TestNAError('DUT is not Chromebook. Test Skipped') 46 47 factory = remote_facade_factory.RemoteFacadeFactory(host) 48 display_facade = factory.create_display_facade() 49 chameleon_board = host.chameleon 50 51 chameleon_board.setup_and_reset(self.outputdir) 52 finder = chameleon_port_finder.ChameleonVideoInputFinder( 53 chameleon_board, display_facade) 54 55 errors = [] 56 warns = [] 57 for chameleon_port in finder.iterate_all_ports(): 58 screen_test = chameleon_screen_test.ChameleonScreenTest( 59 chameleon_port, display_facade, self.outputdir) 60 61 logging.info('See the display on Chameleon: port %d (%s)', 62 chameleon_port.get_connector_id(), 63 chameleon_port.get_connector_type()) 64 65 logging.info('Set mirrored: %s', test_mirrored) 66 display_facade.set_mirrored(test_mirrored) 67 68 # Keep the original connector name, for later comparison. 69 expected_connector = display_facade.get_external_connector_name() 70 resolution = display_facade.get_external_resolution() 71 logging.info('See the display on DUT: %s %r', 72 expected_connector, resolution) 73 74 for (plugged_before_noise, 75 plugged_after_noise) in self.PLUG_CONFIGS: 76 logging.info('TESTING THE CASE: %s > noise > %s', 77 'plug' if plugged_before_noise else 'unplug', 78 'plug' if plugged_after_noise else 'unplug') 79 80 chameleon_port.set_plug(plugged_before_noise) 81 82 if screen_test.check_external_display_connected( 83 expected_connector if plugged_before_noise else False, 84 errors): 85 # Skip the following test if an unexpected display detected. 86 continue 87 88 chameleon_port.fire_mixed_hpd_pulses( 89 self.PULSES_PLUGGED if plugged_after_noise 90 else self.PULSES_UNPLUGGED) 91 92 if plugged_after_noise: 93 chameleon_port.wait_video_input_stable() 94 if test_mirrored: 95 # Wait for resolution change to make sure the resolution 96 # is stable before moving on. This is to deal with the 97 # case where DUT may respond slowly after the noise. 98 # If the resolution doesn't change, then we are 99 # confident that it is stable. Otherwise, a slow 100 # response is caught. 101 r = display_facade.get_internal_resolution() 102 utils.wait_for_value_changed( 103 display_facade.get_internal_resolution, 104 old_value=r) 105 106 err = screen_test.check_external_display_connected( 107 expected_connector) 108 109 if not err: 110 err = screen_test.test_screen_with_image( 111 resolution, test_mirrored) 112 if err: 113 # When something goes wrong after the noise, a normal 114 # user would try to re-plug the cable to recover. 115 # We emulate this behavior below and report error if 116 # the problem persists. 117 logging.warn('Possibly flaky: %s', err) 118 warns.append('Possibly flaky: %s' % err) 119 logging.info('Replug and retry the screen test...') 120 chameleon_port.unplug() 121 time.sleep(self.REPLUG_DELAY_SEC) 122 chameleon_port.plug() 123 chameleon_port.wait_video_input_stable() 124 screen_test.test_screen_with_image( 125 resolution, test_mirrored, errors) 126 else: 127 screen_test.check_external_display_connected(False, errors) 128 time.sleep(1) 129 130 if errors: 131 raise error.TestFail('; '.join(set(errors))) 132 elif warns: 133 raise error.TestWarn('; '.join(set(warns))) 134