Commit cacf4934 authored by Etienne Bergeron's avatar Etienne Bergeron Committed by Commit Bot

[1/4] Allow registration of power monitor observers pre-initialization

This CL is allowing the registration of PowerObservers before the
PowerMonitor is initialized.

The PowerMonitor has a PowerSource and a ObserverList. The call to
PowerMonitor::Initialize is used to set a PowerSource that will
trigger the notifications. It is thus valid to add observers before
the power source is set.

TBR=miu@chromium.org

Bug: 1074332
Change-Id: Ia238b7caf52f80a7de01329908c4979d81341634
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2202877
Commit-Queue: Etienne Bergeron <etienneb@chromium.org>
Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Reviewed-by: default avatarJonathan Backer <backer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#771591}
parent 4fd3317a
...@@ -25,12 +25,8 @@ bool PowerMonitor::IsInitialized() { ...@@ -25,12 +25,8 @@ bool PowerMonitor::IsInitialized() {
return GetInstance()->source_.get() != nullptr; return GetInstance()->source_.get() != nullptr;
} }
bool PowerMonitor::AddObserver(PowerObserver* obs) { void PowerMonitor::AddObserver(PowerObserver* obs) {
PowerMonitor* power_monitor = GetInstance(); GetInstance()->observers_->AddObserver(obs);
if (!IsInitialized())
return false;
power_monitor->observers_->AddObserver(obs);
return true;
} }
void PowerMonitor::RemoveObserver(PowerObserver* obs) { void PowerMonitor::RemoveObserver(PowerObserver* obs) {
...@@ -47,9 +43,8 @@ bool PowerMonitor::IsOnBatteryPower() { ...@@ -47,9 +43,8 @@ bool PowerMonitor::IsOnBatteryPower() {
} }
void PowerMonitor::ShutdownForTesting() { void PowerMonitor::ShutdownForTesting() {
PowerMonitor::GetInstance()->observers_->AssertEmpty();
GetInstance()->source_ = nullptr; GetInstance()->source_ = nullptr;
g_is_process_suspended.store(false); g_is_process_suspended.store(false, std::memory_order_relaxed);
} }
bool PowerMonitor::IsProcessSuspended() { bool PowerMonitor::IsProcessSuspended() {
......
...@@ -40,12 +40,10 @@ class BASE_EXPORT PowerMonitor { ...@@ -40,12 +40,10 @@ class BASE_EXPORT PowerMonitor {
// from which it was registered. // from which it was registered.
// Must not be called from within a notification callback. // Must not be called from within a notification callback.
// //
// AddObserver() fails and returns false if PowerMonitor::Initialize() has not // It is safe to add observers before the PowerMonitor is initialized. It is
// been invoked. Failure should only happen in unit tests, where the // safe to call RemoveObserver with a PowerObserver that was not added as an
// PowerMonitor is generally not initialized. It is safe to call
// RemoveObserver with a PowerObserver that was not successfully added as an
// observer. // observer.
static bool AddObserver(PowerObserver* observer); static void AddObserver(PowerObserver* observer);
static void RemoveObserver(PowerObserver* observer); static void RemoveObserver(PowerObserver* observer);
// Is the computer currently on battery power. May only be called if the // Is the computer currently on battery power. May only be called if the
......
...@@ -13,12 +13,15 @@ namespace base { ...@@ -13,12 +13,15 @@ namespace base {
class PowerMonitorTest : public testing::Test { class PowerMonitorTest : public testing::Test {
protected: protected:
PowerMonitorTest() { PowerMonitorTest() = default;
void TearDown() override { PowerMonitor::ShutdownForTesting(); }
void PowerMonitorInitialize() {
power_monitor_source_ = new PowerMonitorTestSource(); power_monitor_source_ = new PowerMonitorTestSource();
PowerMonitor::Initialize( PowerMonitor::Initialize(
std::unique_ptr<PowerMonitorSource>(power_monitor_source_)); std::unique_ptr<PowerMonitorSource>(power_monitor_source_));
} }
~PowerMonitorTest() override { PowerMonitor::ShutdownForTesting(); }
PowerMonitorTestSource* source() { return power_monitor_source_; } PowerMonitorTestSource* source() { return power_monitor_source_; }
...@@ -34,9 +37,11 @@ class PowerMonitorTest : public testing::Test { ...@@ -34,9 +37,11 @@ class PowerMonitorTest : public testing::Test {
TEST_F(PowerMonitorTest, PowerNotifications) { TEST_F(PowerMonitorTest, PowerNotifications) {
const int kObservers = 5; const int kObservers = 5;
PowerMonitorInitialize();
PowerMonitorTestObserver observers[kObservers]; PowerMonitorTestObserver observers[kObservers];
for (auto& index : observers) for (auto& index : observers)
EXPECT_TRUE(PowerMonitor::AddObserver(&index)); PowerMonitor::AddObserver(&index);
// Sending resume when not suspended should have no effect. // Sending resume when not suspended should have no effect.
source()->GenerateResumeEvent(); source()->GenerateResumeEvent();
...@@ -84,7 +89,9 @@ TEST_F(PowerMonitorTest, PowerNotifications) { ...@@ -84,7 +89,9 @@ TEST_F(PowerMonitorTest, PowerNotifications) {
TEST_F(PowerMonitorTest, ThermalThrottling) { TEST_F(PowerMonitorTest, ThermalThrottling) {
PowerMonitorTestObserver observer; PowerMonitorTestObserver observer;
EXPECT_TRUE(PowerMonitor::AddObserver(&observer)); PowerMonitor::AddObserver(&observer);
PowerMonitorInitialize();
constexpr PowerObserver::DeviceThermalState kThermalStates[] = { constexpr PowerObserver::DeviceThermalState kThermalStates[] = {
PowerObserver::DeviceThermalState::kUnknown, PowerObserver::DeviceThermalState::kUnknown,
...@@ -100,4 +107,32 @@ TEST_F(PowerMonitorTest, ThermalThrottling) { ...@@ -100,4 +107,32 @@ TEST_F(PowerMonitorTest, ThermalThrottling) {
PowerMonitor::RemoveObserver(&observer); PowerMonitor::RemoveObserver(&observer);
} }
TEST_F(PowerMonitorTest, AddObserverBeforeAndAfterInitialization) {
PowerMonitorTestObserver observer1;
PowerMonitorTestObserver observer2;
// An observer is added before the PowerMonitor initialization.
PowerMonitor::AddObserver(&observer1);
PowerMonitorInitialize();
// An observer is added after the PowerMonitor initialization.
PowerMonitor::AddObserver(&observer2);
// Simulate suspend/resume notifications.
source()->GenerateSuspendEvent();
EXPECT_EQ(observer1.suspends(), 1);
EXPECT_EQ(observer2.suspends(), 1);
EXPECT_EQ(observer1.resumes(), 0);
EXPECT_EQ(observer2.resumes(), 0);
source()->GenerateResumeEvent();
EXPECT_EQ(observer1.resumes(), 1);
EXPECT_EQ(observer2.resumes(), 1);
PowerMonitor::RemoveObserver(&observer1);
PowerMonitor::RemoveObserver(&observer2);
}
} // namespace base } // namespace base
...@@ -52,8 +52,10 @@ void WallClockTimer::OnResume() { ...@@ -52,8 +52,10 @@ void WallClockTimer::OnResume() {
} }
void WallClockTimer::AddObserver() { void WallClockTimer::AddObserver() {
if (!observer_added_) if (!observer_added_) {
observer_added_ = base::PowerMonitor::AddObserver(this); base::PowerMonitor::AddObserver(this);
observer_added_ = true;
}
} }
void WallClockTimer::RemoveObserver() { void WallClockTimer::RemoveObserver() {
......
...@@ -284,7 +284,8 @@ void GpuWatchdogThreadImplV2::OnAddPowerObserver() { ...@@ -284,7 +284,8 @@ void GpuWatchdogThreadImplV2::OnAddPowerObserver() {
DCHECK(watchdog_thread_task_runner_->BelongsToCurrentThread()); DCHECK(watchdog_thread_task_runner_->BelongsToCurrentThread());
DCHECK(base::PowerMonitor::IsInitialized()); DCHECK(base::PowerMonitor::IsInitialized());
is_power_observer_added_ = base::PowerMonitor::AddObserver(this); base::PowerMonitor::AddObserver(this);
is_power_observer_added_ = true;
} }
// Running on the watchdog thread. // Running on the watchdog thread.
......
...@@ -181,21 +181,16 @@ H264VideoToolboxEncoder::H264VideoToolboxEncoder( ...@@ -181,21 +181,16 @@ H264VideoToolboxEncoder::H264VideoToolboxEncoder(
weak_factory_.GetWeakPtr(), cast_environment_)); weak_factory_.GetWeakPtr(), cast_environment_));
// Register for power state changes. // Register for power state changes.
if (base::PowerMonitor::AddObserver(this)) { base::PowerMonitor::AddObserver(this);
VLOG(1) << "Registered for power state changes."; VLOG(1) << "Registered for power state changes.";
} else {
DLOG(WARNING) << "No power monitor. Process suspension will invalidate "
"the encoder.";
}
} }
} }
H264VideoToolboxEncoder::~H264VideoToolboxEncoder() { H264VideoToolboxEncoder::~H264VideoToolboxEncoder() {
DestroyCompressionSession(); DestroyCompressionSession();
// If video_frame_factory_ is not null, the encoder registered for power state // Unregister the power observer. It is valid to remove an observer that was
// changes in the ctor and it must now unregister. // not added.
if (video_frame_factory_)
base::PowerMonitor::RemoveObserver(this); base::PowerMonitor::RemoveObserver(this);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment