Index: base/system_monitor/system_monitor_win.cc |
=================================================================== |
--- base/system_monitor/system_monitor_win.cc (revision 137792) |
+++ base/system_monitor/system_monitor_win.cc (working copy) |
@@ -1,9 +1,111 @@ |
-// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Copyright (c) 2012 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/system_monitor.h" |
+#include "base/utf_string_conversions.h" |
+#include "base/win/windows_version.h" |
+namespace { |
+ |
+// Maps a request's reason to the handle and requests count. |
+typedef std::map<std::string, std::pair<HANDLE, int> > HanleMap; |
brettw
2012/05/18 18:19:46
How did you still manage to misspell this? :)
rvargas (doing something else)
2012/05/18 18:44:52
Never underestimate the power of the the brain aut
|
+ |
+#if _WIN32_WINNT <= _WIN32_WINNT_WIN7 |
+POWER_REQUEST_TYPE PowerRequestExecutionRequired = |
+ static_cast<POWER_REQUEST_TYPE>(PowerRequestAwayModeRequired + 1); |
+#endif |
+ |
+POWER_REQUEST_TYPE PowerRequestTestRequired = |
+ static_cast<POWER_REQUEST_TYPE>(PowerRequestExecutionRequired + 10); |
+ |
+POWER_REQUEST_TYPE PowerRequirementToType( |
+ base::SystemMonitor::PowerRequirement requirement) { |
+ switch (requirement) { |
+ case base::SystemMonitor::DISPLAY_REQUIRED: |
+ return PowerRequestDisplayRequired; |
+ case base::SystemMonitor::SYSTEM_REQUIRED: |
+ return PowerRequestSystemRequired; |
+ case base::SystemMonitor::CPU_REQUIRED: |
+ return PowerRequestExecutionRequired; |
+ case base::SystemMonitor::TEST_REQUIRED: |
+ return PowerRequestTestRequired; |
+ } |
+ NOTREACHED(); |
+ return PowerRequestTestRequired; |
+} |
+ |
+HANDLE CreatePowerRequest(POWER_REQUEST_TYPE type, const std::string& reason) { |
+ typedef HANDLE (WINAPI* PowerCreateRequestPtr)(PREASON_CONTEXT); |
+ typedef BOOL (WINAPI* PowerSetRequestPtr)(HANDLE, POWER_REQUEST_TYPE); |
+ |
+ if (type == PowerRequestTestRequired) |
+ return NULL; |
+ |
+ if (type == PowerRequestExecutionRequired && |
+ base::win::GetVersion() < base::win::VERSION_WIN8) { |
+ return INVALID_HANDLE_VALUE; |
+ } |
+ |
+ static PowerCreateRequestPtr PowerCreateRequestFn = NULL; |
+ static PowerSetRequestPtr PowerSetRequestFn = NULL; |
+ |
+ if (!PowerCreateRequestFn || !PowerSetRequestFn) { |
+ HMODULE module = GetModuleHandle(L"kernel32.dll"); |
+ PowerCreateRequestFn = reinterpret_cast<PowerCreateRequestPtr>( |
+ GetProcAddress(module, "PowerCreateRequest")); |
+ PowerSetRequestFn = reinterpret_cast<PowerSetRequestPtr>( |
+ GetProcAddress(module, "PowerSetRequest")); |
+ |
+ if (!PowerCreateRequestFn || !PowerSetRequestFn) |
+ return INVALID_HANDLE_VALUE; |
+ } |
+ string16 wide_reason = ASCIIToUTF16(reason); |
+ REASON_CONTEXT context = {0}; |
+ context.Version = POWER_REQUEST_CONTEXT_VERSION; |
+ context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING; |
+ context.Reason.SimpleReasonString = const_cast<wchar_t*>(wide_reason.c_str()); |
+ |
+ base::win::ScopedHandle handle(PowerCreateRequestFn(&context)); |
+ if (!handle.IsValid()) |
+ return INVALID_HANDLE_VALUE; |
+ |
+ if (PowerSetRequestFn(handle, type)) |
+ return handle.Take(); |
+ |
+ // Something went wrong. |
+ return INVALID_HANDLE_VALUE; |
+} |
+ |
+// Takes ownership of the |handle|. |
+void DeletePowerRequest(POWER_REQUEST_TYPE type, HANDLE handle) { |
+ if (type == PowerRequestTestRequired) |
+ return; |
+ |
+ base::win::ScopedHandle request_handle(handle); |
+ if (!request_handle.IsValid()) |
+ return; |
+ |
+ if (type == PowerRequestExecutionRequired && |
+ base::win::GetVersion() < base::win::VERSION_WIN8) { |
+ return; |
+ } |
+ |
+ typedef BOOL (WINAPI* PowerClearRequestPtr)(HANDLE, POWER_REQUEST_TYPE); |
+ HMODULE module = GetModuleHandle(L"kernel32.dll"); |
+ PowerClearRequestPtr PowerClearRequestFn = |
+ reinterpret_cast<PowerClearRequestPtr>( |
+ GetProcAddress(module, "PowerClearRequest")); |
+ |
+ if (!PowerClearRequestFn) |
+ return; |
+ |
+ BOOL success = PowerClearRequest(request_handle, type); |
+ DCHECK(success); |
+} |
+ |
+} // namespace. |
+ |
namespace base { |
void SystemMonitor::ProcessWmPowerBroadcastMessage(int event_id) { |
@@ -36,6 +138,50 @@ |
ProcessPowerMessage(power_event); |
} |
+void SystemMonitor::BeginPowerRequirement(PowerRequirement requirement, |
+ const std::string& reason) { |
+ thread_checker_.CalledOnValidThread(); |
+ |
+ HanleMap::iterator i = handles_.find(reason); |
+ if (i != handles_.end()) { |
+ // This is not the first request, just increase the requests count. |
+ i->second.second++; |
+ DCHECK_GT(i->second.second, 1); |
+ return; |
+ } |
+ |
+ HANDLE handle = CreatePowerRequest(PowerRequirementToType(requirement), |
+ reason); |
+ |
+ if (handle != INVALID_HANDLE_VALUE) |
+ handles_[reason] = std::pair<HANDLE, int>(handle, 1); |
+} |
+ |
+void SystemMonitor::EndPowerRequirement(PowerRequirement requirement, |
+ const std::string& reason) { |
+ thread_checker_.CalledOnValidThread(); |
+ |
+ HanleMap::iterator i = handles_.find(reason); |
+ if (i == handles_.end()) { |
+ NOTREACHED(); |
+ return; |
+ } |
+ |
+ // Decrease the requests count and see if this the last request. |
+ i->second.second--; |
+ DCHECK_GE(i->second.second, 0); |
+ |
+ if (i->second.second) |
+ return; |
+ |
+ DeletePowerRequest(PowerRequirementToType(requirement), i->second.first); |
+ handles_.erase(i); |
+} |
+ |
+size_t SystemMonitor::GetPowerRequirementsCountForTest() const { |
+ return handles_.size(); |
+} |
+ |
// Function to query the system to see if it is currently running on |
// battery power. Returns true if running on battery. |
bool SystemMonitor::IsBatteryPower() { |