1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/power_monitor/power_monitor_device_source.h"
#include <string>
#include "base/logging.h"
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_monitor_source.h"
#include "base/strings/string_util.h"
#include "base/task/current_thread.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/win/wrapped_window_proc.h"
namespace base {
void ProcessPowerEventHelper(PowerMonitorSource::PowerEvent event) {
PowerMonitorSource::ProcessPowerEvent(event);
}
namespace {
constexpr wchar_t kWindowClassName[] = L"Base_PowerMessageWindow";
void ProcessWmPowerBroadcastMessage(WPARAM event_id) {
PowerMonitorSource::PowerEvent power_event;
switch (event_id) {
case PBT_APMPOWERSTATUSCHANGE: // The power status changed.
power_event = PowerMonitorSource::POWER_STATE_EVENT;
break;
case PBT_APMRESUMEAUTOMATIC: // Resume from suspend.
// We don't notify for PBT_APMRESUMESUSPEND
// because, if it occurs, it is always sent as a
// second event after PBT_APMRESUMEAUTOMATIC.
power_event = PowerMonitorSource::RESUME_EVENT;
break;
case PBT_APMSUSPEND: // System has been suspended.
power_event = PowerMonitorSource::SUSPEND_EVENT;
break;
default:
return;
// Other Power Events:
// PBT_APMBATTERYLOW - removed in Vista.
// PBT_APMOEMEVENT - removed in Vista.
// PBT_APMQUERYSUSPEND - removed in Vista.
// PBT_APMQUERYSUSPENDFAILED - removed in Vista.
// PBT_APMRESUMECRITICAL - removed in Vista.
// PBT_POWERSETTINGCHANGE - user changed the power settings.
}
ProcessPowerEventHelper(power_event);
}
} // namespace
void PowerMonitorDeviceSource::PlatformInit() {
// Only for testing.
if (!CurrentUIThread::IsSet()) {
return;
}
speed_limit_observer_ =
std::make_unique<base::SequenceBound<SpeedLimitObserverWin>>(
base::ThreadPool::CreateSequencedTaskRunner({}),
BindRepeating(&PowerMonitorSource::ProcessSpeedLimitEvent));
}
void PowerMonitorDeviceSource::PlatformDestroy() {
// Because |speed_limit_observer_| is sequence bound, the actual destruction
// happens asynchronously on its task runner. Until this has completed it is
// still possible for PowerMonitorSource::ProcessSpeedLimitEvent to be called.
speed_limit_observer_.reset();
}
// Function to query the system to see if it is currently running on
// battery power. Returns true if running on battery.
bool PowerMonitorDeviceSource::IsOnBatteryPower() {
SYSTEM_POWER_STATUS status;
if (!::GetSystemPowerStatus(&status)) {
DPLOG(ERROR) << "GetSystemPowerStatus failed";
return false;
}
return (status.ACLineStatus == 0);
}
int PowerMonitorDeviceSource::GetInitialSpeedLimit() {
// Returns the maximum value once at start. Subsequent actual values will be
// provided asynchronously via callbacks instead.
return PowerThermalObserver::kSpeedLimitMax;
}
PowerMonitorDeviceSource::PowerMessageWindow::PowerMessageWindow() {
if (!CurrentUIThread::IsSet()) {
// Creating this window in (e.g.) a renderer inhibits shutdown on Windows.
// See http://crbug.com/230122. TODO(vandebo): http://crbug.com/236031
DLOG(ERROR)
<< "Cannot create windows on non-UI thread, power monitor disabled!";
return;
}
WNDCLASSEX window_class;
base::win::InitializeWindowClass(
kWindowClassName,
&base::win::WrappedWindowProc<
PowerMonitorDeviceSource::PowerMessageWindow::WndProcThunk>,
0, 0, 0, nullptr, nullptr, nullptr, nullptr, nullptr, &window_class);
instance_ = window_class.hInstance;
ATOM clazz = ::RegisterClassEx(&window_class);
DCHECK(clazz);
message_hwnd_ =
::CreateWindowEx(WS_EX_NOACTIVATE, kWindowClassName, nullptr, WS_POPUP, 0,
0, 0, 0, nullptr, nullptr, instance_, nullptr);
if (message_hwnd_) {
// On machines with modern standby calling RegisterSuspendResumeNotification
// is required in order to get the PBT_APMSUSPEND message.
power_notify_handle_ = ::RegisterSuspendResumeNotification(
message_hwnd_, DEVICE_NOTIFY_WINDOW_HANDLE);
}
}
PowerMonitorDeviceSource::PowerMessageWindow::~PowerMessageWindow() {
if (message_hwnd_) {
if (power_notify_handle_)
::UnregisterSuspendResumeNotification(power_notify_handle_);
::DestroyWindow(message_hwnd_);
::UnregisterClass(kWindowClassName, instance_);
}
}
// static
LRESULT CALLBACK PowerMonitorDeviceSource::PowerMessageWindow::WndProcThunk(
HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam) {
switch (message) {
case WM_POWERBROADCAST:
ProcessWmPowerBroadcastMessage(wparam);
return TRUE;
default:
return ::DefWindowProc(hwnd, message, wparam, lparam);
}
}
} // namespace base
|