blob: c776da211bc8b573b105cf22e17362b141f2909b [file] [log] [blame]
// Copyright 2014 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.
#include "power_manager/powerd/policy/wakeup_controller.h"
#include <base/strings/stringprintf.h>
#include "gtest/gtest.h"
#include "power_manager/common/fake_prefs.h"
#include "power_manager/powerd/system/acpi_wakeup_helper_stub.h"
#include "power_manager/powerd/system/udev_stub.h"
namespace power_manager {
namespace policy {
namespace {
// An artificial syspath for tests.
const char kSyspath0[] = "/sys/devices/test/0";
};
class WakeupControllerTest : public ::testing::Test {
public:
WakeupControllerTest()
: default_allow_docked_mode_(true),
initial_lid_state_(LID_OPEN),
initial_display_mode_(DISPLAY_NORMAL) {
}
protected:
std::string GetSysattr(const std::string& syspath,
const std::string& sysattr) {
std::string value;
if (!udev_.GetSysattr(syspath, sysattr, &value))
return "(error)";
return value;
}
bool GetAcpiWakeup(const std::string& acpi_name) {
bool value = false;
if (!acpi_wakeup_helper_.GetWakeupEnabled(acpi_name, &value)) {
ADD_FAILURE() << "Expected ACPI wakeup for " << acpi_name
<< " to be defined";
}
return value;
}
void AddDeviceWithTags(const std::string& syspath,
const std::string& tags) {
udev_.SetSysattr(syspath, WakeupController::kPowerWakeup,
WakeupController::kDisabled);
udev_.TaggedDeviceChanged(syspath, tags);
}
void InitWakeupController() {
prefs_.SetInt64(kAllowDockedModePref, default_allow_docked_mode_);
wakeup_controller_.Init(&udev_, &acpi_wakeup_helper_,
initial_lid_state_, initial_display_mode_,
&prefs_);
}
system::UdevStub udev_;
system::AcpiWakeupHelperStub acpi_wakeup_helper_;
FakePrefs prefs_;
bool default_allow_docked_mode_;
LidState initial_lid_state_;
DisplayMode initial_display_mode_;
WakeupController wakeup_controller_;
};
TEST_F(WakeupControllerTest, ConfigureWakeupOnInit) {
AddDeviceWithTags(kSyspath0, WakeupController::kTagWakeup);
EXPECT_EQ(WakeupController::kDisabled,
GetSysattr(kSyspath0, WakeupController::kPowerWakeup));
InitWakeupController();
EXPECT_EQ(WakeupController::kEnabled,
GetSysattr(kSyspath0, WakeupController::kPowerWakeup));
EXPECT_TRUE(GetAcpiWakeup(WakeupController::kTPAD));
EXPECT_FALSE(GetAcpiWakeup(WakeupController::kTSCR));
}
TEST_F(WakeupControllerTest, ConfigureWakeupOnAdd) {
InitWakeupController();
// The device starts out with wakeup disabled, but should get configured by
// WakeupController right away.
AddDeviceWithTags(kSyspath0, WakeupController::kTagWakeup);
EXPECT_EQ(WakeupController::kEnabled,
GetSysattr(kSyspath0, WakeupController::kPowerWakeup));
}
TEST_F(WakeupControllerTest, DisableWakeupWhenClosed) {
AddDeviceWithTags(
kSyspath0,
base::StringPrintf("%s %s %s",
WakeupController::kTagWakeup,
WakeupController::kTagWakeupOnlyWhenUsable,
WakeupController::kTagUsableWhenLaptop));
InitWakeupController();
// In laptop mode, wakeup should be enabled.
EXPECT_EQ(WakeupController::kEnabled,
GetSysattr(kSyspath0, WakeupController::kPowerWakeup));
EXPECT_TRUE(GetAcpiWakeup("TPAD"));
// When the lid is closed, wakeup should be disabled.
wakeup_controller_.SetLidState(LID_CLOSED);
EXPECT_EQ(WakeupController::kDisabled,
GetSysattr(kSyspath0, WakeupController::kPowerWakeup));
EXPECT_FALSE(GetAcpiWakeup(WakeupController::kTPAD));
}
TEST_F(WakeupControllerTest, PermanentlyDisableWakeup) {
AddDeviceWithTags(kSyspath0,
base::StringPrintf("%s %s",
WakeupController::kTagWakeup,
WakeupController::kTagWakeupDisabled));
// Simulate a device that has wakeup enabled initially.
udev_.SetSysattr(kSyspath0, WakeupController::kPowerWakeup,
WakeupController::kEnabled);
InitWakeupController();
EXPECT_EQ(WakeupController::kDisabled,
GetSysattr(kSyspath0, WakeupController::kPowerWakeup));
}
TEST_F(WakeupControllerTest, ConfigureInhibit) {
AddDeviceWithTags(
kSyspath0,
base::StringPrintf("%s %s",
WakeupController::kTagInhibit,
WakeupController::kTagUsableWhenLaptop));
InitWakeupController();
// In laptop mode, inhibit should be off.
EXPECT_EQ("0", GetSysattr(kSyspath0, WakeupController::kInhibited));
// When the lid is closed, inhibit should be on.
wakeup_controller_.SetLidState(LID_CLOSED);
EXPECT_EQ("1", GetSysattr(kSyspath0, WakeupController::kInhibited));
// When the lid is open, inhibit should be off again.
wakeup_controller_.SetLidState(LID_OPEN);
EXPECT_EQ("0", GetSysattr(kSyspath0, WakeupController::kInhibited));
}
TEST_F(WakeupControllerTest, InhibitDocking) {
AddDeviceWithTags(
kSyspath0,
base::StringPrintf("%s %s %s",
WakeupController::kTagInhibit,
WakeupController::kTagUsableWhenLaptop,
WakeupController::kTagUsableWhenDocked));
initial_display_mode_ = DISPLAY_PRESENTATION;
InitWakeupController();
// In laptop mode, inhibit should be off.
EXPECT_EQ("0", GetSysattr(kSyspath0, WakeupController::kInhibited));
// When the lid is closed, inhibit should remain off.
wakeup_controller_.SetLidState(LID_CLOSED);
EXPECT_EQ("0", GetSysattr(kSyspath0, WakeupController::kInhibited));
// When the lid is open, inhibit should still be off.
wakeup_controller_.SetLidState(LID_OPEN);
EXPECT_EQ("0", GetSysattr(kSyspath0, WakeupController::kInhibited));
}
TEST_F(WakeupControllerTest, InhibitDockingDisallowed) {
AddDeviceWithTags(
kSyspath0,
base::StringPrintf("%s %s %s",
WakeupController::kTagInhibit,
WakeupController::kTagUsableWhenLaptop,
WakeupController::kTagUsableWhenDocked));
default_allow_docked_mode_ = false;
initial_display_mode_ = DISPLAY_PRESENTATION;
InitWakeupController();
// In laptop mode, inhibit should be off.
EXPECT_EQ("0", GetSysattr(kSyspath0, WakeupController::kInhibited));
// When the lid is closed, inhibit should be on since docking is disallowed,
// even though the device supports it.
wakeup_controller_.SetLidState(LID_CLOSED);
EXPECT_EQ("1", GetSysattr(kSyspath0, WakeupController::kInhibited));
// When the lid is open, inhibit should be off again.
wakeup_controller_.SetLidState(LID_OPEN);
EXPECT_EQ("0", GetSysattr(kSyspath0, WakeupController::kInhibited));
}
TEST_F(WakeupControllerTest, SetDisplayModeExternalInput) {
AddDeviceWithTags(
kSyspath0,
base::StringPrintf("%s %s %s",
WakeupController::kTagInhibit,
WakeupController::kTagUsableWhenLaptop,
WakeupController::kTagUsableWhenDocked));
initial_lid_state_ = LID_CLOSED;
InitWakeupController();
// When the lid is closed with no external display, external input devices
// should be inhibited.
EXPECT_EQ("1", GetSysattr(kSyspath0, WakeupController::kInhibited));
// When an external display is attached, device should be un-inhibited.
wakeup_controller_.SetDisplayMode(DISPLAY_PRESENTATION);
EXPECT_EQ("0", GetSysattr(kSyspath0, WakeupController::kInhibited));
// When external display goes away, input should be inhibited again.
wakeup_controller_.SetDisplayMode(DISPLAY_NORMAL);
EXPECT_EQ("1", GetSysattr(kSyspath0, WakeupController::kInhibited));
}
TEST_F(WakeupControllerTest, SetDisplayModeInternalInput) {
AddDeviceWithTags(
kSyspath0,
base::StringPrintf("%s %s",
WakeupController::kTagInhibit,
WakeupController::kTagUsableWhenLaptop));
InitWakeupController();
// Devices that are only usable when in laptop mode should not be inhibited
// while the lid is open.
EXPECT_EQ("0", GetSysattr(kSyspath0, WakeupController::kInhibited));
// When an external display is attached, device should remain uninhibited.
wakeup_controller_.SetDisplayMode(DISPLAY_PRESENTATION);
EXPECT_EQ("0", GetSysattr(kSyspath0, WakeupController::kInhibited));
// When the lid is closed, internal input should be inhibited regardless
// of display mode.
wakeup_controller_.SetLidState(LID_CLOSED);
EXPECT_EQ("1", GetSysattr(kSyspath0, WakeupController::kInhibited));
wakeup_controller_.SetDisplayMode(DISPLAY_NORMAL);
EXPECT_EQ("1", GetSysattr(kSyspath0, WakeupController::kInhibited));
}
} // namespace policy
} // namespace power_manager