1 // Copyright 2013 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 "ash/system/chromeos/power/tray_power.h"
7 #include "ash/ash_switches.h"
8 #include "ash/test/ash_test_base.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
11 #include "ui/message_center/fake_message_center.h"
13 using message_center::Notification;
14 using power_manager::PowerSupplyProperties;
18 class MockMessageCenter : public message_center::FakeMessageCenter {
20 MockMessageCenter() : add_count_(0), remove_count_(0) {}
21 virtual ~MockMessageCenter() {}
23 int add_count() const { return add_count_; }
24 int remove_count() const { return remove_count_; }
26 // message_center::FakeMessageCenter overrides:
27 virtual void AddNotification(scoped_ptr<Notification> notification) OVERRIDE {
30 virtual void RemoveNotification(const std::string& id, bool by_user)
39 DISALLOW_COPY_AND_ASSIGN(MockMessageCenter);
47 class TrayPowerTest : public test::AshTestBase {
50 virtual ~TrayPowerTest() {}
52 MockMessageCenter* message_center() { return message_center_.get(); }
53 TrayPower* tray_power() { return tray_power_.get(); }
55 // test::AshTestBase::SetUp() overrides:
56 virtual void SetUp() OVERRIDE {
57 test::AshTestBase::SetUp();
58 message_center_.reset(new MockMessageCenter());
59 tray_power_.reset(new TrayPower(NULL, message_center_.get()));
62 virtual void TearDown() OVERRIDE {
64 message_center_.reset();
65 test::AshTestBase::TearDown();
68 TrayPower::NotificationState notification_state() const {
69 return tray_power_->notification_state_;
72 bool MaybeShowUsbChargerNotification(const PowerSupplyProperties& proto) {
73 PowerStatus::Get()->SetProtoForTesting(proto);
74 return tray_power_->MaybeShowUsbChargerNotification();
77 bool UpdateNotificationState(const PowerSupplyProperties& proto) {
78 PowerStatus::Get()->SetProtoForTesting(proto);
79 return tray_power_->UpdateNotificationState();
82 void SetUsbChargerConnected(bool connected) {
83 tray_power_->usb_charger_was_connected_ = connected;
86 // Returns a discharging PowerSupplyProperties more appropriate for testing.
87 static PowerSupplyProperties DefaultPowerSupplyProperties() {
88 PowerSupplyProperties proto;
89 proto.set_external_power(
90 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED);
91 proto.set_battery_state(
92 power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
93 proto.set_battery_percent(50.0);
94 proto.set_battery_time_to_empty_sec(3 * 60 * 60);
95 proto.set_battery_time_to_full_sec(2 * 60 * 60);
96 proto.set_is_calculating_battery_time(false);
101 scoped_ptr<MockMessageCenter> message_center_;
102 scoped_ptr<TrayPower> tray_power_;
104 DISALLOW_COPY_AND_ASSIGN(TrayPowerTest);
107 TEST_F(TrayPowerTest, MaybeShowUsbChargerNotification) {
108 PowerSupplyProperties discharging = DefaultPowerSupplyProperties();
109 EXPECT_FALSE(MaybeShowUsbChargerNotification(discharging));
110 EXPECT_EQ(0, message_center()->add_count());
111 EXPECT_EQ(0, message_center()->remove_count());
113 // Notification shows when connecting a USB charger.
114 PowerSupplyProperties usb_connected = DefaultPowerSupplyProperties();
115 usb_connected.set_external_power(
116 power_manager::PowerSupplyProperties_ExternalPower_USB);
117 EXPECT_TRUE(MaybeShowUsbChargerNotification(usb_connected));
118 EXPECT_EQ(1, message_center()->add_count());
119 EXPECT_EQ(0, message_center()->remove_count());
121 // Change in charge does not trigger the notification again.
122 PowerSupplyProperties more_charge = DefaultPowerSupplyProperties();
123 more_charge.set_external_power(
124 power_manager::PowerSupplyProperties_ExternalPower_USB);
125 more_charge.set_battery_time_to_full_sec(60 * 60);
126 more_charge.set_battery_percent(75.0);
127 SetUsbChargerConnected(true);
128 EXPECT_FALSE(MaybeShowUsbChargerNotification(more_charge));
129 EXPECT_EQ(1, message_center()->add_count());
130 EXPECT_EQ(0, message_center()->remove_count());
132 // Disconnecting a USB charger with the notification showing should close
134 EXPECT_TRUE(MaybeShowUsbChargerNotification(discharging));
135 EXPECT_EQ(1, message_center()->add_count());
136 EXPECT_EQ(1, message_center()->remove_count());
139 TEST_F(TrayPowerTest, UpdateNotificationState) {
140 // No notifications when no battery present.
141 PowerSupplyProperties no_battery = DefaultPowerSupplyProperties();
142 no_battery.set_external_power(
143 power_manager::PowerSupplyProperties_ExternalPower_AC);
144 no_battery.set_battery_state(
145 power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT);
146 EXPECT_FALSE(UpdateNotificationState(no_battery));
147 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
149 // No notification when calculating remaining battery time.
150 PowerSupplyProperties calculating = DefaultPowerSupplyProperties();
151 calculating.set_is_calculating_battery_time(true);
152 EXPECT_FALSE(UpdateNotificationState(calculating));
153 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
155 // No notification when charging.
156 PowerSupplyProperties charging = DefaultPowerSupplyProperties();
157 charging.set_external_power(
158 power_manager::PowerSupplyProperties_ExternalPower_AC);
159 charging.set_battery_state(
160 power_manager::PowerSupplyProperties_BatteryState_CHARGING);
161 EXPECT_FALSE(UpdateNotificationState(charging));
162 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
164 // When the rounded minutes-to-empty are above the threshold, no notification
166 PowerSupplyProperties low = DefaultPowerSupplyProperties();
167 low.set_battery_time_to_empty_sec(TrayPower::kLowPowerMinutes * 60 + 30);
168 EXPECT_FALSE(UpdateNotificationState(low));
169 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
171 // When the rounded value matches the threshold, the notification should
173 low.set_battery_time_to_empty_sec(TrayPower::kLowPowerMinutes * 60 + 29);
174 EXPECT_TRUE(UpdateNotificationState(low));
175 EXPECT_EQ(TrayPower::NOTIFICATION_LOW_POWER, notification_state());
177 // It should persist at lower values.
178 low.set_battery_time_to_empty_sec(TrayPower::kLowPowerMinutes * 60 - 20);
179 EXPECT_FALSE(UpdateNotificationState(low));
180 EXPECT_EQ(TrayPower::NOTIFICATION_LOW_POWER, notification_state());
182 // The critical low battery notification should be shown when the rounded
183 // value is at the lower threshold.
184 PowerSupplyProperties critical = DefaultPowerSupplyProperties();
185 critical.set_battery_time_to_empty_sec(TrayPower::kCriticalMinutes * 60 + 29);
186 EXPECT_TRUE(UpdateNotificationState(critical));
187 EXPECT_EQ(TrayPower::NOTIFICATION_CRITICAL, notification_state());
189 // The notification should be dismissed when the no-warning threshold is
191 PowerSupplyProperties safe = DefaultPowerSupplyProperties();
192 safe.set_battery_time_to_empty_sec(TrayPower::kNoWarningMinutes * 60 - 29);
193 EXPECT_FALSE(UpdateNotificationState(safe));
194 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
196 // Test that rounded percentages are used when a USB charger is connected.
197 PowerSupplyProperties low_usb = DefaultPowerSupplyProperties();
198 low_usb.set_external_power(
199 power_manager::PowerSupplyProperties_ExternalPower_USB);
200 low_usb.set_battery_percent(TrayPower::kLowPowerPercentage + 0.5);
201 EXPECT_FALSE(UpdateNotificationState(low_usb));
202 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
204 low_usb.set_battery_percent(TrayPower::kLowPowerPercentage + 0.49);
205 EXPECT_TRUE(UpdateNotificationState(low_usb));
206 EXPECT_EQ(TrayPower::NOTIFICATION_LOW_POWER, notification_state());
208 PowerSupplyProperties critical_usb = DefaultPowerSupplyProperties();
209 critical_usb.set_external_power(
210 power_manager::PowerSupplyProperties_ExternalPower_USB);
211 critical_usb.set_battery_percent(TrayPower::kCriticalPercentage + 0.2);
212 EXPECT_TRUE(UpdateNotificationState(critical_usb));
213 EXPECT_EQ(TrayPower::NOTIFICATION_CRITICAL, notification_state());
215 PowerSupplyProperties safe_usb = DefaultPowerSupplyProperties();
216 safe_usb.set_external_power(
217 power_manager::PowerSupplyProperties_ExternalPower_USB);
218 safe_usb.set_battery_percent(TrayPower::kNoWarningPercentage - 0.1);
219 EXPECT_FALSE(UpdateNotificationState(safe_usb));
220 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
222 // A notification shouldn't be shown when we're in the full state with an
223 // original Spring charger connected: http://crbug.com/338376
224 PowerSupplyProperties spring = DefaultPowerSupplyProperties();
225 spring.set_external_power(power_manager::
226 PowerSupplyProperties_ExternalPower_ORIGINAL_SPRING_CHARGER);
227 spring.set_battery_state(
228 power_manager::PowerSupplyProperties_BatteryState_FULL);
229 spring.set_battery_time_to_empty_sec(0);
230 spring.set_battery_time_to_full_sec(0);
231 EXPECT_FALSE(UpdateNotificationState(spring));
232 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
235 } // namespace internal