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);
46 class TrayPowerTest : public test::AshTestBase {
49 virtual ~TrayPowerTest() {}
51 MockMessageCenter* message_center() { return message_center_.get(); }
52 TrayPower* tray_power() { return tray_power_.get(); }
54 // test::AshTestBase::SetUp() overrides:
55 virtual void SetUp() override {
56 test::AshTestBase::SetUp();
57 message_center_.reset(new MockMessageCenter());
58 tray_power_.reset(new TrayPower(NULL, message_center_.get()));
61 virtual void TearDown() override {
63 message_center_.reset();
64 test::AshTestBase::TearDown();
67 TrayPower::NotificationState notification_state() const {
68 return tray_power_->notification_state_;
71 bool MaybeShowUsbChargerNotification(const PowerSupplyProperties& proto) {
72 PowerStatus::Get()->SetProtoForTesting(proto);
73 return tray_power_->MaybeShowUsbChargerNotification();
76 bool UpdateNotificationState(const PowerSupplyProperties& proto) {
77 PowerStatus::Get()->SetProtoForTesting(proto);
78 return tray_power_->UpdateNotificationState();
81 void SetUsbChargerConnected(bool connected) {
82 tray_power_->usb_charger_was_connected_ = connected;
85 // Returns a discharging PowerSupplyProperties more appropriate for testing.
86 static PowerSupplyProperties DefaultPowerSupplyProperties() {
87 PowerSupplyProperties proto;
88 proto.set_external_power(
89 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED);
90 proto.set_battery_state(
91 power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
92 proto.set_battery_percent(50.0);
93 proto.set_battery_time_to_empty_sec(3 * 60 * 60);
94 proto.set_battery_time_to_full_sec(2 * 60 * 60);
95 proto.set_is_calculating_battery_time(false);
100 scoped_ptr<MockMessageCenter> message_center_;
101 scoped_ptr<TrayPower> tray_power_;
103 DISALLOW_COPY_AND_ASSIGN(TrayPowerTest);
106 TEST_F(TrayPowerTest, MaybeShowUsbChargerNotification) {
107 PowerSupplyProperties discharging = DefaultPowerSupplyProperties();
108 EXPECT_FALSE(MaybeShowUsbChargerNotification(discharging));
109 EXPECT_EQ(0, message_center()->add_count());
110 EXPECT_EQ(0, message_center()->remove_count());
112 // Notification shows when connecting a USB charger.
113 PowerSupplyProperties usb_connected = DefaultPowerSupplyProperties();
114 usb_connected.set_external_power(
115 power_manager::PowerSupplyProperties_ExternalPower_USB);
116 EXPECT_TRUE(MaybeShowUsbChargerNotification(usb_connected));
117 EXPECT_EQ(1, message_center()->add_count());
118 EXPECT_EQ(0, message_center()->remove_count());
120 // Change in charge does not trigger the notification again.
121 PowerSupplyProperties more_charge = DefaultPowerSupplyProperties();
122 more_charge.set_external_power(
123 power_manager::PowerSupplyProperties_ExternalPower_USB);
124 more_charge.set_battery_time_to_full_sec(60 * 60);
125 more_charge.set_battery_percent(75.0);
126 SetUsbChargerConnected(true);
127 EXPECT_FALSE(MaybeShowUsbChargerNotification(more_charge));
128 EXPECT_EQ(1, message_center()->add_count());
129 EXPECT_EQ(0, message_center()->remove_count());
131 // Disconnecting a USB charger with the notification showing should close
133 EXPECT_TRUE(MaybeShowUsbChargerNotification(discharging));
134 EXPECT_EQ(1, message_center()->add_count());
135 EXPECT_EQ(1, message_center()->remove_count());
138 TEST_F(TrayPowerTest, UpdateNotificationState) {
139 // No notifications when no battery present.
140 PowerSupplyProperties no_battery = DefaultPowerSupplyProperties();
141 no_battery.set_external_power(
142 power_manager::PowerSupplyProperties_ExternalPower_AC);
143 no_battery.set_battery_state(
144 power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT);
145 EXPECT_FALSE(UpdateNotificationState(no_battery));
146 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
148 // No notification when calculating remaining battery time.
149 PowerSupplyProperties calculating = DefaultPowerSupplyProperties();
150 calculating.set_is_calculating_battery_time(true);
151 EXPECT_FALSE(UpdateNotificationState(calculating));
152 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
154 // No notification when charging.
155 PowerSupplyProperties charging = DefaultPowerSupplyProperties();
156 charging.set_external_power(
157 power_manager::PowerSupplyProperties_ExternalPower_AC);
158 charging.set_battery_state(
159 power_manager::PowerSupplyProperties_BatteryState_CHARGING);
160 EXPECT_FALSE(UpdateNotificationState(charging));
161 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
163 // When the rounded minutes-to-empty are above the threshold, no notification
165 PowerSupplyProperties low = DefaultPowerSupplyProperties();
166 low.set_battery_time_to_empty_sec(TrayPower::kLowPowerMinutes * 60 + 30);
167 EXPECT_FALSE(UpdateNotificationState(low));
168 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
170 // When the rounded value matches the threshold, the notification should
172 low.set_battery_time_to_empty_sec(TrayPower::kLowPowerMinutes * 60 + 29);
173 EXPECT_TRUE(UpdateNotificationState(low));
174 EXPECT_EQ(TrayPower::NOTIFICATION_LOW_POWER, notification_state());
176 // It should persist at lower values.
177 low.set_battery_time_to_empty_sec(TrayPower::kLowPowerMinutes * 60 - 20);
178 EXPECT_FALSE(UpdateNotificationState(low));
179 EXPECT_EQ(TrayPower::NOTIFICATION_LOW_POWER, notification_state());
181 // The critical low battery notification should be shown when the rounded
182 // value is at the lower threshold.
183 PowerSupplyProperties critical = DefaultPowerSupplyProperties();
184 critical.set_battery_time_to_empty_sec(TrayPower::kCriticalMinutes * 60 + 29);
185 EXPECT_TRUE(UpdateNotificationState(critical));
186 EXPECT_EQ(TrayPower::NOTIFICATION_CRITICAL, notification_state());
188 // The notification should be dismissed when the no-warning threshold is
190 PowerSupplyProperties safe = DefaultPowerSupplyProperties();
191 safe.set_battery_time_to_empty_sec(TrayPower::kNoWarningMinutes * 60 - 29);
192 EXPECT_FALSE(UpdateNotificationState(safe));
193 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
195 // Test that rounded percentages are used when a USB charger is connected.
196 PowerSupplyProperties low_usb = DefaultPowerSupplyProperties();
197 low_usb.set_external_power(
198 power_manager::PowerSupplyProperties_ExternalPower_USB);
199 low_usb.set_battery_percent(TrayPower::kLowPowerPercentage + 0.5);
200 EXPECT_FALSE(UpdateNotificationState(low_usb));
201 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
203 low_usb.set_battery_percent(TrayPower::kLowPowerPercentage + 0.49);
204 EXPECT_TRUE(UpdateNotificationState(low_usb));
205 EXPECT_EQ(TrayPower::NOTIFICATION_LOW_POWER, notification_state());
207 PowerSupplyProperties critical_usb = DefaultPowerSupplyProperties();
208 critical_usb.set_external_power(
209 power_manager::PowerSupplyProperties_ExternalPower_USB);
210 critical_usb.set_battery_percent(TrayPower::kCriticalPercentage + 0.2);
211 EXPECT_TRUE(UpdateNotificationState(critical_usb));
212 EXPECT_EQ(TrayPower::NOTIFICATION_CRITICAL, notification_state());
214 PowerSupplyProperties safe_usb = DefaultPowerSupplyProperties();
215 safe_usb.set_external_power(
216 power_manager::PowerSupplyProperties_ExternalPower_USB);
217 safe_usb.set_battery_percent(TrayPower::kNoWarningPercentage - 0.1);
218 EXPECT_FALSE(UpdateNotificationState(safe_usb));
219 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());
221 // A notification shouldn't be shown when we're in the full state with an
222 // original Spring charger connected: http://crbug.com/338376
223 PowerSupplyProperties spring = DefaultPowerSupplyProperties();
224 spring.set_external_power(power_manager::
225 PowerSupplyProperties_ExternalPower_ORIGINAL_SPRING_CHARGER);
226 spring.set_battery_state(
227 power_manager::PowerSupplyProperties_BatteryState_FULL);
228 spring.set_battery_time_to_empty_sec(0);
229 spring.set_battery_time_to_full_sec(0);
230 EXPECT_FALSE(UpdateNotificationState(spring));
231 EXPECT_EQ(TrayPower::NOTIFICATION_NONE, notification_state());