xref: /aosp_15_r20/external/autotest/client/site_tests/desktopui_ScreenLocker/desktopui_ScreenLocker.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Copyright (c) 2013 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
5import logging
6
7from autotest_lib.client.bin import test, utils
8from autotest_lib.client.common_lib import error
9from autotest_lib.client.common_lib.cros import chrome, session_manager
10from autotest_lib.client.cros import asan
11from autotest_lib.client.cros.input_playback import input_playback
12
13from datetime import datetime
14from dbus.mainloop.glib import DBusGMainLoop
15# AU tests use ToT client code, but ToT -3 client version.
16try:
17    from gi.repository import GObject
18except ImportError:
19    import gobject as GObject
20
21class desktopui_ScreenLocker(test.test):
22    """This is a client side test that exercises the screenlocker."""
23    version = 1
24
25    _SCREEN_IS_LOCKED_TIMEOUT = 30
26    # TODO(jdufault): Remove this timeout increase for asan bots once we figure
27    # out what's taking so long to lock the screen. See crbug.com/452599.
28    if asan.running_on_asan():
29      _SCREEN_IS_LOCKED_TIMEOUT *= 2
30
31    """Timeout for password authentication."""
32    _AUTHENTICATION_TIMEOUT = 30
33
34
35    def initialize(self):
36        """Init method"""
37        super(desktopui_ScreenLocker, self).initialize()
38        DBusGMainLoop(set_as_default=True)
39        self.player = input_playback.InputPlayback()
40        self.player.emulate(input_type='keyboard')
41        self.player.find_connected_inputs()
42
43
44    def cleanup(self):
45        """Test cleanup."""
46        self.player.close()
47
48
49    @property
50    def screen_locked(self):
51        """True if the screen is locked."""
52        return self._chrome.login_status['isScreenLocked']
53
54
55    @property
56    def screen_ready_for_password(self):
57        """True if the screen is ready for password."""
58        return self._chrome.login_status['isReadyForPassword']
59
60
61    def lock_screen(self, perf_values):
62        """Lock the screen.
63
64        @param perf_values: Performance data will be stored inside of this dict.
65
66        @raises: error.TestFail when screen already locked.
67        @raises: error.TestFail when screen not locked.
68
69        """
70        logging.debug('lock_screen')
71        if self.screen_locked:
72            raise error.TestFail('Screen already locked')
73        signal_listener = session_manager.ScreenIsLockedSignalListener(
74                GObject.MainLoop())
75        ext = self._chrome.autotest_ext
76
77        start = datetime.now()
78        ext.EvaluateJavaScript('chrome.autotestPrivate.lockScreen();')
79        signal_listener.wait_for_signals(desc='Screen is locked.',
80                                         timeout=self._SCREEN_IS_LOCKED_TIMEOUT)
81        perf_values['lock_seconds'] = (datetime.now() - start).total_seconds()
82
83        utils.poll_for_condition(
84                lambda: self.screen_locked,
85                exception=error.TestFail('Screen not locked'))
86
87
88    def lock_screen_through_keyboard(self):
89        """Lock the screen with keyboard(search+L) .
90
91         @raises: error.TestFail when screen already locked.
92         @raises: error.TestFail if screen not locked after using keyboard
93                  shortcut.
94
95         """
96        logging.debug('Locking screen through the keyboard shortcut')
97        if self.screen_locked:
98            raise error.TestFail('Screen already locked')
99        self.player.blocking_playback_of_default_file(
100            input_type='keyboard', filename='keyboard_search+L')
101        utils.poll_for_condition(
102                lambda: self.screen_locked,
103                exception=error.TestFail(
104                        'Screen not locked after using keyboard shortcut'))
105
106
107    def attempt_unlock_bad_password(self):
108        """Attempt unlock with a bad password.
109
110         @raises: error.TestFail when successfully unlock with bad password.
111
112         """
113        logging.debug('attempt_unlock_bad_password')
114        self.player.blocking_playback_of_default_file(
115                input_type='keyboard', filename='keyboard_b+a+d+enter')
116
117        # Wait for the authentication to complete.
118        utils.poll_for_condition(
119                lambda: self.screen_ready_for_password,
120                exception=error.TestFail(
121                        'Authentication is not completed after %d seconds',
122                        self._AUTHENTICATION_TIMEOUT),
123                timeout=self._AUTHENTICATION_TIMEOUT)
124        if not self.screen_locked:
125            raise error.TestFail('Screen unlocked with bad password')
126
127
128    def unlock_screen(self):
129        """Unlock the screen with the right password. The correct password is
130           the empty string.
131           TODO(crbug.com/792251): Use non-empty password.
132
133         @raises: error.TestFail if failed to unlock screen.
134
135        """
136        logging.debug('unlock_screen')
137        self.player.blocking_playback_of_default_file(
138                input_type='keyboard', filename='keyboard_g+o+o+d+enter')
139        utils.poll_for_condition(
140                lambda: not self.screen_locked,
141                exception=error.TestFail('Failed to unlock screen'),
142                timeout=self._AUTHENTICATION_TIMEOUT)
143
144
145    def run_once(self):
146        """
147        This test locks the screen, tries to unlock with a bad password,
148        then unlocks with the right password.
149
150        """
151        with chrome.Chrome(autotest_ext=True, password='good') as self._chrome:
152            try:
153                # Give performance data some initial state that will be reported
154                # if the test times out.
155                perf_values = { 'lock_seconds': self._SCREEN_IS_LOCKED_TIMEOUT }
156
157                self.lock_screen(perf_values)
158                self.attempt_unlock_bad_password()
159                self.unlock_screen()
160                self.lock_screen_through_keyboard()
161                self.unlock_screen()
162            finally:
163                self.output_perf_value(
164                        description='time_to_lock_screen',
165                        value=perf_values['lock_seconds'],
166                        units='s',
167                        higher_is_better=False)
168