| # Copyright 2014 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """This test remotely emulates noisy HPD line when connecting to an external |
| display in extended mode using the Chameleon board.""" |
| |
| import logging |
| import time |
| |
| from autotest_lib.client.bin import utils |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.cros.chameleon import chameleon_port_finder |
| from autotest_lib.client.cros.chameleon import chameleon_screen_test |
| from autotest_lib.server import test |
| from autotest_lib.server.cros.multimedia import remote_facade_factory |
| |
| |
| class display_HotPlugNoisy(test.test): |
| """Noisy display HPD test. |
| |
| This test talks to a Chameleon board and a DUT to set up, run, and verify |
| DUT behavior in response to noisy HPD line. |
| """ |
| version = 1 |
| PLUG_CONFIGS = [ |
| # (plugged_before_noise, plugged_after_noise) |
| |
| (False, False), |
| (False, True), |
| (True, False), |
| (True, True), |
| ] |
| |
| # pulse segments in msec that end with plugged state |
| PULSES_PLUGGED = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] |
| # pulse segments in msec that end with unplugged state |
| PULSES_UNPLUGGED = PULSES_PLUGGED + [2048] |
| |
| REPLUG_DELAY_SEC = 1 |
| |
| |
| def run_once(self, host, test_mirrored=False): |
| if test_mirrored and not host.get_board_type() == 'CHROMEBOOK': |
| raise error.TestNAError('DUT is not Chromebook. Test Skipped') |
| |
| factory = remote_facade_factory.RemoteFacadeFactory(host) |
| display_facade = factory.create_display_facade() |
| chameleon_board = host.chameleon |
| |
| chameleon_board.setup_and_reset(self.outputdir) |
| finder = chameleon_port_finder.ChameleonVideoInputFinder( |
| chameleon_board, display_facade) |
| |
| errors = [] |
| warns = [] |
| for chameleon_port in finder.iterate_all_ports(): |
| screen_test = chameleon_screen_test.ChameleonScreenTest( |
| host, chameleon_port, display_facade, self.outputdir) |
| |
| logging.info('See the display on Chameleon: port %d (%s)', |
| chameleon_port.get_connector_id(), |
| chameleon_port.get_connector_type()) |
| |
| logging.info('Set mirrored: %s', test_mirrored) |
| display_facade.set_mirrored(test_mirrored) |
| |
| # Keep the original connector name, for later comparison. |
| expected_connector = display_facade.get_external_connector_name() |
| resolution = display_facade.get_external_resolution() |
| logging.info('See the display on DUT: %s %r', |
| expected_connector, resolution) |
| |
| for (plugged_before_noise, |
| plugged_after_noise) in self.PLUG_CONFIGS: |
| logging.info('TESTING THE CASE: %s > noise > %s', |
| 'plug' if plugged_before_noise else 'unplug', |
| 'plug' if plugged_after_noise else 'unplug') |
| |
| chameleon_port.set_plug(plugged_before_noise) |
| |
| if screen_test.check_external_display_connected( |
| expected_connector if plugged_before_noise else False, |
| errors): |
| # Skip the following test if an unexpected display detected. |
| continue |
| |
| chameleon_port.fire_mixed_hpd_pulses( |
| self.PULSES_PLUGGED if plugged_after_noise |
| else self.PULSES_UNPLUGGED) |
| |
| if plugged_after_noise: |
| chameleon_port.wait_video_input_stable() |
| if test_mirrored: |
| # Wait for resolution change to make sure the resolution |
| # is stable before moving on. This is to deal with the |
| # case where DUT may respond slowly after the noise. |
| # If the resolution doesn't change, then we are |
| # confident that it is stable. Otherwise, a slow |
| # response is caught. |
| r = display_facade.get_internal_resolution() |
| utils.wait_for_value_changed( |
| display_facade.get_internal_resolution, |
| old_value=r) |
| |
| err = screen_test.check_external_display_connected( |
| expected_connector) |
| |
| if not err: |
| err = screen_test.test_screen_with_image( |
| resolution, test_mirrored) |
| if err: |
| # When something goes wrong after the noise, a normal |
| # user would try to re-plug the cable to recover. |
| # We emulate this behavior below and report error if |
| # the problem persists. |
| logging.warn('Possibly flaky: %s', err) |
| warns.append('Possibly flaky: %s' % err) |
| logging.info('Replug and retry the screen test...') |
| chameleon_port.unplug() |
| time.sleep(self.REPLUG_DELAY_SEC) |
| chameleon_port.plug() |
| chameleon_port.wait_video_input_stable() |
| screen_test.test_screen_with_image( |
| resolution, test_mirrored, errors) |
| else: |
| screen_test.check_external_display_connected(False, errors) |
| time.sleep(1) |
| |
| if errors: |
| raise error.TestFail('; '.join(set(errors))) |
| elif warns: |
| raise error.TestWarn('; '.join(set(warns))) |