• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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