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 factory = remote_facade_factory.RemoteFacadeFactory(host) 45 display_facade = factory.create_display_facade() 46 chameleon_board = host.chameleon 47 48 chameleon_board.reset() 49 finder = chameleon_port_finder.ChameleonVideoInputFinder( 50 chameleon_board, display_facade) 51 52 errors = [] 53 warns = [] 54 for chameleon_port in finder.iterate_all_ports(): 55 screen_test = chameleon_screen_test.ChameleonScreenTest( 56 chameleon_port, display_facade, self.outputdir) 57 58 logging.info('See the display on Chameleon: port %d (%s)', 59 chameleon_port.get_connector_id(), 60 chameleon_port.get_connector_type()) 61 62 logging.info('Set mirrored: %s', test_mirrored) 63 display_facade.set_mirrored(test_mirrored) 64 65 # Keep the original connector name, for later comparison. 66 expected_connector = display_facade.get_external_connector_name() 67 resolution = display_facade.get_external_resolution() 68 logging.info('See the display on DUT: %s %r', 69 expected_connector, resolution) 70 71 for (plugged_before_noise, 72 plugged_after_noise) in self.PLUG_CONFIGS: 73 logging.info('TESTING THE CASE: %s > noise > %s', 74 'plug' if plugged_before_noise else 'unplug', 75 'plug' if plugged_after_noise else 'unplug') 76 77 chameleon_port.set_plug(plugged_before_noise) 78 79 if screen_test.check_external_display_connected( 80 expected_connector if plugged_before_noise else False, 81 errors): 82 # Skip the following test if an unexpected display detected. 83 continue 84 85 chameleon_port.fire_mixed_hpd_pulses( 86 self.PULSES_PLUGGED if plugged_after_noise 87 else self.PULSES_UNPLUGGED) 88 89 if plugged_after_noise: 90 chameleon_port.wait_video_input_stable() 91 if test_mirrored: 92 # Wait for resolution change to make sure the resolution 93 # is stable before moving on. This is to deal with the 94 # case where DUT may respond slowly after the noise. 95 # If the resolution doesn't change, then we are 96 # confident that it is stable. Otherwise, a slow 97 # response is caught. 98 r = display_facade.get_internal_resolution() 99 utils.wait_for_value_changed( 100 display_facade.get_internal_resolution, 101 old_value=r) 102 103 err = screen_test.check_external_display_connected( 104 expected_connector) 105 106 if not err: 107 err = screen_test.test_screen_with_image( 108 resolution, test_mirrored) 109 if err: 110 # When something goes wrong after the noise, a normal 111 # user would try to re-plug the cable to recover. 112 # We emulate this behavior below and report error if 113 # the problem persists. 114 logging.warn('Possibly flaky: %s', err) 115 warns.append('Possibly flaky: %s' % err) 116 logging.info('Replug and retry the screen test...') 117 chameleon_port.unplug() 118 time.sleep(self.REPLUG_DELAY_SEC) 119 chameleon_port.plug() 120 chameleon_port.wait_video_input_stable() 121 screen_test.test_screen_with_image( 122 resolution, test_mirrored, errors) 123 else: 124 screen_test.check_external_display_connected(False, errors) 125 time.sleep(1) 126 127 if errors: 128 raise error.TestFail('; '.join(set(errors))) 129 elif warns: 130 raise error.TestWarn('; '.join(set(warns))) 131