blob: 6f008dea8fa6a011ee50d692f5ba5469bc70d754 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/power/power_prefs.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "ash/public/cpp/ash_pref_names.h"
#include "ash/session/session_controller.h"
#include "ash/session/test_session_controller_client.h"
#include "ash/shell.h"
#include "ash/shell_test_api.h"
#include "ash/test/ash_test_base.h"
#include "base/macros.h"
#include "base/test/simple_test_tick_clock.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_power_manager_client.h"
#include "chromeos/dbus/power_manager/idle.pb.h"
#include "chromeos/dbus/power_policy_controller.h"
#include "components/prefs/pref_service.h"
using session_manager::SessionState;
namespace ash {
namespace {
// Screen lock state that determines which delays are used by
// GetExpectedPowerPolicyForPrefs().
enum class ScreenLockState {
LOCKED,
UNLOCKED,
};
PrefService* GetSigninScreenPrefService() {
return Shell::Get()->session_controller()->GetSigninScreenPrefService();
}
// Returns prefs for the user identified by |user_email|, or null if the user's
// prefs are unavailable (e.g. because they don't exist).
PrefService* GetUserPrefService(const std::string& user_email) {
return Shell::Get()->session_controller()->GetUserPrefServiceForUser(
AccountId::FromUserEmail(user_email));
}
std::string GetExpectedPowerPolicyForPrefs(PrefService* prefs,
ScreenLockState screen_lock_state) {
const bool is_smart_dim_enabled =
prefs->GetBoolean(prefs::kPowerSmartDimEnabled);
power_manager::PowerManagementPolicy expected_policy;
expected_policy.mutable_ac_delays()->set_screen_dim_ms(
prefs->GetInteger(screen_lock_state == ScreenLockState::LOCKED
? prefs::kPowerLockScreenDimDelayMs
: prefs::kPowerAcScreenDimDelayMs));
expected_policy.mutable_ac_delays()->set_screen_off_ms(
prefs->GetInteger(screen_lock_state == ScreenLockState::LOCKED
? prefs::kPowerLockScreenOffDelayMs
: prefs::kPowerAcScreenOffDelayMs));
expected_policy.mutable_ac_delays()->set_screen_lock_ms(
prefs->GetInteger(prefs::kPowerAcScreenLockDelayMs));
expected_policy.mutable_ac_delays()->set_idle_warning_ms(
prefs->GetInteger(prefs::kPowerAcIdleWarningDelayMs));
expected_policy.mutable_ac_delays()->set_idle_ms(
prefs->GetInteger(prefs::kPowerAcIdleDelayMs));
expected_policy.mutable_battery_delays()->set_screen_dim_ms(
prefs->GetInteger(screen_lock_state == ScreenLockState::LOCKED
? prefs::kPowerLockScreenDimDelayMs
: prefs::kPowerBatteryScreenDimDelayMs));
expected_policy.mutable_battery_delays()->set_screen_off_ms(
prefs->GetInteger(screen_lock_state == ScreenLockState::LOCKED
? prefs::kPowerLockScreenOffDelayMs
: prefs::kPowerBatteryScreenOffDelayMs));
expected_policy.mutable_battery_delays()->set_screen_lock_ms(
prefs->GetInteger(prefs::kPowerBatteryScreenLockDelayMs));
expected_policy.mutable_battery_delays()->set_idle_warning_ms(
prefs->GetInteger(prefs::kPowerBatteryIdleWarningDelayMs));
expected_policy.mutable_battery_delays()->set_idle_ms(
prefs->GetInteger(prefs::kPowerBatteryIdleDelayMs));
expected_policy.set_ac_idle_action(
static_cast<power_manager::PowerManagementPolicy_Action>(
prefs->GetInteger(prefs::kPowerAcIdleAction)));
expected_policy.set_battery_idle_action(
static_cast<power_manager::PowerManagementPolicy_Action>(
prefs->GetInteger(prefs::kPowerBatteryIdleAction)));
expected_policy.set_lid_closed_action(
static_cast<power_manager::PowerManagementPolicy_Action>(
prefs->GetInteger(prefs::kPowerLidClosedAction)));
expected_policy.set_use_audio_activity(
prefs->GetBoolean(prefs::kPowerUseAudioActivity));
expected_policy.set_use_video_activity(
prefs->GetBoolean(prefs::kPowerUseVideoActivity));
if (is_smart_dim_enabled) {
// Screen-dim scaling factors are disabled by PowerPolicyController when
// smart-dimming is enabled.
expected_policy.set_presentation_screen_dim_delay_factor(1.0);
expected_policy.set_user_activity_screen_dim_delay_factor(1.0);
} else {
expected_policy.set_presentation_screen_dim_delay_factor(
prefs->GetDouble(prefs::kPowerPresentationScreenDimDelayFactor));
expected_policy.set_user_activity_screen_dim_delay_factor(
prefs->GetDouble(prefs::kPowerUserActivityScreenDimDelayFactor));
}
expected_policy.set_wait_for_initial_user_activity(
prefs->GetBoolean(prefs::kPowerWaitForInitialUserActivity));
expected_policy.set_force_nonzero_brightness_for_user_activity(
prefs->GetBoolean(prefs::kPowerForceNonzeroBrightnessForUserActivity));
expected_policy.set_reason("Prefs");
return chromeos::PowerPolicyController::GetPolicyDebugString(expected_policy);
}
bool GetExpectedAllowScreenWakeLocksForPrefs(PrefService* prefs) {
return prefs->GetBoolean(prefs::kPowerAllowScreenWakeLocks);
}
} // namespace
class PowerPrefsTest : public NoSessionAshTestBase {
protected:
PowerPrefsTest() = default;
~PowerPrefsTest() override = default;
// NoSessionAshTestBase:
void SetUp() override {
fake_power_manager_client_ = new chromeos::FakePowerManagerClient;
chromeos::DBusThreadManager::GetSetterForTesting()->SetPowerManagerClient(
base::WrapUnique(fake_power_manager_client_));
NoSessionAshTestBase::SetUp();
power_policy_controller_ = chromeos::PowerPolicyController::Get();
power_prefs_ = ShellTestApi(Shell::Get()).power_prefs();
// Advance the clock an arbitrary amount of time so it won't report zero.
tick_clock_.Advance(base::TimeDelta::FromSeconds(1));
power_prefs_->set_tick_clock_for_test(&tick_clock_);
// Get to Login screen.
GetSessionControllerClient()->SetSessionState(SessionState::LOGIN_PRIMARY);
}
std::string GetCurrentPowerPolicy() const {
return chromeos::PowerPolicyController::GetPolicyDebugString(
fake_power_manager_client_->policy());
}
bool GetCurrentAllowScreenWakeLocks() const {
return power_policy_controller_->honor_screen_wake_locks_for_test();
}
std::vector<power_manager::PowerManagementPolicy_Action>
GetCurrentPowerPolicyActions() const {
return {fake_power_manager_client_->policy().ac_idle_action(),
fake_power_manager_client_->policy().battery_idle_action(),
fake_power_manager_client_->policy().lid_closed_action()};
}
void SetLockedState(ScreenLockState lock_state) {
GetSessionControllerClient()->SetSessionState(
lock_state == ScreenLockState::LOCKED ? SessionState::LOCKED
: SessionState::ACTIVE);
}
void NotifyScreenIdleOffChanged(bool off) {
power_manager::ScreenIdleState proto;
proto.set_off(off);
fake_power_manager_client_->SendScreenIdleStateChanged(proto);
}
// Owned by chromeos::DBusThreadManager.
chromeos::FakePowerManagerClient* fake_power_manager_client_;
chromeos::PowerPolicyController* power_policy_controller_ =
nullptr; // Not owned.
PowerPrefs* power_prefs_ = nullptr; // Not owned.
base::SimpleTestTickClock tick_clock_;
private:
DISALLOW_COPY_AND_ASSIGN(PowerPrefsTest);
};
TEST_F(PowerPrefsTest, LoginScreen) {
PrefService* prefs =
Shell::Get()->session_controller()->GetActivePrefService();
EXPECT_EQ(GetSigninScreenPrefService(), prefs);
EXPECT_EQ(GetExpectedPowerPolicyForPrefs(prefs, ScreenLockState::UNLOCKED),
GetCurrentPowerPolicy());
EXPECT_EQ(GetExpectedAllowScreenWakeLocksForPrefs(prefs),
GetCurrentAllowScreenWakeLocks());
// Lock the screen and check that the expected delays are used.
SetLockedState(ScreenLockState::LOCKED);
EXPECT_EQ(GetExpectedPowerPolicyForPrefs(prefs, ScreenLockState::LOCKED),
GetCurrentPowerPolicy());
// Unlock the screen.
SetLockedState(ScreenLockState::UNLOCKED);
EXPECT_EQ(GetExpectedPowerPolicyForPrefs(prefs, ScreenLockState::UNLOCKED),
GetCurrentPowerPolicy());
}
TEST_F(PowerPrefsTest, UserSession) {
const char kUserEmail[] = "user@example.net";
SimulateUserLogin(kUserEmail);
PrefService* prefs = GetUserPrefService(kUserEmail);
ASSERT_TRUE(prefs);
EXPECT_EQ(GetExpectedPowerPolicyForPrefs(prefs, ScreenLockState::UNLOCKED),
GetCurrentPowerPolicy());
EXPECT_EQ(GetExpectedAllowScreenWakeLocksForPrefs(prefs),
GetCurrentAllowScreenWakeLocks());
}
TEST_F(PowerPrefsTest, PrimaryUserPrefs) {
// Add a user with restrictive prefs.
const char kFirstUserEmail[] = "user1@example.net";
SimulateUserLogin(kFirstUserEmail);
PrefService* first_prefs = GetUserPrefService(kFirstUserEmail);
ASSERT_TRUE(first_prefs);
first_prefs->SetBoolean(prefs::kPowerAllowScreenWakeLocks, false);
first_prefs->SetInteger(prefs::kPowerLidClosedAction,
chromeos::PowerPolicyController::ACTION_SHUT_DOWN);
// Add a second user with lenient prefs.
const char kSecondUserEmail[] = "user2@example.net";
SimulateUserLogin(kSecondUserEmail);
PrefService* second_prefs = GetUserPrefService(kSecondUserEmail);
ASSERT_TRUE(second_prefs);
second_prefs->SetBoolean(prefs::kPowerAllowScreenWakeLocks, true);
second_prefs->SetInteger(prefs::kPowerLidClosedAction,
chromeos::PowerPolicyController::ACTION_DO_NOTHING);
// Even though the second user is active, the first (primary) user's prefs
// should still be used.
ASSERT_EQ(second_prefs,
Shell::Get()->session_controller()->GetActivePrefService());
EXPECT_EQ(
GetExpectedPowerPolicyForPrefs(first_prefs, ScreenLockState::UNLOCKED),
GetCurrentPowerPolicy());
}
TEST_F(PowerPrefsTest, AvoidLockDelaysAfterInactivity) {
const char kUserEmail[] = "user@example.net";
SimulateUserLogin(kUserEmail);
PrefService* prefs = GetUserPrefService(kUserEmail);
ASSERT_TRUE(prefs);
EXPECT_EQ(GetExpectedPowerPolicyForPrefs(prefs, ScreenLockState::UNLOCKED),
GetCurrentPowerPolicy());
// If the screen was already off due to inactivity when it was locked, we
// should continue using the unlocked delays.
NotifyScreenIdleOffChanged(true);
tick_clock_.Advance(base::TimeDelta::FromSeconds(5));
SetLockedState(ScreenLockState::LOCKED);
EXPECT_EQ(GetExpectedPowerPolicyForPrefs(prefs, ScreenLockState::UNLOCKED),
GetCurrentPowerPolicy());
// If the screen turns on while still locked, we should switch to the locked
// delays.
tick_clock_.Advance(base::TimeDelta::FromSeconds(5));
NotifyScreenIdleOffChanged(false);
EXPECT_EQ(GetExpectedPowerPolicyForPrefs(prefs, ScreenLockState::LOCKED),
GetCurrentPowerPolicy());
tick_clock_.Advance(base::TimeDelta::FromSeconds(5));
SetLockedState(ScreenLockState::UNLOCKED);
EXPECT_EQ(GetExpectedPowerPolicyForPrefs(prefs, ScreenLockState::UNLOCKED),
GetCurrentPowerPolicy());
}
TEST_F(PowerPrefsTest, DisabledLockScreen) {
const char kUserEmail[] = "user@example.net";
SimulateUserLogin(kUserEmail);
PrefService* prefs = GetUserPrefService(kUserEmail);
ASSERT_TRUE(prefs);
// Verify that the power policy actions are set to default values initially.
EXPECT_EQ(std::vector<power_manager::PowerManagementPolicy_Action>(
3, power_manager::PowerManagementPolicy_Action_SUSPEND),
GetCurrentPowerPolicyActions());
// The automatic screen locking is enabled, but, as the lock screen is
// allowed, the power policy actions still have the default values.
prefs->SetBoolean(prefs::kEnableAutoScreenLock, true);
EXPECT_EQ(std::vector<power_manager::PowerManagementPolicy_Action>(
3, power_manager::PowerManagementPolicy_Action_SUSPEND),
GetCurrentPowerPolicyActions());
// The lock screen is disabled, but, as automatic screen locking is not
// enabled, the power policy actions still have the default values.
prefs->ClearPref(prefs::kEnableAutoScreenLock);
prefs->SetBoolean(prefs::kAllowScreenLock, false);
EXPECT_EQ(std::vector<power_manager::PowerManagementPolicy_Action>(
3, power_manager::PowerManagementPolicy_Action_SUSPEND),
GetCurrentPowerPolicyActions());
// The automatic screen locking is enabled and the lock screen is disabled, so
// the power policy actions are set now to stop the user session.
prefs->SetBoolean(prefs::kEnableAutoScreenLock, true);
EXPECT_EQ(std::vector<power_manager::PowerManagementPolicy_Action>(
3, power_manager::PowerManagementPolicy_Action_STOP_SESSION),
GetCurrentPowerPolicyActions());
}
TEST_F(PowerPrefsTest, SmartDimEnabled) {
PrefService* prefs =
Shell::Get()->session_controller()->GetActivePrefService();
EXPECT_TRUE(prefs->GetBoolean(prefs::kPowerSmartDimEnabled));
}
} // namespace ash