1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/battery_status/battery_status_manager.h"
7 #include "base/memory/ref_counted.h"
8 #include "chromeos/dbus/dbus_thread_manager.h"
9 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
10 #include "chromeos/dbus/power_manager_client.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "third_party/WebKit/public/platform/WebBatteryStatus.h"
18 class PowerManagerObserver
19 : public chromeos::PowerManagerClient::Observer
,
20 public base::RefCountedThreadSafe
<PowerManagerObserver
> {
22 explicit PowerManagerObserver(
23 const BatteryStatusService::BatteryUpdateCallback
& callback
)
24 : callback_(callback
), currently_listening_(false) {}
26 // Starts listening for updates. It is safe to call this on any thread.
28 if (BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
31 BrowserThread::PostTask(
34 base::Bind(&PowerManagerObserver::StartOnUI
, this));
38 // Stops listening for updates. It is safe to call this on any thread.
40 if (BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
43 BrowserThread::PostTask(
46 base::Bind(&PowerManagerObserver::StopOnUI
, this));
51 friend class base::RefCountedThreadSafe
<PowerManagerObserver
>;
53 virtual ~PowerManagerObserver() {}
55 bool IsBatteryPresent(
56 const power_manager::PowerSupplyProperties
& proto
) const {
57 return proto
.battery_state() !=
58 power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT
;
61 bool IsUsbChargerConnected(
62 const power_manager::PowerSupplyProperties
& proto
) const {
63 return proto
.external_power() ==
64 power_manager::PowerSupplyProperties_ExternalPower_USB
;
67 bool IsBatteryCharging(
68 const power_manager::PowerSupplyProperties
& proto
) const {
69 return proto
.battery_state() !=
70 power_manager::PowerSupplyProperties_BatteryState_DISCHARGING
;
73 bool IsBatteryFull(const power_manager::PowerSupplyProperties
& proto
) const {
74 return proto
.battery_state() ==
75 power_manager::PowerSupplyProperties_BatteryState_FULL
;
78 double GetBatteryLevel(
79 const power_manager::PowerSupplyProperties
& proto
) const {
80 const double kMaxBatteryLevelProto
= 100.f
;
81 return proto
.battery_percent() / kMaxBatteryLevelProto
;
85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
86 if (currently_listening_
)
88 chromeos::PowerManagerClient
* power_client
=
89 chromeos::DBusThreadManager::Get()->GetPowerManagerClient();
90 power_client
->AddObserver(this);
91 power_client
->RequestStatusUpdate();
92 currently_listening_
= true;
96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
97 if (!currently_listening_
)
99 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(
101 currently_listening_
= false;
104 // chromeos::PowerManagerClient::Observer:
105 virtual void PowerChanged(
106 const power_manager::PowerSupplyProperties
& proto
) OVERRIDE
{
107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
108 blink::WebBatteryStatus status
;
109 // Use the default values if there is no battery in the system.
110 if (IsBatteryPresent(proto
)) {
111 // The charging status is unreliable if a low power charger is connected
113 bool status_unreliable
= IsUsbChargerConnected(proto
);
114 // Battery time is unreliable if it is still being computed.
115 bool time_unreliable
=
116 status_unreliable
|| proto
.is_calculating_battery_time();
118 // Set |charging| only if the status is reliable. Otherwise, keep the
119 // default (which is |true|).
120 if (!status_unreliable
)
121 status
.charging
= IsBatteryCharging(proto
);
123 // Set |chargingTime| to +infinity if the battery is discharging, or if
124 // the time is unreliable. Keep the default value (which is 0) if the
126 if (time_unreliable
|| !status
.charging
)
127 status
.chargingTime
= std::numeric_limits
<double>::infinity();
128 else if (!IsBatteryFull(proto
))
129 status
.chargingTime
= proto
.battery_time_to_full_sec();
131 // Keep the default value for |dischargingTime| (which is +infinity) if
132 // the time is unreliable, or if the battery is charging.
133 if (!time_unreliable
&& !status
.charging
)
134 status
.dischargingTime
= proto
.battery_time_to_empty_sec();
136 status
.level
= GetBatteryLevel(proto
);
138 callback_
.Run(status
);
141 BatteryStatusService::BatteryUpdateCallback callback_
;
142 bool currently_listening_
;
144 DISALLOW_COPY_AND_ASSIGN(PowerManagerObserver
);
147 class BatteryStatusManagerChromeOS
148 : public BatteryStatusManager
,
149 public chromeos::PowerManagerClient::Observer
{
151 explicit BatteryStatusManagerChromeOS(
152 const BatteryStatusService::BatteryUpdateCallback
& callback
)
153 : observer_(new PowerManagerObserver(callback
)) {}
155 virtual ~BatteryStatusManagerChromeOS() { observer_
->Stop(); }
158 // BatteryStatusManager:
159 virtual bool StartListeningBatteryChange() OVERRIDE
{
160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
165 virtual void StopListeningBatteryChange() OVERRIDE
{
166 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
170 scoped_refptr
<PowerManagerObserver
> observer_
;
172 DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerChromeOS
);
178 scoped_ptr
<BatteryStatusManager
> BatteryStatusManager::Create(
179 const BatteryStatusService::BatteryUpdateCallback
& callback
) {
180 return scoped_ptr
<BatteryStatusManager
>(
181 new BatteryStatusManagerChromeOS(callback
));
184 } // namespace content