summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/SConscript2
-rw-r--r--base/build/base.vcproj12
-rw-r--r--base/build/base_unittests.vcproj4
-rw-r--r--base/system_monitor.cc42
-rw-r--r--base/system_monitor.h110
-rw-r--r--base/system_monitor_unittest.cc66
-rw-r--r--base/system_monitor_win.cc40
7 files changed, 276 insertions, 0 deletions
diff --git a/base/SConscript b/base/SConscript
index b9667bd..8b6eab2 100644
--- a/base/SConscript
+++ b/base/SConscript
@@ -59,6 +59,7 @@ input_files = [
'string_piece.cc',
'string_util.cc',
'string_util_icu.cc',
+ 'system_monitor.cc',
'thread.cc',
'time.cc',
'time_format.cc',
@@ -116,6 +117,7 @@ if env['PLATFORM'] == 'win32':
'shared_memory_win.cc',
'sys_info_win.cc',
'sys_string_conversions_win.cc',
+ 'system_monitor_win.cc',
'thread_local_storage_win.cc',
'thread_local_win.cc',
'time_win.cc',
diff --git a/base/build/base.vcproj b/base/build/base.vcproj
index 5f69555..c80e372 100644
--- a/base/build/base.vcproj
+++ b/base/build/base.vcproj
@@ -718,6 +718,18 @@
>
</File>
<File
+ RelativePath="..\system_monitor.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\system_monitor.h"
+ >
+ </File>
+ <File
+ RelativePath="..\system_monitor_win.cc"
+ >
+ </File>
+ <File
RelativePath="..\task.h"
>
</File>
diff --git a/base/build/base_unittests.vcproj b/base/build/base_unittests.vcproj
index 1fa32c9..4f1d999 100644
--- a/base/build/base_unittests.vcproj
+++ b/base/build/base_unittests.vcproj
@@ -316,6 +316,10 @@
>
</File>
<File
+ RelativePath="..\system_monitor_unittest.cc"
+ >
+ </File>
+ <File
RelativePath="..\thread_local_storage_unittest.cc"
>
</File>
diff --git a/base/system_monitor.cc b/base/system_monitor.cc
new file mode 100644
index 0000000..375945d
--- /dev/null
+++ b/base/system_monitor.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2008 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 "base/system_monitor.h"
+
+namespace base {
+
+SystemMonitor::SystemMonitor()
+ : battery_in_use_(IsBatteryPower()),
+ suspended_(false) {
+}
+
+void SystemMonitor::ProcessPowerMessage(PowerEvent event_id) {
+ // Suppress duplicate notifications. Some platforms may
+ // send multiple notifications of the same event.
+ switch (event_id) {
+ case PowerStateEvent:
+ {
+ bool on_battery = IsBatteryPower();
+ if (on_battery != battery_in_use_) {
+ battery_in_use_ = on_battery;
+ NotifyPowerStateChange();
+ }
+ }
+ break;
+ case ResumeEvent:
+ if (suspended_) {
+ suspended_ = false;
+ NotifyResume();
+ }
+ break;
+ case SuspendEvent:
+ if (!suspended_) {
+ suspended_ = true;
+ NotifySuspend();
+ }
+ break;
+ }
+}
+
+} // namespace base \ No newline at end of file
diff --git a/base/system_monitor.h b/base/system_monitor.h
new file mode 100644
index 0000000..ec4c593
--- /dev/null
+++ b/base/system_monitor.h
@@ -0,0 +1,110 @@
+// Copyright (c) 2008 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.
+
+#ifndef BASE_SYSTEM_MONITOR_H_
+#define BASE_SYSTEM_MONITOR_H_
+
+#include "base/logging.h"
+#include "base/observer_list.h"
+#include "base/singleton.h"
+
+namespace base {
+
+// Singleton class for monitoring various system-related subsystems
+// such as power management, network status, etc.
+// TODO(mbelshe): Add support beyond just power management.
+class SystemMonitor {
+ public:
+ // Access to the Singleton
+ static SystemMonitor* Get() {
+ return Singleton<SystemMonitor>::get();
+ }
+
+ //
+ // Power-related APIs
+ //
+
+ // Is the computer currently on battery power.
+ bool BatteryPower() { return battery_in_use_; }
+
+ // Normalized list of power events.
+ enum PowerEvent {
+ // The Power status of the system has changed.
+ PowerStateEvent,
+
+ // The system is being suspended.
+ SuspendEvent,
+
+ // The system is being resumed.
+ ResumeEvent
+ };
+
+ class PowerObserver {
+ public:
+ // Notification of a change in power status of the computer, such
+ // as from switching between battery and A/C power.
+ virtual void OnPowerStateChange(SystemMonitor*) = 0;
+
+ // Notification that the system is suspending.
+ virtual void OnSuspend(SystemMonitor*) = 0;
+
+ // Notification that the system is resuming.
+ virtual void OnResume(SystemMonitor*) = 0;
+ };
+
+ void AddObserver(PowerObserver* obs) {
+ observer_list_.AddObserver(obs);
+ }
+
+ void RemoveObserver(PowerObserver* obs) {
+ observer_list_.RemoveObserver(obs);
+ }
+
+ void NotifyPowerStateChange() {
+ LOG(INFO) << L"PowerStateChange: "
+ << (BatteryPower() ? L"On" : L"Off") << L" battery";
+ FOR_EACH_OBSERVER(PowerObserver, observer_list_,
+ OnPowerStateChange(this));
+ }
+
+ void NotifySuspend() {
+ FOR_EACH_OBSERVER(PowerObserver, observer_list_, OnSuspend(this));
+ }
+
+ void NotifyResume() {
+ FOR_EACH_OBSERVER(PowerObserver, observer_list_, OnResume(this));
+ }
+
+ // Constructor.
+ // Don't use this; access SystemMonitor via the Singleton.
+ SystemMonitor();
+
+#if defined(OS_WIN)
+ // Windows-specific handling of a WM_POWERBROADCAST message.
+ // Embedders of this API should hook their top-level window
+ // message loop and forward WM_POWERBROADCAST through this call.
+ void ProcessWmPowerBroadcastMessage(int event_id);
+#endif
+
+ // Cross-platform handling of a power event.
+ // This is only exposed for testing.
+ void ProcessPowerMessage(PowerEvent event_id);
+
+ private:
+ // Platform-specific method to check whether the system is currently
+ // running on battery power. Returns true if running on batteries,
+ // false otherwise.
+ bool IsBatteryPower();
+
+ ObserverList<PowerObserver> observer_list_;
+ bool battery_in_use_;
+ bool suspended_;
+
+ DISALLOW_COPY_AND_ASSIGN(SystemMonitor);
+};
+
+}
+
+#endif // BASE_SYSTEM_MONITOR_H_
+
diff --git a/base/system_monitor_unittest.cc b/base/system_monitor_unittest.cc
new file mode 100644
index 0000000..aced8fe
--- /dev/null
+++ b/base/system_monitor_unittest.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2008 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 "base/system_monitor.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class PowerTest : public base::SystemMonitor::PowerObserver {
+ public:
+ PowerTest()
+ : battery_(false),
+ power_state_changes_(0),
+ suspends_(0),
+ resumes_(0) {};
+
+ // PowerObserver callbacks.
+ void OnPowerStateChange(base::SystemMonitor*) { power_state_changes_++; };
+ void OnSuspend(base::SystemMonitor*) { suspends_++; };
+ void OnResume(base::SystemMonitor*) { resumes_++; };
+
+ // Test status counts.
+ bool battery() { return battery_; }
+ int power_state_changes() { return power_state_changes_; }
+ int suspends() { return suspends_; }
+ int resumes() { return resumes_; }
+
+ private:
+ bool battery_; // Do we currently think we're on battery power.
+ int power_state_changes_; // Count of OnPowerStateChange notifications.
+ int suspends_; // Count of OnSuspend notifications.
+ int resumes_; // Count of OnResume notifications.
+};
+
+TEST(SystemMonitor, PowerNotifications) {
+ base::SystemMonitor* monitor = base::SystemMonitor::Get();
+ PowerTest test;
+ monitor->AddObserver(&test);
+
+ // Send a bunch of power changes. Since the battery power hasn't
+ // actually changed, we shouldn't get notifications.
+ for (int index = 0; index < 5; index++) {
+ monitor->ProcessPowerMessage(base::SystemMonitor::PowerStateEvent);
+ EXPECT_EQ(test.power_state_changes(), 0);
+ }
+
+ // Sending resume when not suspended should have no effect.
+ monitor->ProcessPowerMessage(base::SystemMonitor::ResumeEvent);
+ EXPECT_EQ(test.resumes(), 0);
+
+ // Pretend we suspended.
+ monitor->ProcessPowerMessage(base::SystemMonitor::SuspendEvent);
+ EXPECT_EQ(test.suspends(), 1);
+
+ // Send a second suspend notification. This should be suppressed.
+ monitor->ProcessPowerMessage(base::SystemMonitor::SuspendEvent);
+ EXPECT_EQ(test.suspends(), 1);
+
+ // Pretend we were awakened.
+ monitor->ProcessPowerMessage(base::SystemMonitor::ResumeEvent);
+ EXPECT_EQ(test.resumes(), 1);
+
+ // Send a duplicate resume notification. This should be suppressed.
+ monitor->ProcessPowerMessage(base::SystemMonitor::ResumeEvent);
+ EXPECT_EQ(test.resumes(), 1);
+}
+
diff --git a/base/system_monitor_win.cc b/base/system_monitor_win.cc
new file mode 100644
index 0000000..0603797
--- /dev/null
+++ b/base/system_monitor_win.cc
@@ -0,0 +1,40 @@
+// Copyright (c) 2008 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 "base/system_monitor.h"
+
+namespace base {
+
+void SystemMonitor::ProcessWmPowerBroadcastMessage(int event_id) {
+ PowerEvent power_event;
+ switch (event_id) {
+ case PBT_APMPOWERSTATUSCHANGE:
+ power_event = PowerStateEvent;
+ break;
+ case PBT_APMRESUMEAUTOMATIC:
+ power_event = ResumeEvent;
+ break;
+ case PBT_APMSUSPEND:
+ power_event = SuspendEvent;
+ break;
+ default:
+ DCHECK(false);
+ }
+ ProcessPowerMessage(power_event);
+}
+
+// Function to query the system to see if it is currently running on
+// battery power. Returns true if running on battery.
+bool SystemMonitor::IsBatteryPower() {
+ SYSTEM_POWER_STATUS status;
+ if (!GetSystemPowerStatus(&status)) {
+ LOG(ERROR) << "GetSystemPowerStatus failed: " << GetLastError();
+ return false;
+ }
+ return (status.ACLineStatus == 0);
+}
+
+
+
+} // namespace base \ No newline at end of file