Bumping manifests a=b2g-bump
[gecko.git] / hal / windows / WindowsBattery.cpp
blobc1b9a31e6128d582e9570265132282b38ef9c597
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "Hal.h"
7 #include "HalImpl.h"
8 #include "nsITimer.h"
9 #include "mozilla/Preferences.h"
10 #include "mozilla/dom/battery/Constants.h"
11 #include "nsComponentManagerUtils.h"
13 #include <windows.h>
14 #include "mozilla/WindowsVersion.h"
16 using namespace mozilla::dom::battery;
18 namespace mozilla {
19 namespace hal_impl {
21 static nsCOMPtr<nsITimer> sUpdateTimer;
23 /* Power Event API is Vista or later */
24 static decltype(RegisterPowerSettingNotification)* sRegisterPowerSettingNotification = nullptr;
25 static decltype(UnregisterPowerSettingNotification)* sUnregisterPowerSettingNotification = nullptr;
26 static HPOWERNOTIFY sPowerHandle = nullptr;
27 static HPOWERNOTIFY sCapacityHandle = nullptr;
28 static HWND sHWnd = nullptr;
30 static void
31 UpdateHandler(nsITimer* aTimer, void* aClosure) {
32 NS_ASSERTION(!IsVistaOrLater(),
33 "We shouldn't call this function for Vista or later version!");
35 static hal::BatteryInformation sLastInfo;
36 hal::BatteryInformation currentInfo;
38 hal_impl::GetCurrentBatteryInformation(&currentInfo);
39 if (sLastInfo.level() != currentInfo.level() ||
40 sLastInfo.charging() != currentInfo.charging() ||
41 sLastInfo.remainingTime() != currentInfo.remainingTime()) {
42 hal::NotifyBatteryChange(currentInfo);
43 sLastInfo = currentInfo;
47 static
48 LRESULT CALLBACK
49 BatteryWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
50 if (msg != WM_POWERBROADCAST || wParam != PBT_POWERSETTINGCHANGE) {
51 return DefWindowProc(hwnd, msg, wParam, lParam);
54 hal::BatteryInformation currentInfo;
56 // Since we need update remainingTime, we cannot use LPARAM.
57 hal_impl::GetCurrentBatteryInformation(&currentInfo);
59 hal::NotifyBatteryChange(currentInfo);
60 return TRUE;
63 void
64 EnableBatteryNotifications()
66 if (IsVistaOrLater()) {
67 // RegisterPowerSettingNotification is from Vista or later.
68 // Use this API if available.
69 HMODULE hUser32 = GetModuleHandleW(L"USER32.DLL");
70 if (!sRegisterPowerSettingNotification)
71 sRegisterPowerSettingNotification = (decltype(RegisterPowerSettingNotification)*)
72 GetProcAddress(hUser32, "RegisterPowerSettingNotification");
73 if (!sUnregisterPowerSettingNotification)
74 sUnregisterPowerSettingNotification = (decltype(UnregisterPowerSettingNotification)*)
75 GetProcAddress(hUser32, "UnregisterPowerSettingNotification");
77 if (!sRegisterPowerSettingNotification ||
78 !sUnregisterPowerSettingNotification) {
79 NS_ASSERTION(false, "Canot find PowerSettingNotification functions.");
80 return;
83 // Create custom window to watch battery event
84 // If we can get Gecko's window handle, this is unnecessary.
86 if (sHWnd == nullptr) {
87 WNDCLASSW wc;
88 HMODULE hSelf = GetModuleHandle(nullptr);
90 if (!GetClassInfoW(hSelf, L"MozillaBatteryClass", &wc)) {
91 ZeroMemory(&wc, sizeof(WNDCLASSW));
92 wc.hInstance = hSelf;
93 wc.lpfnWndProc = BatteryWindowProc;
94 wc.lpszClassName = L"MozillaBatteryClass";
95 RegisterClassW(&wc);
98 sHWnd = CreateWindowW(L"MozillaBatteryClass", L"Battery Watcher",
99 0, 0, 0, 0, 0,
100 nullptr, nullptr, hSelf, nullptr);
103 if (sHWnd == nullptr) {
104 return;
107 sPowerHandle =
108 sRegisterPowerSettingNotification(sHWnd,
109 &GUID_ACDC_POWER_SOURCE,
110 DEVICE_NOTIFY_WINDOW_HANDLE);
111 sCapacityHandle =
112 sRegisterPowerSettingNotification(sHWnd,
113 &GUID_BATTERY_PERCENTAGE_REMAINING,
114 DEVICE_NOTIFY_WINDOW_HANDLE);
115 } else
117 // for Windows XP. If we remove Windows XP support,
118 // we should remove timer-based power notification
119 sUpdateTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
120 if (sUpdateTimer) {
121 sUpdateTimer->InitWithFuncCallback(UpdateHandler,
122 nullptr,
123 Preferences::GetInt("dom.battery.timer",
124 30000 /* 30s */),
125 nsITimer::TYPE_REPEATING_SLACK);
130 void
131 DisableBatteryNotifications()
133 if (IsVistaOrLater()) {
134 if (sPowerHandle) {
135 sUnregisterPowerSettingNotification(sPowerHandle);
136 sPowerHandle = nullptr;
139 if (sCapacityHandle) {
140 sUnregisterPowerSettingNotification(sCapacityHandle);
141 sCapacityHandle = nullptr;
144 if (sHWnd) {
145 DestroyWindow(sHWnd);
146 sHWnd = nullptr;
148 } else
150 if (sUpdateTimer) {
151 sUpdateTimer->Cancel();
152 sUpdateTimer = nullptr;
157 void
158 GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
160 SYSTEM_POWER_STATUS status;
161 if (!GetSystemPowerStatus(&status)) {
162 aBatteryInfo->level() = kDefaultLevel;
163 aBatteryInfo->charging() = kDefaultCharging;
164 aBatteryInfo->remainingTime() = kDefaultRemainingTime;
165 return;
168 aBatteryInfo->level() =
169 status.BatteryLifePercent == 255 ? kDefaultLevel
170 : ((double)status.BatteryLifePercent) / 100.0;
171 aBatteryInfo->charging() = (status.ACLineStatus != 0);
172 if (status.ACLineStatus != 0) {
173 if (aBatteryInfo->level() == 1.0) {
174 // GetSystemPowerStatus API may returns -1 for BatteryFullLifeTime.
175 // So, if battery is 100%, set kDefaultRemainingTime at force.
176 aBatteryInfo->remainingTime() = kDefaultRemainingTime;
177 } else {
178 aBatteryInfo->remainingTime() =
179 status.BatteryFullLifeTime == (DWORD)-1 ? kUnknownRemainingTime
180 : status.BatteryFullLifeTime;
182 } else {
183 aBatteryInfo->remainingTime() =
184 status.BatteryLifeTime == (DWORD)-1 ? kUnknownRemainingTime
185 : status.BatteryLifeTime;
189 } // hal_impl
190 } // mozilla