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. 4 5 #include "services/device/battery/battery_status_manager.h" 6 7 #include <memory> 8 9 #include "base/macros.h" 10 #include "base/memory/ref_counted.h" 11 #include "chromeos/dbus/power/power_manager_client.h" 12 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h" 13 14 namespace device { 15 16 namespace { 17 18 class PowerManagerObserver 19 : public chromeos::PowerManagerClient::Observer, 20 public base::RefCountedThreadSafe<PowerManagerObserver> { 21 public: PowerManagerObserver(const BatteryStatusService::BatteryUpdateCallback & callback)22 explicit PowerManagerObserver( 23 const BatteryStatusService::BatteryUpdateCallback& callback) 24 : callback_(callback), currently_listening_(false) {} 25 26 // Starts listening for updates. Start()27 void Start() { 28 if (currently_listening_) 29 return; 30 chromeos::PowerManagerClient* power_client = 31 chromeos::PowerManagerClient::Get(); 32 power_client->AddObserver(this); 33 power_client->RequestStatusUpdate(); 34 currently_listening_ = true; 35 } 36 37 // Stops listening for updates. Stop()38 void Stop() { 39 if (!currently_listening_) 40 return; 41 chromeos::PowerManagerClient::Get()->RemoveObserver(this); 42 currently_listening_ = false; 43 } 44 45 private: 46 friend class base::RefCountedThreadSafe<PowerManagerObserver>; 47 ~PowerManagerObserver()48 ~PowerManagerObserver() override {} 49 IsBatteryPresent(const power_manager::PowerSupplyProperties & proto) const50 bool IsBatteryPresent( 51 const power_manager::PowerSupplyProperties& proto) const { 52 return proto.battery_state() != 53 power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT; 54 } 55 IsUsbChargerConnected(const power_manager::PowerSupplyProperties & proto) const56 bool IsUsbChargerConnected( 57 const power_manager::PowerSupplyProperties& proto) const { 58 return proto.external_power() == 59 power_manager::PowerSupplyProperties_ExternalPower_USB; 60 } 61 IsBatteryCharging(const power_manager::PowerSupplyProperties & proto) const62 bool IsBatteryCharging( 63 const power_manager::PowerSupplyProperties& proto) const { 64 return proto.battery_state() != 65 power_manager::PowerSupplyProperties_BatteryState_DISCHARGING; 66 } 67 IsBatteryFull(const power_manager::PowerSupplyProperties & proto) const68 bool IsBatteryFull(const power_manager::PowerSupplyProperties& proto) const { 69 return proto.battery_state() == 70 power_manager::PowerSupplyProperties_BatteryState_FULL; 71 } 72 GetBatteryLevel(const power_manager::PowerSupplyProperties & proto) const73 double GetBatteryLevel( 74 const power_manager::PowerSupplyProperties& proto) const { 75 const double kMaxBatteryLevelProto = 100.f; 76 return proto.battery_percent() / kMaxBatteryLevelProto; 77 } 78 79 // chromeos::PowerManagerClient::Observer: PowerChanged(const power_manager::PowerSupplyProperties & proto)80 void PowerChanged( 81 const power_manager::PowerSupplyProperties& proto) override { 82 mojom::BatteryStatus status; 83 84 // Use the default values if there is no battery in the system. 85 if (IsBatteryPresent(proto)) { 86 // The charging status is unreliable if a low power charger is connected 87 // (i.e. usb). 88 bool status_unreliable = IsUsbChargerConnected(proto); 89 // Battery time is unreliable if it is still being computed. 90 bool time_unreliable = 91 status_unreliable || proto.is_calculating_battery_time(); 92 93 // Set |charging| only if the status is reliable. Otherwise, keep the 94 // default (which is |true|). 95 if (!status_unreliable) 96 status.charging = IsBatteryCharging(proto); 97 98 // Set |chargingTime| to +infinity if the battery is discharging, or if 99 // the time is unreliable. Keep the default value (which is 0) if the 100 // battery is full. 101 if (time_unreliable || !status.charging) 102 status.charging_time = std::numeric_limits<double>::infinity(); 103 else if (!IsBatteryFull(proto)) 104 status.charging_time = proto.battery_time_to_full_sec(); 105 106 // Keep the default value for |dischargingTime| (which is +infinity) if 107 // the time is unreliable, or if the battery is charging. 108 if (!time_unreliable && !status.charging) 109 status.discharging_time = proto.battery_time_to_empty_sec(); 110 111 status.level = GetBatteryLevel(proto); 112 } 113 callback_.Run(status); 114 } 115 116 BatteryStatusService::BatteryUpdateCallback callback_; 117 bool currently_listening_; 118 119 DISALLOW_COPY_AND_ASSIGN(PowerManagerObserver); 120 }; 121 122 class BatteryStatusManagerChromeOS 123 : public BatteryStatusManager, 124 public chromeos::PowerManagerClient::Observer { 125 public: BatteryStatusManagerChromeOS(const BatteryStatusService::BatteryUpdateCallback & callback)126 explicit BatteryStatusManagerChromeOS( 127 const BatteryStatusService::BatteryUpdateCallback& callback) 128 : observer_(base::MakeRefCounted<PowerManagerObserver>(callback)) {} 129 ~BatteryStatusManagerChromeOS()130 ~BatteryStatusManagerChromeOS() override { observer_->Stop(); } 131 132 private: 133 // BatteryStatusManager: StartListeningBatteryChange()134 bool StartListeningBatteryChange() override { 135 observer_->Start(); 136 return true; 137 } 138 StopListeningBatteryChange()139 void StopListeningBatteryChange() override { observer_->Stop(); } 140 141 scoped_refptr<PowerManagerObserver> observer_; 142 143 DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerChromeOS); 144 }; 145 146 } // namespace 147 148 // static Create(const BatteryStatusService::BatteryUpdateCallback & callback)149std::unique_ptr<BatteryStatusManager> BatteryStatusManager::Create( 150 const BatteryStatusService::BatteryUpdateCallback& callback) { 151 return std::make_unique<BatteryStatusManagerChromeOS>(callback); 152 } 153 154 } // namespace device 155