no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / dom / battery / BatteryManager.cpp
bloba42ac3017d86e5ac06b5f84a1e490860807e3503
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include <cmath>
8 #include <limits>
9 #include "BatteryManager.h"
10 #include "Constants.h"
11 #include "mozilla/DOMEventTargetHelper.h"
12 #include "mozilla/Hal.h"
13 #include "mozilla/dom/BatteryManagerBinding.h"
14 #include "mozilla/Preferences.h"
15 #include "nsContentUtils.h"
16 #include "nsGlobalWindowInner.h"
17 #include "mozilla/dom/Document.h"
19 /**
20 * We have to use macros here because our leak analysis tool things we are
21 * leaking strings when we have |static const nsString|. Sad :(
23 #define LEVELCHANGE_EVENT_NAME u"levelchange"_ns
24 #define CHARGINGCHANGE_EVENT_NAME u"chargingchange"_ns
25 #define DISCHARGINGTIMECHANGE_EVENT_NAME u"dischargingtimechange"_ns
26 #define CHARGINGTIMECHANGE_EVENT_NAME u"chargingtimechange"_ns
28 namespace mozilla::dom::battery {
30 BatteryManager::BatteryManager(nsPIDOMWindowInner* aWindow)
31 : DOMEventTargetHelper(aWindow),
32 mLevel(kDefaultLevel),
33 mCharging(kDefaultCharging),
34 mRemainingTime(kDefaultRemainingTime) {}
36 void BatteryManager::Init() {
37 hal::RegisterBatteryObserver(this);
39 hal::BatteryInformation batteryInfo;
40 hal::GetCurrentBatteryInformation(&batteryInfo);
42 UpdateFromBatteryInfo(batteryInfo);
45 void BatteryManager::Shutdown() { hal::UnregisterBatteryObserver(this); }
47 JSObject* BatteryManager::WrapObject(JSContext* aCx,
48 JS::Handle<JSObject*> aGivenProto) {
49 return BatteryManager_Binding::Wrap(aCx, this, aGivenProto);
52 bool BatteryManager::Charging() const {
53 MOZ_ASSERT(NS_IsMainThread());
54 // For testing, unable to report the battery status information
55 if (Preferences::GetBool("dom.battery.test.default", false)) {
56 return true;
58 if (Preferences::GetBool("dom.battery.test.charging", false)) {
59 return true;
61 if (Preferences::GetBool("dom.battery.test.discharging", false)) {
62 return false;
65 return mCharging;
68 double BatteryManager::DischargingTime() const {
69 MOZ_ASSERT(NS_IsMainThread());
70 // For testing, unable to report the battery status information
71 if (Preferences::GetBool("dom.battery.test.default", false)) {
72 return std::numeric_limits<double>::infinity();
74 if (Preferences::GetBool("dom.battery.test.discharging", false)) {
75 return 42.0;
78 if (Charging() || mRemainingTime == kUnknownRemainingTime) {
79 return std::numeric_limits<double>::infinity();
82 return mRemainingTime;
85 double BatteryManager::ChargingTime() const {
86 MOZ_ASSERT(NS_IsMainThread());
87 // For testing, unable to report the battery status information
88 if (Preferences::GetBool("dom.battery.test.default", false)) {
89 return 0.0;
91 if (Preferences::GetBool("dom.battery.test.charging", false)) {
92 return 42.0;
95 if (!Charging() || mRemainingTime == kUnknownRemainingTime) {
96 return std::numeric_limits<double>::infinity();
99 return mRemainingTime;
102 double BatteryManager::Level() const {
103 MOZ_ASSERT(NS_IsMainThread());
104 // For testing, unable to report the battery status information
105 if (Preferences::GetBool("dom.battery.test.default")) {
106 return 1.0;
109 return mLevel;
112 void BatteryManager::UpdateFromBatteryInfo(
113 const hal::BatteryInformation& aBatteryInfo) {
114 mLevel = aBatteryInfo.level();
116 // Round to the nearest ten percent for non-chrome.
117 Document* doc = GetOwnerWindow() ? GetOwnerWindow()->GetDoc() : nullptr;
119 mCharging = aBatteryInfo.charging();
120 mRemainingTime = aBatteryInfo.remainingTime();
122 if (!nsContentUtils::IsChromeDoc(doc)) {
123 mLevel = lround(mLevel * 10.0) / 10.0;
124 if (mLevel == 1.0) {
125 mRemainingTime =
126 mCharging ? kDefaultRemainingTime : kUnknownRemainingTime;
127 } else if (mRemainingTime != kUnknownRemainingTime) {
128 // Round the remaining time to a multiple of 15 minutes and never zero
129 const double MINUTES_15 = 15.0 * 60.0;
130 mRemainingTime =
131 fmax(lround(mRemainingTime / MINUTES_15) * MINUTES_15, MINUTES_15);
135 // Add some guards to make sure the values are coherent.
136 if (mLevel == 1.0 && mCharging == true &&
137 mRemainingTime != kDefaultRemainingTime) {
138 mRemainingTime = kDefaultRemainingTime;
139 NS_ERROR(
140 "Battery API: When charging and level at 1.0, remaining time "
141 "should be 0. Please fix your backend!");
145 void BatteryManager::Notify(const hal::BatteryInformation& aBatteryInfo) {
146 double previousLevel = mLevel;
147 bool previousCharging = mCharging;
148 double previousRemainingTime = mRemainingTime;
150 UpdateFromBatteryInfo(aBatteryInfo);
152 if (previousCharging != mCharging) {
153 DispatchTrustedEvent(CHARGINGCHANGE_EVENT_NAME);
156 if (previousLevel != mLevel) {
157 DispatchTrustedEvent(LEVELCHANGE_EVENT_NAME);
161 * There are a few situations that could happen here:
162 * 1. Charging state changed:
163 * a. Previous remaining time wasn't unkwonw, we have to fire an event for
164 * the change.
165 * b. New remaining time isn't unkwonw, we have to fire an event for it.
166 * 2. Charging state didn't change but remainingTime did, we have to fire
167 * the event that correspond to the current charging state.
169 if (mCharging != previousCharging) {
170 if (previousRemainingTime != kUnknownRemainingTime) {
171 DispatchTrustedEvent(previousCharging ? CHARGINGTIMECHANGE_EVENT_NAME
172 : DISCHARGINGTIMECHANGE_EVENT_NAME);
174 if (mRemainingTime != kUnknownRemainingTime) {
175 DispatchTrustedEvent(mCharging ? CHARGINGTIMECHANGE_EVENT_NAME
176 : DISCHARGINGTIMECHANGE_EVENT_NAME);
178 } else if (previousRemainingTime != mRemainingTime) {
179 DispatchTrustedEvent(mCharging ? CHARGINGTIMECHANGE_EVENT_NAME
180 : DISCHARGINGTIMECHANGE_EVENT_NAME);
184 } // namespace mozilla::dom::battery