Home | History | Annotate | Download | only in policy_PowerManagementIdleSettings
      1 # Copyright 2016 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 import logging
      6 import time
      7 
      8 from autotest_lib.client.bin import utils
      9 from autotest_lib.client.common_lib import error
     10 from autotest_lib.client.cros import cryptohome
     11 from autotest_lib.client.cros import power_status, power_utils
     12 from autotest_lib.client.cros.enterprise import enterprise_policy_base
     13 from autotest_lib.client.cros.graphics import graphics_utils
     14 
     15 
     16 class policy_PowerManagementIdleSettings(
     17           enterprise_policy_base.EnterprisePolicyTest):
     18     """
     19     Test effect of PowerManagementIdleSettings policy on Chrome OS behavior.
     20 
     21     This test verifies the effect of the PowerManagementIdleSettings user
     22     policy on specific Chrome OS client behaviors. It tests two valid values
     23     for the IdleAction property: 'DoNothing' and Not set, with three test
     24     cases: DoNothing_Continue, NotSet_Sleep, and Logout_EndSession. It also
     25     verifies that the screen dims after ScreenDim delay, and then turns off
     26     after ScreenOff delay (both delays in milliseconds).
     27 
     28     Note: Valid IdleAction values are 'DoNothing', 'Suspend', 'Logout', and
     29     'Shutdown'. This test exercises only the DoNothing and Logout actions.
     30     Suspend is tested by enterprise_PowerManager.py. Shutdown can be tested
     31     only using a Server-side AutoTest.
     32 
     33     Chrome reports user activity to the power manager at most every 5 seconds.
     34     To accomodate potential delays, the test pads the idle-action delay with
     35     a 5 second activity report interval.
     36 
     37     Several supporting policies are necessary to facillitate testing, or to
     38     make testing more reliable. These policies are listed below with a brief
     39     description of the set value.
     40     - WaitForInitialUserActivity=False so idle timer starts immediately after
     41       session starts.
     42     - UserActivityScreenDimDelayScale=100 to prevent increase delays when
     43       user activity occurs after screen dim.
     44     - ChromeOsLockOnIdleSuspend=False to prevent screen lock upon suspend.
     45     - AllowScreenLock=False to prevent manual screen lock. Will not affect
     46       this test, but is the safest setting.
     47     - AllowScreenWakeLocks=False to ignore 'keep awake' requests. Since wake
     48       locks are not requested during this test, ignoring them is unnecessary.
     49       But for safety we ignore them when testing suspend.
     50     - LidCloseAction=3 to invoke no action upon (accidental) lid closure.
     51     - ResoreOnStartup* polices are set to display the settings and policy
     52       pages. This is useful when debugging failures.
     53 
     54     """
     55     version = 1
     56 
     57     def initialize(self, **kwargs):
     58         """Set up local variables and ensure device is on AC power."""
     59         self._initialize_test_constants()
     60         self._power_status = power_status.get_status()
     61         if not self._power_status.on_ac():
     62             raise error.TestNAError('Test must be run with DUT on AC power.')
     63         self._backlight = power_utils.Backlight()
     64         super(policy_PowerManagementIdleSettings, self).initialize(**kwargs)
     65 
     66     def _initialize_test_constants(self):
     67         self.POLICY_NAME = 'PowerManagementIdleSettings'
     68         self.SCREEN_SETTLE_TIME = 0.3
     69         self.SCREEN_DIM_DELAY = 4
     70         self.IDLE_WARNING_DELAY = 6
     71         self.SCREEN_OFF_DELAY = 8
     72         self.IDLE_ACTION_DELAY = 10
     73         self.ACTIVITY_REPORT_INTERVAL = 5
     74         self.IDLE_ACTION_NOTSET = {
     75             'AC': {
     76                 'Delays': {
     77                     'ScreenDim': (self.SCREEN_DIM_DELAY * 1000),
     78                     'IdleWarning': (self.IDLE_WARNING_DELAY * 1000),
     79                     'ScreenOff': (self.SCREEN_OFF_DELAY * 1000),
     80                     'Idle': (self.IDLE_ACTION_DELAY * 1000)
     81                 }
     82             }
     83         }
     84         self.IDLE_ACTION_DONOTHING = {
     85             'AC': {
     86                 'Delays': {
     87                     'ScreenDim': (self.SCREEN_DIM_DELAY * 1000),
     88                     'IdleWarning': (self.IDLE_WARNING_DELAY * 1000),
     89                     'ScreenOff': (self.SCREEN_OFF_DELAY * 1000),
     90                     'Idle': (self.IDLE_ACTION_DELAY * 1000)
     91                 },
     92                 'IdleAction': 'DoNothing'
     93             }
     94         }
     95         self.IDLE_ACTION_LOGOUT = {
     96             'AC': {
     97                 'Delays': {
     98                     'ScreenDim': (self.SCREEN_DIM_DELAY * 1000),
     99                     'IdleWarning': (self.IDLE_WARNING_DELAY * 1000),
    100                     'ScreenOff': (self.SCREEN_OFF_DELAY * 1000),
    101                     'Idle': (self.IDLE_ACTION_DELAY * 1000)
    102                 },
    103                 'IdleAction': 'Logout'
    104             }
    105         }
    106         self.TEST_CASES = {
    107             'NotSet_Sleep': self.IDLE_ACTION_NOTSET,
    108             'DoNothing_Continue': self.IDLE_ACTION_DONOTHING,
    109             'Logout_EndSession': self.IDLE_ACTION_LOGOUT
    110         }
    111         self.STARTUP_URLS = ['chrome://settings', 'chrome://policy']
    112         self.SUPPORTING_POLICIES = {
    113             'WaitForInitialUserActivity': True,
    114             'UserActivityScreenDimDelayScale': 100,
    115             'ChromeOsLockOnIdleSuspend': False,
    116             'AllowScreenLock': False,
    117             'AllowScreenWakeLocks': False,
    118             'LidCloseAction': 3,
    119             'RestoreOnStartup': 4,
    120             'RestoreOnStartupURLs': self.STARTUP_URLS
    121         }
    122 
    123 
    124     def elapsed_time(self, start_time):
    125         """Get time elapsed since |start_time|.
    126 
    127         @param start_time: clock time from which elapsed time is measured.
    128         @returns time elapsed since the start time.
    129         """
    130         return time.time() - start_time
    131 
    132 
    133     def _simulate_user_activity(self):
    134         """Inject user activity via D-bus to restart idle timer.
    135 
    136         Note that if the screen has gone black, these use activities will
    137         wake up the display again. However, they will not wake up a screen
    138         that has merely been dimmed.
    139 
    140         """
    141         graphics_utils.click_mouse()  # Note: Duration is 0.4 seconds.
    142         graphics_utils.press_keys(['KEY_LEFTCTRL'])
    143 
    144 
    145     def _wait_for_login_status(self, attribute, value, timeout):
    146         """Return when attribute has value, or its current value on timeout.
    147 
    148         Login_status is a dictionary of attributes that describe the login
    149         status of the current session. It contains values for the following
    150         attributes: isLoggedIn, isRegularUser, isOwner, isKiosk, isGuest,
    151         isScreenLocked, userImage, email, and displayEmail.
    152 
    153         @param attribute: String attribute key to be measured.
    154         @param value: Boolean attribute value expected.
    155         @param timeout: integer seconds till timeout.
    156         @returns dict of login status.
    157 
    158         """
    159         attribute_value = utils.wait_for_value(
    160             lambda: self.cr.login_status[attribute],
    161             expected_value=value,
    162             timeout_sec=timeout)
    163         return attribute_value
    164 
    165 
    166     def _poll_until_user_is_logged_out(self, timeout):
    167         """Return True when user logs out, False when user remains logged in.
    168 
    169         @returns boolean of user logged out status.
    170 
    171         """
    172         my_result = utils.poll_for_condition(
    173             lambda: not cryptohome.is_vault_mounted(user=self.username,
    174                                                     allow_fail=True),
    175             exception=None,
    176             timeout=timeout,
    177             sleep_interval=2,
    178             desc='Polling for user to be logged out.')
    179         return my_result
    180 
    181 
    182     def _set_brightness_to_maximum(self):
    183         """Set screen to maximum brightness."""
    184         max_level = self._backlight.get_max_level()
    185         self._backlight.set_level(max_level)
    186 
    187 
    188     def _wait_for_brightness_change(self, timeout):
    189         """Return screen brightness on update, or current value on timeout.
    190 
    191         @returns float of screen brightness percentage.
    192 
    193         """
    194         initial_brightness = self._backlight.get_percent()
    195         current_brightness = utils.wait_for_value_changed(
    196             lambda: self._backlight.get_percent(),
    197             old_value=initial_brightness,
    198             timeout_sec=timeout)
    199         if current_brightness != initial_brightness:
    200             time.sleep(self.SCREEN_SETTLE_TIME)
    201             current_brightness = self._backlight.get_percent()
    202         return current_brightness
    203 
    204 
    205     def _test_idle_action(self, policy_value):
    206         """
    207         Verify CrOS enforces PowerManagementIdleSettings policy value.
    208 
    209         @param policy_value: policy value for this case.
    210         @raises: TestFail if idle actions are not performed after their
    211                  specified delays.
    212 
    213         """
    214         logging.info('Running _test_idle_action(%s)', policy_value)
    215 
    216         # Wait until UI settles down with user logged in.
    217         user_is_logged_in = self._wait_for_login_status(
    218             'isLoggedIn', True, self.IDLE_ACTION_DELAY)
    219         if not user_is_logged_in:
    220             raise error.TestFail('User must be logged in at start.')
    221 
    222         # Set screen to maxiumum brightness.
    223         self._set_brightness_to_maximum()
    224         max_brightness = self._backlight.get_percent()
    225         logging.info('Brightness maximized to: %.2f', max_brightness)
    226 
    227         # Induce user activity to start idle timer.
    228         self._simulate_user_activity()
    229         start_time = time.time()
    230 
    231         # Verify screen is dimmed after expected delay.
    232         seconds_to_dim = (
    233             self.SCREEN_DIM_DELAY - self.elapsed_time(start_time))
    234         dim_brightness = self._wait_for_brightness_change(seconds_to_dim)
    235         dim_elapsed_time = self.elapsed_time(start_time)
    236         logging.info('  Brightness dimmed to: %.2f, ', dim_brightness)
    237         logging.info('  after %s seconds.', dim_elapsed_time)
    238         if not (dim_brightness < max_brightness and dim_brightness > 0.0):
    239             raise error.TestFail('Screen did not dim on delay.')
    240 
    241         # Verify screen is turned off after expected delay.
    242         seconds_to_off = (
    243             self.SCREEN_OFF_DELAY - self.elapsed_time(start_time))
    244         off_brightness = self._wait_for_brightness_change(seconds_to_off)
    245         off_elapsed_time = self.elapsed_time(start_time)
    246         logging.info('  Brightness off to: %.2f, ', off_brightness)
    247         logging.info('  after %s seconds.', off_elapsed_time)
    248         if not off_brightness < dim_brightness:
    249             raise error.TestFail('Screen did not turn off on delay.')
    250 
    251         # Verify user is still logged in before IdleAction.
    252         user_is_logged_in = self.cr.login_status['isLoggedIn']
    253         if not user_is_logged_in:
    254             raise error.TestFail('User must be logged in before idle action.')
    255 
    256         # Get user logged in state after IdleAction.
    257         seconds_to_action = (
    258             self.IDLE_ACTION_DELAY + self.ACTIVITY_REPORT_INTERVAL
    259             - self.elapsed_time(start_time))
    260         try:
    261             user_is_logged_in = not self._poll_until_user_is_logged_out(
    262                 seconds_to_action)
    263         except utils.TimeoutError:
    264             pass
    265         action_elapsed_time = self.elapsed_time(start_time)
    266         logging.info('  User logged out: %r, ', not user_is_logged_in)
    267         logging.info('  after %s seconds.', action_elapsed_time)
    268 
    269         # Verify user status against expected result, based on case.
    270         if self.case == 'NotSet_Sleep' or self.case == 'DoNothing_Continue':
    271             if not user_is_logged_in:
    272                 raise error.TestFail('User should be logged in.')
    273         elif self.case == 'Logout_EndSession':
    274             if user_is_logged_in:
    275                 raise error.TestFail('User should be logged out.')
    276 
    277 
    278     def run_test_case(self, case):
    279         """
    280         Setup and run the test configured for the specified test case.
    281 
    282         @param case: Name of the test case to run.
    283 
    284         """
    285         case_value = self.TEST_CASES[case]
    286         self.setup_case(self.POLICY_NAME, case_value, self.SUPPORTING_POLICIES)
    287         self._test_idle_action(case_value)
    288