289 lines
12 KiB
Python
289 lines
12 KiB
Python
# Copyright 2016 The Chromium OS Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
import logging
|
|
import time
|
|
|
|
from autotest_lib.client.bin import utils
|
|
from autotest_lib.client.common_lib import error
|
|
from autotest_lib.client.cros import cryptohome
|
|
from autotest_lib.client.cros.enterprise import enterprise_policy_base
|
|
from autotest_lib.client.cros.graphics import graphics_utils
|
|
from autotest_lib.client.cros.power import power_status, power_utils
|
|
|
|
|
|
class policy_PowerManagementIdleSettings(
|
|
enterprise_policy_base.EnterprisePolicyTest):
|
|
"""
|
|
Test effect of PowerManagementIdleSettings policy on Chrome OS behavior.
|
|
|
|
This test verifies the effect of the PowerManagementIdleSettings user
|
|
policy on specific Chrome OS client behaviors. It tests two valid values
|
|
for the IdleAction property: 'DoNothing' and Not set, with three test
|
|
cases: DoNothing_Continue, NotSet_Sleep, and Logout_EndSession. It also
|
|
verifies that the screen dims after ScreenDim delay, and then turns off
|
|
after ScreenOff delay (both delays in milliseconds).
|
|
|
|
Note: Valid IdleAction values are 'DoNothing', 'Suspend', 'Logout', and
|
|
'Shutdown'. This test exercises only the DoNothing and Logout actions.
|
|
Suspend is tested by enterprise_PowerManager.py. Shutdown can be tested
|
|
only using a Server-side AutoTest.
|
|
|
|
Chrome reports user activity to the power manager at most every 5 seconds.
|
|
To accomodate potential delays, the test pads the idle-action delay with
|
|
a 5 second activity report interval.
|
|
|
|
Several supporting policies are necessary to facillitate testing, or to
|
|
make testing more reliable. These policies are listed below with a brief
|
|
description of the set value.
|
|
- WaitForInitialUserActivity=False so idle timer starts immediately after
|
|
session starts.
|
|
- UserActivityScreenDimDelayScale=100 to prevent increase delays when
|
|
user activity occurs after screen dim.
|
|
- ChromeOsLockOnIdleSuspend=False to prevent screen lock upon suspend.
|
|
- AllowScreenLock=False to prevent manual screen lock. Will not affect
|
|
this test, but is the safest setting.
|
|
- AllowScreenWakeLocks=False to ignore 'keep awake' requests. Since wake
|
|
locks are not requested during this test, ignoring them is unnecessary.
|
|
But for safety we ignore them when testing suspend.
|
|
- LidCloseAction=3 to invoke no action upon (accidental) lid closure.
|
|
- ResoreOnStartup* polices are set to display the settings and policy
|
|
pages. This is useful when debugging failures.
|
|
|
|
"""
|
|
version = 1
|
|
|
|
def initialize(self, **kwargs):
|
|
"""Set up local variables and ensure device is on AC power."""
|
|
self._initialize_test_constants()
|
|
self._power_status = power_status.get_status()
|
|
if not self._power_status.on_ac():
|
|
raise error.TestNAError('Test must be run with DUT on AC power.')
|
|
self._backlight = power_utils.Backlight()
|
|
super(policy_PowerManagementIdleSettings, self).initialize(**kwargs)
|
|
|
|
def _initialize_test_constants(self):
|
|
self.POLICY_NAME = 'PowerManagementIdleSettings'
|
|
self.SCREEN_SETTLE_TIME = 0.3
|
|
self.SCREEN_DIM_DELAY = 4
|
|
self.IDLE_WARNING_DELAY = 6
|
|
self.SCREEN_OFF_DELAY = 8
|
|
self.IDLE_ACTION_DELAY = 10
|
|
self.ACTIVITY_REPORT_INTERVAL = 5
|
|
self.IDLE_ACTION_NOTSET = {
|
|
'AC': {
|
|
'Delays': {
|
|
'ScreenDim': (self.SCREEN_DIM_DELAY * 1000),
|
|
'IdleWarning': (self.IDLE_WARNING_DELAY * 1000),
|
|
'ScreenOff': (self.SCREEN_OFF_DELAY * 1000),
|
|
'Idle': (self.IDLE_ACTION_DELAY * 1000)
|
|
}
|
|
}
|
|
}
|
|
self.IDLE_ACTION_DONOTHING = {
|
|
'AC': {
|
|
'Delays': {
|
|
'ScreenDim': (self.SCREEN_DIM_DELAY * 1000),
|
|
'IdleWarning': (self.IDLE_WARNING_DELAY * 1000),
|
|
'ScreenOff': (self.SCREEN_OFF_DELAY * 1000),
|
|
'Idle': (self.IDLE_ACTION_DELAY * 1000)
|
|
},
|
|
'IdleAction': 'DoNothing'
|
|
}
|
|
}
|
|
self.IDLE_ACTION_LOGOUT = {
|
|
'AC': {
|
|
'Delays': {
|
|
'ScreenDim': (self.SCREEN_DIM_DELAY * 1000),
|
|
'IdleWarning': (self.IDLE_WARNING_DELAY * 1000),
|
|
'ScreenOff': (self.SCREEN_OFF_DELAY * 1000),
|
|
'Idle': (self.IDLE_ACTION_DELAY * 1000)
|
|
},
|
|
'IdleAction': 'Logout'
|
|
}
|
|
}
|
|
self.TEST_CASES = {
|
|
'NotSet_Sleep': self.IDLE_ACTION_NOTSET,
|
|
'DoNothing_Continue': self.IDLE_ACTION_DONOTHING,
|
|
'Logout_EndSession': self.IDLE_ACTION_LOGOUT
|
|
}
|
|
self.STARTUP_URLS = ['chrome://settings', 'chrome://policy']
|
|
self.SUPPORTING_POLICIES = {
|
|
'WaitForInitialUserActivity': True,
|
|
'UserActivityScreenDimDelayScale': 100,
|
|
'ChromeOsLockOnIdleSuspend': False,
|
|
'AllowScreenLock': False,
|
|
'AllowScreenWakeLocks': False,
|
|
'LidCloseAction': 3,
|
|
'RestoreOnStartup': 4,
|
|
'RestoreOnStartupURLs': self.STARTUP_URLS
|
|
}
|
|
|
|
|
|
def elapsed_time(self, start_time):
|
|
"""Get time elapsed since |start_time|.
|
|
|
|
@param start_time: clock time from which elapsed time is measured.
|
|
@returns time elapsed since the start time.
|
|
"""
|
|
return time.time() - start_time
|
|
|
|
|
|
def _simulate_user_activity(self):
|
|
"""Inject user activity via D-bus to restart idle timer.
|
|
|
|
Note that if the screen has gone black, these use activities will
|
|
wake up the display again. However, they will not wake up a screen
|
|
that has merely been dimmed.
|
|
|
|
"""
|
|
graphics_utils.click_mouse() # Note: Duration is 0.4 seconds.
|
|
graphics_utils.press_keys(['KEY_LEFTCTRL'])
|
|
|
|
|
|
def _wait_for_login_status(self, attribute, value, timeout):
|
|
"""Return when attribute has value, or its current value on timeout.
|
|
|
|
Login_status is a dictionary of attributes that describe the login
|
|
status of the current session. It contains values for the following
|
|
attributes: isLoggedIn, isRegularUser, isOwner, isKiosk, isGuest,
|
|
isScreenLocked, userImage, email, and displayEmail.
|
|
|
|
@param attribute: String attribute key to be measured.
|
|
@param value: Boolean attribute value expected.
|
|
@param timeout: integer seconds till timeout.
|
|
@returns dict of login status.
|
|
|
|
"""
|
|
attribute_value = utils.wait_for_value(
|
|
lambda: self.cr.login_status[attribute],
|
|
expected_value=value,
|
|
timeout_sec=timeout)
|
|
return attribute_value
|
|
|
|
|
|
def _poll_until_user_is_logged_out(self, timeout):
|
|
"""Return True when user logs out, False when user remains logged in.
|
|
|
|
@returns boolean of user logged out status.
|
|
|
|
"""
|
|
my_result = utils.poll_for_condition(
|
|
lambda: not cryptohome.is_vault_mounted(user=self.username,
|
|
allow_fail=True),
|
|
exception=None,
|
|
timeout=timeout,
|
|
sleep_interval=2,
|
|
desc='Polling for user to be logged out.')
|
|
return my_result
|
|
|
|
|
|
def _set_brightness_to_maximum(self):
|
|
"""Set screen to maximum brightness."""
|
|
max_level = self._backlight.get_max_level()
|
|
self._backlight.set_level(max_level)
|
|
|
|
|
|
def _wait_for_brightness_change(self, timeout):
|
|
"""Return screen brightness on update, or current value on timeout.
|
|
|
|
@returns float of screen brightness percentage.
|
|
|
|
"""
|
|
initial_brightness = self._backlight.get_percent()
|
|
current_brightness = utils.wait_for_value_changed(
|
|
lambda: self._backlight.get_percent(),
|
|
old_value=initial_brightness,
|
|
timeout_sec=timeout)
|
|
if current_brightness != initial_brightness:
|
|
time.sleep(self.SCREEN_SETTLE_TIME)
|
|
current_brightness = self._backlight.get_percent()
|
|
return current_brightness
|
|
|
|
|
|
def _test_idle_action(self, policy_value):
|
|
"""
|
|
Verify CrOS enforces PowerManagementIdleSettings policy value.
|
|
|
|
@param policy_value: policy value for this case.
|
|
@raises: TestFail if idle actions are not performed after their
|
|
specified delays.
|
|
|
|
"""
|
|
logging.info('Running _test_idle_action(%s)', policy_value)
|
|
|
|
# Wait until UI settles down with user logged in.
|
|
user_is_logged_in = self._wait_for_login_status(
|
|
'isLoggedIn', True, self.IDLE_ACTION_DELAY)
|
|
if not user_is_logged_in:
|
|
raise error.TestFail('User must be logged in at start.')
|
|
|
|
# Set screen to maxiumum brightness.
|
|
self._set_brightness_to_maximum()
|
|
max_brightness = self._backlight.get_percent()
|
|
logging.info('Brightness maximized to: %.2f', max_brightness)
|
|
|
|
# Induce user activity to start idle timer.
|
|
self._simulate_user_activity()
|
|
start_time = time.time()
|
|
|
|
# Verify screen is dimmed after expected delay.
|
|
seconds_to_dim = (
|
|
self.SCREEN_DIM_DELAY - self.elapsed_time(start_time))
|
|
dim_brightness = self._wait_for_brightness_change(seconds_to_dim)
|
|
dim_elapsed_time = self.elapsed_time(start_time)
|
|
logging.info(' Brightness dimmed to: %.2f, ', dim_brightness)
|
|
logging.info(' after %s seconds.', dim_elapsed_time)
|
|
if not (dim_brightness < max_brightness and dim_brightness > 0.0):
|
|
raise error.TestFail('Screen did not dim on delay.')
|
|
|
|
# Verify screen is turned off after expected delay.
|
|
seconds_to_off = (
|
|
self.SCREEN_OFF_DELAY - self.elapsed_time(start_time))
|
|
off_brightness = self._wait_for_brightness_change(seconds_to_off)
|
|
off_elapsed_time = self.elapsed_time(start_time)
|
|
logging.info(' Brightness off to: %.2f, ', off_brightness)
|
|
logging.info(' after %s seconds.', off_elapsed_time)
|
|
if not off_brightness < dim_brightness:
|
|
raise error.TestFail('Screen did not turn off on delay.')
|
|
|
|
# Verify user is still logged in before IdleAction.
|
|
user_is_logged_in = self.cr.login_status['isLoggedIn']
|
|
if not user_is_logged_in:
|
|
raise error.TestFail('User must be logged in before idle action.')
|
|
|
|
# Get user logged in state after IdleAction.
|
|
seconds_to_action = (
|
|
self.IDLE_ACTION_DELAY + self.ACTIVITY_REPORT_INTERVAL
|
|
- self.elapsed_time(start_time))
|
|
try:
|
|
user_is_logged_in = not self._poll_until_user_is_logged_out(
|
|
seconds_to_action)
|
|
except utils.TimeoutError:
|
|
pass
|
|
action_elapsed_time = self.elapsed_time(start_time)
|
|
logging.info(' User logged out: %r, ', not user_is_logged_in)
|
|
logging.info(' after %s seconds.', action_elapsed_time)
|
|
|
|
# Verify user status against expected result, based on case.
|
|
if self.case == 'NotSet_Sleep' or self.case == 'DoNothing_Continue':
|
|
if not user_is_logged_in:
|
|
raise error.TestFail('User should be logged in.')
|
|
elif self.case == 'Logout_EndSession':
|
|
if user_is_logged_in:
|
|
raise error.TestFail('User should be logged out.')
|
|
|
|
|
|
def run_once(self, case):
|
|
"""
|
|
Setup and run the test configured for the specified test case.
|
|
|
|
@param case: Name of the test case to run.
|
|
|
|
"""
|
|
case_value = self.TEST_CASES[case]
|
|
self.SUPPORTING_POLICIES[self.POLICY_NAME] = case_value
|
|
self.setup_case(user_policies=self.SUPPORTING_POLICIES)
|
|
self._test_idle_action(case_value)
|