Home | History | Annotate | Download | only in display_HotPlugNoisy
      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
      6 display in extended mode using the Chameleon board."""
      7 
      8 import logging
      9 import time
     10 
     11 from autotest_lib.client.bin import utils
     12 from autotest_lib.client.common_lib import error
     13 from autotest_lib.client.cros.chameleon import chameleon_port_finder
     14 from autotest_lib.client.cros.chameleon import chameleon_screen_test
     15 from autotest_lib.server import test
     16 from autotest_lib.server.cros.multimedia import remote_facade_factory
     17 
     18 
     19 class 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