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