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 display hot-plug and suspend test using the Chameleon board.""" 7 8from __future__ import print_function 9 10import logging 11import time 12 13from autotest_lib.client.bin import utils 14from autotest_lib.client.common_lib import error 15from autotest_lib.client.cros.chameleon import chameleon_port_finder 16from autotest_lib.client.cros.chameleon import chameleon_screen_test 17from autotest_lib.server import test 18from autotest_lib.server.cros.multimedia import remote_facade_factory 19 20 21class display_HotPlugAtSuspend(test.test): 22 """Display hot-plug and suspend test. 23 24 This test talks to a Chameleon board and a DUT to set up, run, and verify 25 DUT behavior response to different configuration of hot-plug during 26 suspend/resume. 27 """ 28 version = 1 29 # Duration of suspend, in second. 30 SUSPEND_DURATION = 40 31 # Allowed timeout for the transition of suspend. 32 SUSPEND_TIMEOUT = 30 33 # Allowed timeout for the transition of resume. 34 RESUME_TIMEOUT = 60 35 # Time margin to do plug/unplug before resume. 36 TIME_MARGIN_BEFORE_RESUME = 5 37 # Timeout of waiting DUT mirrored. 38 TIMEOUT_WAITING_MIRRORED = 5 39 40 41 def run_once(self, host, plug_status, test_mirrored=False): 42 if test_mirrored and not host.get_board_type() == 'CHROMEBOOK': 43 raise error.TestNAError('DUT is not Chromebook. Test Skipped') 44 45 factory = remote_facade_factory.RemoteFacadeFactory(host) 46 display_facade = factory.create_display_facade() 47 chameleon_board = host.chameleon 48 49 chameleon_board.setup_and_reset(self.outputdir) 50 finder = chameleon_port_finder.ChameleonVideoInputFinder( 51 chameleon_board, display_facade) 52 53 errors = [] 54 is_display_failure = False 55 for chameleon_port in finder.iterate_all_ports(): 56 screen_test = chameleon_screen_test.ChameleonScreenTest( 57 host, chameleon_port, display_facade, self.outputdir) 58 59 logging.info('See the display on Chameleon: port %d (%s)', 60 chameleon_port.get_connector_id(), 61 chameleon_port.get_connector_type()) 62 63 logging.info('Set mirrored: %s', test_mirrored) 64 display_facade.set_mirrored(test_mirrored) 65 66 # Keep the original connector name, for later comparison. 67 expected_connector = display_facade.get_external_connector_name() 68 resolution = display_facade.get_external_resolution() 69 logging.info('See the display on DUT: %s %r', 70 expected_connector, resolution) 71 72 for (plugged_before_suspend, plugged_after_suspend, 73 plugged_before_resume) in plug_status: 74 test_case = ('TEST CASE: %s > SUSPEND > %s > %s > RESUME' % 75 ('PLUG' if plugged_before_suspend else 'UNPLUG', 76 'PLUG' if plugged_after_suspend else 'UNPLUG', 77 'PLUG' if plugged_before_resume else 'UNPLUG')) 78 logging.info(test_case) 79 boot_id = host.get_boot_id() 80 chameleon_port.set_plug(plugged_before_suspend) 81 82 if screen_test.check_external_display_connected( 83 expected_connector if plugged_before_suspend else False, 84 errors): 85 is_display_failure = True 86 # Skip the following test if an unexpected display detected. 87 continue 88 89 logging.info('GOING TO SUSPEND FOR %d SECONDS...', 90 self.SUSPEND_DURATION) 91 time_before_suspend = time.time() 92 display_facade.suspend_resume_bg(self.SUSPEND_DURATION) 93 94 # Confirm DUT suspended. 95 logging.info('WAITING FOR SUSPEND...') 96 try: 97 host.test_wait_for_sleep(self.SUSPEND_TIMEOUT) 98 except error.TestFail as ex: 99 errors.append("%s - %s" % (test_case, str(ex))) 100 if plugged_after_suspend is not plugged_before_suspend: 101 chameleon_port.set_plug(plugged_after_suspend) 102 103 current_time = time.time() 104 sleep_time = (self.SUSPEND_DURATION - 105 (current_time - time_before_suspend) - 106 self.TIME_MARGIN_BEFORE_RESUME) 107 if sleep_time > 0: 108 logging.info('- Sleep for %.2f seconds...', sleep_time) 109 time.sleep(sleep_time) 110 if plugged_before_resume is not plugged_after_suspend: 111 chameleon_port.set_plug(plugged_before_resume) 112 time.sleep(self.TIME_MARGIN_BEFORE_RESUME) 113 114 logging.info('WAITING FOR RESUME...') 115 try: 116 host.test_wait_for_resume(boot_id, self.RESUME_TIMEOUT) 117 except error.TestFail as ex: 118 errors.append("%s - %s" % (test_case, str(ex))) 119 120 logging.info('Resumed back') 121 122 if screen_test.check_external_display_connected( 123 expected_connector if plugged_before_resume else False, 124 errors): 125 # Skip the following test if an unexpected display detected. 126 continue 127 128 if plugged_before_resume: 129 if test_mirrored and (not utils.wait_for_value( 130 display_facade.is_mirrored_enabled, True, 131 timeout_sec=self.TIMEOUT_WAITING_MIRRORED)): 132 error_message = 'Error: not resumed to mirrored mode' 133 errors.append("%s - %s" % (test_case, error_message)) 134 logging.error(error_message) 135 logging.info('Set mirrored: %s', True) 136 display_facade.set_mirrored(True) 137 elif screen_test.test_screen_with_image( 138 resolution, test_mirrored, errors): 139 is_display_failure = True 140 141 if errors: 142 if is_display_failure: 143 raise error.TestFail('; '.join(set(errors))) 144 else: 145 raise error.TestError('; '.join(set(errors))) 146