#include "chromeos/dbus/power/power_manager_client.h"
#include <map>
#include <memory>
#include <string>
#include <utility>
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/test/power_monitor_test.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "base/unguessable_token.h"
#include "chromeos/dbus/power_manager/backlight.pb.h"
#include "chromeos/dbus/power_manager/suspend.pb.h"
#include "chromeos/dbus/power_manager/thermal.pb.h"
#include "dbus/mock_bus.h"
#include "dbus/mock_object_proxy.h"
#include "dbus/object_path.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/power_manager/dbus-constants.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
using ::testing::_;
using ::testing::Return;
using ::testing::SaveArg;
namespace chromeos {
namespace {
const char* kInterface = power_manager::kPowerManagerInterface;
const char* kSuspendImminent = power_manager::kSuspendImminentSignal;
const char* kDarkSuspendImminent = power_manager::kDarkSuspendImminentSignal;
const char* kHandleSuspendReadiness =
power_manager::kHandleSuspendReadinessMethod;
const char* kHandleDarkSuspendReadiness =
power_manager::kHandleDarkSuspendReadinessMethod;
MATCHER_P(HasMember, name, "") {
if (arg->GetMember() != name) {
*result_listener << "has member " << arg->GetMember();
return false;
}
return true;
}
MATCHER_P3(IsSuspendReadiness, method_name, suspend_id, delay_id, "") {
if (arg->GetMember() != method_name) {
*result_listener << "has member " << arg->GetMember();
return false;
}
power_manager::SuspendReadinessInfo proto;
if (!dbus::MessageReader(arg).PopArrayOfBytesAsProto(&proto)) {
*result_listener << "does not contain SuspendReadinessInfo protobuf";
return false;
}
if (proto.suspend_id() != suspend_id) {
*result_listener << "suspend ID is " << proto.suspend_id();
return false;
}
if (proto.delay_id() != delay_id) {
*result_listener << "delay ID is " << proto.delay_id();
return false;
}
return true;
}
MATCHER_P4(IsRequestSuspend, method_name, count, duration, flavor, "") {
if (arg->GetMember() != method_name) {
*result_listener << "has member " << arg->GetMember();
return false;
}
dbus::MessageReader reader(arg);
uint64_t read_count;
if (!reader.PopUint64(&read_count)) {
*result_listener << "missing value 1 (count)";
return false;
}
if (read_count != count) {
*result_listener << "expected count = " << count << ", got " << read_count;
return false;
}
int32_t read_duration;
if (!reader.PopInt32(&read_duration)) {
*result_listener << "missing value 2 (duration)";
return false;
}
if (read_duration != duration) {
*result_listener << "expected duration = " << duration << ", got "
<< read_duration;
return false;
}
uint32_t read_flavor;
if (!reader.PopUint32(&read_flavor)) {
*result_listener << "missing value 1 (count)";
return false;
}
if (read_flavor != flavor) {
*result_listener << "expected flavor = " << flavor << ", got "
<< read_flavor;
return false;
}
return true;
}
MATCHER_P(IsRequestRestart, method_name, "") {
if (arg->GetMember() != method_name) {
*result_listener << "has member " << arg->GetMember();
return false;
}
return true;
}
MATCHER_P2(IsAmbientLightSensorEnabled, method_name, sensor_enabled, "") {
if (arg->GetMember() != method_name) {
*result_listener << "has member " << arg->GetMember();
return false;
}
dbus::MessageReader reader(arg);
power_manager::SetAmbientLightSensorEnabledRequest request;
if (!reader.PopArrayOfBytesAsProto(&request)) {
*result_listener << "missing or invalid protobuf";
return false;
}
if (request.sensor_enabled() != sensor_enabled) {
*result_listener << "expected enabled = " << sensor_enabled << ", got "
<< request.sensor_enabled();
return false;
}
return true;
}
void RunResponseCallback(dbus::ObjectProxy::ResponseCallback callback,
std::unique_ptr<dbus::Response> response) {
std::move(callback).Run(response.get());
}
class TestObserver : public PowerManagerClient::Observer {
public:
explicit TestObserver(PowerManagerClient* client) : client_(client) {
client_->AddObserver(this);
}
TestObserver(const TestObserver&) = delete;
TestObserver& operator=(const TestObserver&) = delete;
~TestObserver() override { client_->RemoveObserver(this); }
int num_suspend_imminent() const { return num_suspend_imminent_; }
int num_suspend_done() const { return num_suspend_done_; }
int num_dark_suspend_imminent() const { return num_dark_suspend_imminent_; }
int num_restart_requested() const { return num_restart_requested_; }
const base::UnguessableToken& block_suspend_token() const {
return block_suspend_token_;
}
int32_t ambient_color_temperature() const {
return ambient_color_temperature_;
}
power_manager::BatterySaverModeState battery_saver_mode_state() const {
return battery_saver_mode_state_;
}
const power_manager::AmbientLightSensorChange&
last_ambient_light_sensor_change() const {
return last_ambient_light_sensor_change_;
}
const power_manager::AmbientLightSensorChange&
last_keyboard_ambient_light_sensor_change() const {
return last_keyboard_ambient_light_sensor_change_;
}
void set_should_block_suspend(bool take_callback) {
should_block_suspend_ = take_callback;
}
void set_run_unblock_suspend_immediately(bool run) {
run_unblock_suspend_immediately_ = run;
}
[[nodiscard]] bool UnblockSuspend() {
if (block_suspend_token_.is_empty())
return false;
client_->UnblockSuspend(block_suspend_token_);
return true;
}
void SuspendImminent(power_manager::SuspendImminent::Reason reason) override {
num_suspend_imminent_++;
if (should_block_suspend_) {
block_suspend_token_ = base::UnguessableToken::Create();
client_->BlockSuspend(block_suspend_token_, FROM_HERE.ToString());
}
if (run_unblock_suspend_immediately_)
CHECK(UnblockSuspend());
}
void SuspendDone(base::TimeDelta sleep_duration) override {
num_suspend_done_++;
}
void DarkSuspendImminent() override {
num_dark_suspend_imminent_++;
if (should_block_suspend_) {
block_suspend_token_ = base::UnguessableToken::Create();
client_->BlockSuspend(block_suspend_token_, FROM_HERE.ToString());
}
if (run_unblock_suspend_immediately_)
CHECK(UnblockSuspend());
}
void AmbientColorChanged(const int32_t color_temperature) override {
ambient_color_temperature_ = color_temperature;
}
void BatterySaverModeStateChanged(
const power_manager::BatterySaverModeState& state) override {
battery_saver_mode_state_ = state;
}
void RestartRequested(power_manager::RequestRestartReason reason) override {
num_restart_requested_++;
}
void AmbientLightSensorEnabledChanged(
const power_manager::AmbientLightSensorChange& change) override {
last_ambient_light_sensor_change_ = change;
}
void KeyboardAmbientLightSensorEnabledChanged(
const power_manager::AmbientLightSensorChange& change) override {
last_keyboard_ambient_light_sensor_change_ = change;
}
private:
raw_ptr<PowerManagerClient> client_;
int num_suspend_imminent_ = 0;
int num_suspend_done_ = 0;
int num_dark_suspend_imminent_ = 0;
int num_restart_requested_ = 0;
bool should_block_suspend_ = false;
bool run_unblock_suspend_immediately_ = false;
base::UnguessableToken block_suspend_token_;
int32_t ambient_color_temperature_ = 0;
power_manager::BatterySaverModeState battery_saver_mode_state_;
power_manager::AmbientLightSensorChange last_ambient_light_sensor_change_;
power_manager::AmbientLightSensorChange
last_keyboard_ambient_light_sensor_change_;
};
class TestDelegate : public PowerManagerClient::RenderProcessManagerDelegate {
public:
explicit TestDelegate(PowerManagerClient* client) {
client->SetRenderProcessManagerDelegate(weak_ptr_factory_.GetWeakPtr());
}
TestDelegate(const TestDelegate&) = delete;
TestDelegate& operator=(const TestDelegate&) = delete;
~TestDelegate() override = default;
int num_suspend_imminent() const { return num_suspend_imminent_; }
int num_suspend_done() const { return num_suspend_done_; }
void SuspendImminent() override { num_suspend_imminent_++; }
void SuspendDone() override { num_suspend_done_++; }
private:
int num_suspend_imminent_ = 0;
int num_suspend_done_ = 0;
base::WeakPtrFactory<TestDelegate> weak_ptr_factory_{this};
};
class PowerMonitorTestObserverLocal
: public base::test::PowerMonitorTestObserver {
public:
using base::test::PowerMonitorTestObserver::PowerMonitorTestObserver;
PowerMonitorTestObserverLocal(const PowerMonitorTestObserverLocal&) = delete;
PowerMonitorTestObserverLocal& operator=(
const PowerMonitorTestObserverLocal&) = delete;
void OnThermalStateChange(
PowerThermalObserver::DeviceThermalState new_state) override {
base::test::PowerMonitorTestObserver::OnThermalStateChange(new_state);
test_future_.GetCallback().Run(new_state);
}
PowerThermalObserver::DeviceThermalState GetThermalState() {
return test_future_.Take();
}
private:
base::test::TestFuture<PowerThermalObserver::DeviceThermalState> test_future_;
};
}
class PowerManagerClientTest : public testing::Test {
public:
PowerManagerClientTest() = default;
PowerManagerClientTest(const PowerManagerClientTest&) = delete;
PowerManagerClientTest& operator=(const PowerManagerClientTest&) = delete;
~PowerManagerClientTest() override = default;
void SetUp() override {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
bus_ = new dbus::MockBus(std::move(options));
proxy_ = new dbus::MockObjectProxy(
bus_.get(), power_manager::kPowerManagerServiceName,
dbus::ObjectPath(power_manager::kPowerManagerServicePath));
EXPECT_CALL(*bus_,
GetObjectProxy(
power_manager::kPowerManagerServiceName,
dbus::ObjectPath(power_manager::kPowerManagerServicePath)))
.WillRepeatedly(Return(proxy_.get()));
EXPECT_CALL(*bus_, GetDBusTaskRunner())
.WillRepeatedly(
Return(task_environment_.GetMainThreadTaskRunner().get()));
EXPECT_CALL(*bus_, GetOriginTaskRunner())
.WillRepeatedly(
Return(task_environment_.GetMainThreadTaskRunner().get()));
EXPECT_CALL(*proxy_, ConnectToSignal(kInterface, _, _, _))
.WillRepeatedly(Invoke(this, &PowerManagerClientTest::ConnectToSignal));
EXPECT_CALL(*proxy_, SetNameOwnerChangedCallback(_))
.WillRepeatedly(SaveArg<0>(&name_owner_changed_callback_));
EXPECT_CALL(
*proxy_,
CallMethod(HasMember(power_manager::kRegisterSuspendDelayMethod), _, _))
.WillRepeatedly(
Invoke(this, &PowerManagerClientTest::RegisterSuspendDelay));
EXPECT_CALL(
*proxy_,
CallMethod(HasMember(power_manager::kRegisterDarkSuspendDelayMethod), _,
_))
.WillRepeatedly(
Invoke(this, &PowerManagerClientTest::RegisterSuspendDelay));
EXPECT_CALL(
*proxy_,
CallMethod(HasMember(power_manager::kGetThermalStateMethod), _, _));
EXPECT_CALL(
*proxy_,
CallMethod(HasMember(power_manager::kGetPowerSupplyPropertiesMethod), _,
_));
PowerManagerClient::Initialize(bus_.get());
client_ = PowerManagerClient::Get();
base::RunLoop().RunUntilIdle();
}
void TearDown() override { PowerManagerClient::Shutdown(); }
void HandleGetBatterySaverModeState(
dbus::MethodCall* method_call,
int timeout_ms,
dbus::ObjectProxy::ResponseCallback callback) {
power_manager::BatterySaverModeState proto;
proto.set_enabled(true);
auto response = ::dbus::Response::CreateEmpty();
dbus::MessageWriter(response.get()).AppendProtoAsArrayOfBytes(proto);
std::move(callback).Run(response.get());
}
protected:
void EmitSignal(dbus::Signal* signal) {
const std::string signal_name = signal->GetMember();
const auto it = signal_callbacks_.find(signal_name);
ASSERT_TRUE(it != signal_callbacks_.end())
<< "Client didn't register for signal " << signal_name;
it->second.Run(signal);
}
void EmitSuspendImminentSignal(const std::string& signal_name,
int suspend_id) {
power_manager::SuspendImminent proto;
proto.set_suspend_id(suspend_id);
proto.set_reason(power_manager::SuspendImminent_Reason_OTHER);
dbus::Signal signal(kInterface, signal_name);
dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(proto);
EmitSignal(&signal);
}
void EmitSuspendDoneSignal(int suspend_id) {
power_manager::SuspendDone proto;
proto.set_suspend_id(suspend_id);
dbus::Signal signal(kInterface, power_manager::kSuspendDoneSignal);
dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(proto);
EmitSignal(&signal);
}
void ExpectSuspendReadiness(const std::string& method_name,
int suspend_id,
int delay_id) {
EXPECT_CALL(
*proxy_.get(),
CallMethod(IsSuspendReadiness(method_name, suspend_id, delay_id), _,
_));
}
static const int kSuspendDelayId = 100;
static const int kDarkSuspendDelayId = 200;
base::test::SingleThreadTaskEnvironment task_environment_;
scoped_refptr<dbus::MockBus> bus_;
scoped_refptr<dbus::MockObjectProxy> proxy_;
raw_ptr<PowerManagerClient, DanglingUntriaged> client_ = nullptr;
std::map<std::string, dbus::ObjectProxy::SignalCallback> signal_callbacks_;
dbus::ObjectProxy::NameOwnerChangedCallback name_owner_changed_callback_;
private:
void ConnectToSignal(
const std::string& interface_name,
const std::string& signal_name,
dbus::ObjectProxy::SignalCallback signal_callback,
dbus::ObjectProxy::OnConnectedCallback on_connected_callback) {
CHECK_EQ(interface_name, power_manager::kPowerManagerInterface);
signal_callbacks_[signal_name] = signal_callback;
task_environment_.GetMainThreadTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(std::move(on_connected_callback), interface_name,
signal_name, true ));
}
void RegisterSuspendDelay(dbus::MethodCall* method_call,
int timeout_ms,
dbus::ObjectProxy::ResponseCallback callback) {
power_manager::RegisterSuspendDelayReply proto;
proto.set_delay_id(method_call->GetMember() ==
power_manager::kRegisterDarkSuspendDelayMethod
? kDarkSuspendDelayId
: kSuspendDelayId);
method_call->SetSerial(123);
std::unique_ptr<dbus::Response> response(
dbus::Response::FromMethodCall(method_call));
CHECK(dbus::MessageWriter(response.get()).AppendProtoAsArrayOfBytes(proto));
task_environment_.GetMainThreadTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&RunResponseCallback, std::move(callback),
std::move(response)));
}
};
TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithoutObservers) {
const int kSuspendId = 1;
ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
EmitSuspendDoneSignal(kSuspendId);
}
TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithoutCallbacks) {
TestObserver observer_1(client_);
TestObserver observer_2(client_);
const int kSuspendId = 1;
ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
EXPECT_EQ(1, observer_1.num_suspend_imminent());
EXPECT_EQ(0, observer_1.num_suspend_done());
EXPECT_EQ(1, observer_2.num_suspend_imminent());
EXPECT_EQ(0, observer_2.num_suspend_done());
EmitSuspendDoneSignal(kSuspendId);
EXPECT_EQ(1, observer_1.num_suspend_imminent());
EXPECT_EQ(1, observer_1.num_suspend_done());
EXPECT_EQ(1, observer_2.num_suspend_imminent());
EXPECT_EQ(1, observer_2.num_suspend_done());
}
TEST_F(PowerManagerClientTest, ReportSuspendReadinessWithCallbacks) {
TestObserver observer_1(client_);
observer_1.set_should_block_suspend(true);
TestObserver observer_2(client_);
observer_2.set_should_block_suspend(true);
TestObserver observer_3(client_);
const int kSuspendId = 1;
EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
EXPECT_TRUE(observer_1.UnblockSuspend());
ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
EXPECT_TRUE(observer_2.UnblockSuspend());
EmitSuspendDoneSignal(kSuspendId);
EXPECT_EQ(1, observer_1.num_suspend_done());
EXPECT_EQ(1, observer_2.num_suspend_done());
}
TEST_F(PowerManagerClientTest, NotifyRenderProcessManagerDelegate) {
TestDelegate delegate(client_);
TestObserver observer(client_);
observer.set_should_block_suspend(true);
const int kSuspendId = 1;
EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
EXPECT_EQ(0, delegate.num_suspend_imminent());
EXPECT_EQ(0, delegate.num_suspend_done());
ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
EXPECT_TRUE(observer.UnblockSuspend());
EXPECT_EQ(1, delegate.num_suspend_imminent());
EXPECT_EQ(0, delegate.num_suspend_done());
EmitSuspendDoneSignal(kSuspendId);
EXPECT_EQ(1, delegate.num_suspend_imminent());
EXPECT_EQ(1, delegate.num_suspend_done());
}
TEST_F(PowerManagerClientTest, ReportDarkSuspendReadiness) {
TestDelegate delegate(client_);
TestObserver observer(client_);
observer.set_should_block_suspend(true);
const int kSuspendId = 1;
EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
EXPECT_EQ(1, observer.num_suspend_imminent());
EXPECT_EQ(0, delegate.num_suspend_imminent());
ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
EXPECT_TRUE(observer.UnblockSuspend());
EXPECT_EQ(1, delegate.num_suspend_imminent());
const int kDarkSuspendId = 5;
EmitSuspendImminentSignal(kDarkSuspendImminent, kDarkSuspendId);
EXPECT_EQ(1, observer.num_dark_suspend_imminent());
EXPECT_EQ(1, delegate.num_suspend_imminent());
EXPECT_EQ(0, delegate.num_suspend_done());
ExpectSuspendReadiness(kHandleDarkSuspendReadiness, kDarkSuspendId,
kDarkSuspendDelayId);
EXPECT_TRUE(observer.UnblockSuspend());
EXPECT_EQ(0, delegate.num_suspend_done());
EmitSuspendDoneSignal(kSuspendId);
EXPECT_EQ(1, observer.num_suspend_done());
EXPECT_EQ(1, delegate.num_suspend_done());
}
TEST_F(PowerManagerClientTest, SuspendCancelledWhileCallbackPending) {
TestDelegate delegate(client_);
TestObserver observer(client_);
observer.set_should_block_suspend(true);
const int kSuspendId = 1;
EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
EXPECT_EQ(1, observer.num_suspend_imminent());
EmitSuspendDoneSignal(kSuspendId);
EXPECT_EQ(1, observer.num_suspend_done());
EXPECT_EQ(0, delegate.num_suspend_done());
EXPECT_TRUE(observer.UnblockSuspend());
EXPECT_EQ(0, delegate.num_suspend_imminent());
EXPECT_EQ(0, delegate.num_suspend_done());
}
TEST_F(PowerManagerClientTest, SuspendDoneWhileDarkSuspendCallbackPending) {
TestDelegate delegate(client_);
TestObserver observer(client_);
observer.set_should_block_suspend(true);
const int kSuspendId = 1;
EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
EXPECT_TRUE(observer.UnblockSuspend());
EXPECT_EQ(1, delegate.num_suspend_imminent());
const int kDarkSuspendId = 5;
EmitSuspendImminentSignal(kDarkSuspendImminent, kDarkSuspendId);
EXPECT_EQ(1, observer.num_dark_suspend_imminent());
EmitSuspendDoneSignal(kSuspendId);
EXPECT_EQ(1, observer.num_suspend_done());
EXPECT_EQ(1, delegate.num_suspend_done());
EXPECT_TRUE(observer.UnblockSuspend());
EXPECT_EQ(1, delegate.num_suspend_imminent());
EXPECT_EQ(1, delegate.num_suspend_done());
}
TEST_F(PowerManagerClientTest, DarkSuspendImminentWhileCallbackPending) {
TestDelegate delegate(client_);
TestObserver observer(client_);
observer.set_should_block_suspend(true);
const int kSuspendId = 1;
EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
EXPECT_EQ(1, observer.num_suspend_imminent());
base::UnguessableToken regular_token = observer.block_suspend_token();
const int kDarkSuspendId = 1;
EmitSuspendImminentSignal(kDarkSuspendImminent, kDarkSuspendId);
EXPECT_EQ(1, observer.num_dark_suspend_imminent());
base::UnguessableToken dark_token = observer.block_suspend_token();
EmitSuspendDoneSignal(kSuspendId);
EXPECT_EQ(1, observer.num_suspend_done());
client_->UnblockSuspend(regular_token);
client_->UnblockSuspend(dark_token);
}
TEST_F(PowerManagerClientTest, SyncCallbackWithSingleObserver) {
TestObserver observer(client_);
observer.set_should_block_suspend(true);
observer.set_run_unblock_suspend_immediately(true);
const int kSuspendId = 1;
ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
EmitSuspendDoneSignal(kSuspendId);
}
TEST_F(PowerManagerClientTest, SyncCallbackWithMultipleObservers) {
TestObserver observer1(client_);
observer1.set_should_block_suspend(true);
observer1.set_run_unblock_suspend_immediately(true);
TestObserver observer2(client_);
observer2.set_should_block_suspend(true);
const int kSuspendId = 1;
EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
ExpectSuspendReadiness(kHandleSuspendReadiness, kSuspendId, kSuspendDelayId);
EXPECT_TRUE(observer2.UnblockSuspend());
EmitSuspendDoneSignal(kSuspendId);
}
TEST_F(PowerManagerClientTest, ChangeAmbientColorTemperature) {
TestObserver observer(client_);
constexpr int32_t kTemperature = 6500;
dbus::Signal signal(kInterface,
power_manager::kAmbientColorTemperatureChangedSignal);
dbus::MessageWriter(&signal).AppendInt32(kTemperature);
EmitSignal(&signal);
EXPECT_EQ(kTemperature, observer.ambient_color_temperature());
}
TEST_F(PowerManagerClientTest, ChangeThermalState) {
base::test::ScopedPowerMonitorTestSource power_monitor_source;
PowerMonitorTestObserverLocal observer;
base::PowerMonitor::GetInstance()->AddPowerThermalObserver(&observer);
typedef struct {
power_manager::ThermalEvent::ThermalState dbus_state;
base::PowerThermalObserver::DeviceThermalState expected_state;
} ThermalDBusTestType;
ThermalDBusTestType thermal_states[] = {
{.dbus_state = power_manager::ThermalEvent_ThermalState_NOMINAL,
.expected_state =
base::PowerThermalObserver::DeviceThermalState::kNominal},
{.dbus_state = power_manager::ThermalEvent_ThermalState_FAIR,
.expected_state = base::PowerThermalObserver::DeviceThermalState::kFair},
{.dbus_state = power_manager::ThermalEvent_ThermalState_SERIOUS,
.expected_state =
base::PowerThermalObserver::DeviceThermalState::kSerious},
{.dbus_state = power_manager::ThermalEvent_ThermalState_CRITICAL,
.expected_state =
base::PowerThermalObserver::DeviceThermalState::kCritical},
{.dbus_state = power_manager::ThermalEvent_ThermalState_UNKNOWN,
.expected_state =
base::PowerThermalObserver::DeviceThermalState::kUnknown},
};
for (const auto& p : thermal_states) {
power_manager::ThermalEvent proto;
proto.set_thermal_state(p.dbus_state);
proto.set_timestamp(0);
dbus::Signal signal(kInterface, power_manager::kThermalEventSignal);
dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(proto);
EmitSignal(&signal);
EXPECT_EQ(observer.GetThermalState(), p.expected_state);
}
base::PowerMonitor::GetInstance()->RemovePowerThermalObserver(&observer);
}
TEST_F(PowerManagerClientTest, RequestSuspend) {
const uint64_t expected_count = -1ULL;
const int32_t expected_duration = 5;
const auto expected_flavor = power_manager::REQUEST_SUSPEND_DEFAULT;
EXPECT_CALL(*proxy_.get(),
CallMethod(IsRequestSuspend("RequestSuspend", expected_count,
expected_duration, expected_flavor),
_, _));
client_->RequestSuspend(std::nullopt, expected_duration, expected_flavor);
const uint64_t expected_count2 = 18446744073709550592ULL;
const int32_t expected_duration2 = -5;
const auto expected_flavor2 = power_manager::REQUEST_SUSPEND_TO_DISK;
EXPECT_CALL(*proxy_.get(),
CallMethod(IsRequestSuspend("RequestSuspend", expected_count2,
expected_duration2, expected_flavor2),
_, _));
client_->RequestSuspend(expected_count2, expected_duration2,
expected_flavor2);
}
TEST_F(PowerManagerClientTest, ObserverCalledAfterRequestRestart) {
TestObserver observer(client_);
EXPECT_CALL(*proxy_.get(),
CallMethod(IsRequestRestart("RequestRestart"), _, _));
EXPECT_EQ(0, observer.num_restart_requested());
client_->RequestRestart(
power_manager::RequestRestartReason::REQUEST_RESTART_OTHER,
"test restart");
EXPECT_EQ(1, observer.num_restart_requested());
}
TEST_F(PowerManagerClientTest, GetSetBatterySaverModeState) {
EXPECT_CALL(
*proxy_,
CallMethod(HasMember(power_manager::kSetBatterySaverModeState), _, _));
power_manager::SetBatterySaverModeStateRequest proto;
proto.set_enabled(true);
client_->SetBatterySaverModeState(proto);
EXPECT_CALL(
*proxy_,
CallMethod(HasMember(power_manager::kGetBatterySaverModeState), _, _))
.WillOnce(Invoke(
this, &PowerManagerClientTest::HandleGetBatterySaverModeState));
client_->GetBatterySaverModeState(base::BindOnce(
[](std::optional<power_manager::BatterySaverModeState> state) {
ASSERT_TRUE(state.has_value());
EXPECT_TRUE(state->enabled());
}));
}
TEST_F(PowerManagerClientTest, BatterySaverModeStateChanged) {
TestObserver observer(client_);
power_manager::BatterySaverModeState proto;
proto.set_enabled(true);
dbus::Signal signal(kInterface, power_manager::kBatterySaverModeStateChanged);
dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(proto);
EmitSignal(&signal);
EXPECT_EQ(proto.enabled(), observer.battery_saver_mode_state().enabled());
}
TEST_F(PowerManagerClientTest, SetAmbientLightSensorEnabled) {
power_manager::SetAmbientLightSensorEnabledRequest request;
request.set_sensor_enabled(false);
EXPECT_CALL(*proxy_.get(),
CallMethod(IsAmbientLightSensorEnabled(
"SetAmbientLightSensorEnabled", false),
_, _));
client_->SetAmbientLightSensorEnabled(request);
request.set_sensor_enabled(true);
EXPECT_CALL(*proxy_.get(),
CallMethod(IsAmbientLightSensorEnabled(
"SetAmbientLightSensorEnabled", true),
_, _));
client_->SetAmbientLightSensorEnabled(request);
}
TEST_F(PowerManagerClientTest, SetKeyboardAmbientLightSensorEnabled) {
power_manager::SetAmbientLightSensorEnabledRequest request;
request.set_sensor_enabled(false);
EXPECT_CALL(*proxy_.get(),
CallMethod(IsAmbientLightSensorEnabled(
"SetKeyboardAmbientLightSensorEnabled", false),
_, _));
client_->SetKeyboardAmbientLightSensorEnabled(request);
request.set_sensor_enabled(true);
EXPECT_CALL(*proxy_.get(),
CallMethod(IsAmbientLightSensorEnabled(
"SetKeyboardAmbientLightSensorEnabled", true),
_, _));
client_->SetKeyboardAmbientLightSensorEnabled(request);
}
TEST_F(PowerManagerClientTest, GetKeyboardAmbientLightSensorEnabled) {
EXPECT_CALL(
*proxy_,
CallMethod(
HasMember(power_manager::kGetKeyboardAmbientLightSensorEnabledMethod),
_, _))
.WillOnce([](dbus::MethodCall* method_call, int timeout_ms,
dbus::ObjectProxy::ResponseCallback callback) {
auto response = ::dbus::Response::CreateEmpty();
dbus::MessageWriter(response.get()).AppendBool(true);
std::move(callback).Run(response.get());
});
client_->GetKeyboardAmbientLightSensorEnabled(
base::BindOnce([](std::optional<bool> is_ambient_light_sensor_enabled) {
EXPECT_TRUE(is_ambient_light_sensor_enabled.value());
}));
EXPECT_CALL(
*proxy_,
CallMethod(
HasMember(power_manager::kGetKeyboardAmbientLightSensorEnabledMethod),
_, _))
.WillOnce([](dbus::MethodCall* method_call, int timeout_ms,
dbus::ObjectProxy::ResponseCallback callback) {
auto response = ::dbus::Response::CreateEmpty();
dbus::MessageWriter(response.get()).AppendBool(false);
std::move(callback).Run(response.get());
});
client_->GetKeyboardAmbientLightSensorEnabled(
base::BindOnce([](std::optional<bool> is_ambient_light_sensor_enabled) {
EXPECT_FALSE(is_ambient_light_sensor_enabled.value());
}));
}
TEST_F(PowerManagerClientTest, HasAmbientLightSensor) {
EXPECT_CALL(
*proxy_,
CallMethod(HasMember(power_manager::kHasAmbientLightSensorMethod), _, _))
.WillOnce([](dbus::MethodCall* method_call, int timeout_ms,
dbus::ObjectProxy::ResponseCallback callback) {
auto response = ::dbus::Response::CreateEmpty();
dbus::MessageWriter(response.get()).AppendBool(true);
std::move(callback).Run(response.get());
});
client_->HasAmbientLightSensor(
base::BindOnce([](std::optional<bool> has_ambient_light_sensor) {
EXPECT_TRUE(has_ambient_light_sensor.value());
}));
EXPECT_CALL(
*proxy_,
CallMethod(HasMember(power_manager::kHasAmbientLightSensorMethod), _, _))
.WillOnce([](dbus::MethodCall* method_call, int timeout_ms,
dbus::ObjectProxy::ResponseCallback callback) {
auto response = ::dbus::Response::CreateEmpty();
dbus::MessageWriter(response.get()).AppendBool(false);
std::move(callback).Run(response.get());
});
client_->HasAmbientLightSensor(
base::BindOnce([](std::optional<bool> has_ambient_light_sensor) {
EXPECT_FALSE(has_ambient_light_sensor.value());
}));
}
TEST_F(PowerManagerClientTest, AmbientLightSensorEnabledChanged) {
TestObserver observer(client_);
EXPECT_FALSE(
observer.last_ambient_light_sensor_change().has_sensor_enabled());
EXPECT_FALSE(observer.last_ambient_light_sensor_change().has_cause());
{
power_manager::AmbientLightSensorChange proto;
proto.set_sensor_enabled(false);
proto.set_cause(
power_manager::AmbientLightSensorChange_Cause_BRIGHTNESS_USER_REQUEST);
dbus::Signal signal(kInterface,
power_manager::kAmbientLightSensorEnabledChangedSignal);
dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(proto);
EmitSignal(&signal);
EXPECT_TRUE(
observer.last_ambient_light_sensor_change().has_sensor_enabled());
EXPECT_EQ(proto.sensor_enabled(),
observer.last_ambient_light_sensor_change().sensor_enabled());
EXPECT_TRUE(observer.last_ambient_light_sensor_change().has_cause());
EXPECT_EQ(proto.cause(),
observer.last_ambient_light_sensor_change().cause());
}
{
power_manager::AmbientLightSensorChange proto;
proto.set_sensor_enabled(true);
proto.set_cause(
power_manager::
AmbientLightSensorChange_Cause_USER_REQUEST_SETTINGS_APP);
dbus::Signal signal(kInterface,
power_manager::kAmbientLightSensorEnabledChangedSignal);
dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(proto);
EmitSignal(&signal);
EXPECT_TRUE(
observer.last_ambient_light_sensor_change().has_sensor_enabled());
EXPECT_EQ(proto.sensor_enabled(),
observer.last_ambient_light_sensor_change().sensor_enabled());
EXPECT_TRUE(observer.last_ambient_light_sensor_change().has_cause());
EXPECT_EQ(proto.cause(),
observer.last_ambient_light_sensor_change().cause());
}
}
TEST_F(PowerManagerClientTest, KeyboardAmbientLightSensorEnabledChanged) {
TestObserver observer(client_);
EXPECT_FALSE(observer.last_keyboard_ambient_light_sensor_change()
.has_sensor_enabled());
EXPECT_FALSE(
observer.last_keyboard_ambient_light_sensor_change().has_cause());
{
power_manager::AmbientLightSensorChange proto;
proto.set_sensor_enabled(false);
proto.set_cause(
power_manager::AmbientLightSensorChange_Cause_BRIGHTNESS_USER_REQUEST);
dbus::Signal signal(
kInterface,
power_manager::kKeyboardAmbientLightSensorEnabledChangedSignal);
dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(proto);
EmitSignal(&signal);
EXPECT_TRUE(observer.last_keyboard_ambient_light_sensor_change()
.has_sensor_enabled());
EXPECT_EQ(
proto.sensor_enabled(),
observer.last_keyboard_ambient_light_sensor_change().sensor_enabled());
EXPECT_TRUE(
observer.last_keyboard_ambient_light_sensor_change().has_cause());
EXPECT_EQ(proto.cause(),
observer.last_keyboard_ambient_light_sensor_change().cause());
}
{
power_manager::AmbientLightSensorChange proto;
proto.set_sensor_enabled(true);
proto.set_cause(
power_manager::
AmbientLightSensorChange_Cause_USER_REQUEST_SETTINGS_APP);
dbus::Signal signal(
kInterface,
power_manager::kKeyboardAmbientLightSensorEnabledChangedSignal);
dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(proto);
EmitSignal(&signal);
EXPECT_TRUE(observer.last_keyboard_ambient_light_sensor_change()
.has_sensor_enabled());
EXPECT_EQ(
proto.sensor_enabled(),
observer.last_keyboard_ambient_light_sensor_change().sensor_enabled());
EXPECT_TRUE(
observer.last_keyboard_ambient_light_sensor_change().has_cause());
EXPECT_EQ(proto.cause(),
observer.last_keyboard_ambient_light_sensor_change().cause());
}
}
TEST_F(PowerManagerClientTest, GetAmbientLightSensorEnabled) {
EXPECT_CALL(
*proxy_,
CallMethod(HasMember(power_manager::kGetAmbientLightSensorEnabledMethod),
_, _))
.WillOnce([](dbus::MethodCall* method_call, int timeout_ms,
dbus::ObjectProxy::ResponseCallback callback) {
auto response = ::dbus::Response::CreateEmpty();
dbus::MessageWriter(response.get()).AppendBool(true);
std::move(callback).Run(response.get());
});
client_->GetAmbientLightSensorEnabled(
base::BindOnce([](std::optional<bool> is_ambient_light_sensor_enabled) {
EXPECT_TRUE(is_ambient_light_sensor_enabled.value());
}));
EXPECT_CALL(
*proxy_,
CallMethod(HasMember(power_manager::kGetAmbientLightSensorEnabledMethod),
_, _))
.WillOnce([](dbus::MethodCall* method_call, int timeout_ms,
dbus::ObjectProxy::ResponseCallback callback) {
auto response = ::dbus::Response::CreateEmpty();
dbus::MessageWriter(response.get()).AppendBool(false);
std::move(callback).Run(response.get());
});
client_->GetAmbientLightSensorEnabled(
base::BindOnce([](std::optional<bool> is_ambient_light_sensor_enabled) {
EXPECT_FALSE(is_ambient_light_sensor_enabled.value());
}));
}
}