power_notification_controller_unittest.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. // Copyright 2018 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. #include "ash/system/power/power_notification_controller.h"
  5. #include <map>
  6. #include <memory>
  7. #include <string>
  8. #include "ash/test/ash_test_base.h"
  9. #include "base/logging.h"
  10. #include "base/strings/utf_string_conversions.h"
  11. #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
  12. #include "ui/message_center/fake_message_center.h"
  13. using message_center::Notification;
  14. using power_manager::PowerSupplyProperties;
  15. namespace {
  16. class MockMessageCenter : public message_center::FakeMessageCenter {
  17. public:
  18. MockMessageCenter() : add_count_(0), remove_count_(0), update_count_(0) {}
  19. MockMessageCenter(const MockMessageCenter&) = delete;
  20. MockMessageCenter& operator=(const MockMessageCenter&) = delete;
  21. ~MockMessageCenter() override = default;
  22. int add_count() const { return add_count_; }
  23. int remove_count() const { return remove_count_; }
  24. int update_count() const { return update_count_; }
  25. // message_center::FakeMessageCenter overrides:
  26. void AddNotification(std::unique_ptr<Notification> notification) override {
  27. add_count_++;
  28. notifications_.insert(
  29. std::make_pair(notification->id(), std::move(notification)));
  30. }
  31. void RemoveNotification(const std::string& id, bool by_user) override {
  32. Notification* notification = FindVisibleNotificationById(id);
  33. if (notification && notification->delegate())
  34. notification->delegate()->Close(by_user);
  35. remove_count_++;
  36. notifications_.erase(id);
  37. }
  38. void UpdateNotification(
  39. const std::string& id,
  40. std::unique_ptr<Notification> new_notification) override {
  41. update_count_++;
  42. Notification* notification = FindVisibleNotificationById(id);
  43. if (notification)
  44. notifications_.erase(id);
  45. notifications_.insert(
  46. std::make_pair(new_notification->id(), std::move(new_notification)));
  47. }
  48. Notification* FindVisibleNotificationById(const std::string& id) override {
  49. auto it = notifications_.find(id);
  50. return it == notifications_.end() ? NULL : it->second.get();
  51. }
  52. private:
  53. int add_count_;
  54. int remove_count_;
  55. int update_count_;
  56. std::map<std::string, std::unique_ptr<Notification>> notifications_;
  57. };
  58. } // namespace
  59. namespace ash {
  60. class PowerNotificationControllerTest : public AshTestBase {
  61. public:
  62. PowerNotificationControllerTest() = default;
  63. PowerNotificationControllerTest(const PowerNotificationControllerTest&) =
  64. delete;
  65. PowerNotificationControllerTest& operator=(
  66. const PowerNotificationControllerTest&) = delete;
  67. ~PowerNotificationControllerTest() override = default;
  68. MockMessageCenter* message_center() { return message_center_.get(); }
  69. PowerNotificationController* controller() { return controller_.get(); }
  70. // AshTestBase:
  71. void SetUp() override {
  72. AshTestBase::SetUp();
  73. message_center_ = std::make_unique<MockMessageCenter>();
  74. controller_ =
  75. std::make_unique<PowerNotificationController>(message_center_.get());
  76. }
  77. void TearDown() override {
  78. controller_.reset();
  79. message_center_.reset();
  80. AshTestBase::TearDown();
  81. }
  82. PowerNotificationController::NotificationState notification_state() const {
  83. return controller_->notification_state_;
  84. }
  85. bool MaybeShowUsbChargerNotification(const PowerSupplyProperties& proto) {
  86. PowerStatus::Get()->SetProtoForTesting(proto);
  87. return controller_->MaybeShowUsbChargerNotification();
  88. }
  89. void MaybeShowDualRoleNotification(const PowerSupplyProperties& proto) {
  90. PowerStatus::Get()->SetProtoForTesting(proto);
  91. controller_->MaybeShowDualRoleNotification();
  92. }
  93. void UpdateNotificationState(
  94. const PowerSupplyProperties& proto,
  95. PowerNotificationController::NotificationState expected_state,
  96. bool expected_add,
  97. bool expected_remove) {
  98. int prev_add = message_center_->add_count();
  99. int prev_remove = message_center_->remove_count();
  100. PowerStatus::Get()->SetProtoForTesting(proto);
  101. controller_->OnPowerStatusChanged();
  102. EXPECT_EQ(expected_state, notification_state());
  103. EXPECT_EQ(expected_add, message_center_->add_count() == prev_add + 1);
  104. EXPECT_EQ(expected_remove,
  105. message_center_->remove_count() == prev_remove + 1);
  106. }
  107. void SetUsbChargerWasConnected(bool connected) {
  108. controller_->usb_charger_was_connected_ = connected;
  109. }
  110. void SetBatteryWasFull(bool full) { controller_->battery_was_full_ = full; }
  111. // Returns a discharging PowerSupplyProperties more appropriate for testing.
  112. static PowerSupplyProperties DefaultPowerSupplyProperties() {
  113. PowerSupplyProperties proto;
  114. proto.set_external_power(
  115. power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED);
  116. proto.set_battery_state(
  117. power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
  118. proto.set_battery_percent(50.0);
  119. proto.set_battery_time_to_empty_sec(3 * 60 * 60);
  120. proto.set_battery_time_to_full_sec(2 * 60 * 60);
  121. proto.set_is_calculating_battery_time(false);
  122. return proto;
  123. }
  124. private:
  125. std::unique_ptr<MockMessageCenter> message_center_;
  126. std::unique_ptr<PowerNotificationController> controller_;
  127. };
  128. TEST_F(PowerNotificationControllerTest, MaybeShowUsbChargerNotification) {
  129. PowerSupplyProperties discharging = DefaultPowerSupplyProperties();
  130. EXPECT_FALSE(MaybeShowUsbChargerNotification(discharging));
  131. EXPECT_EQ(0, message_center()->add_count());
  132. EXPECT_EQ(0, message_center()->remove_count());
  133. // Notification shows when connecting a USB charger.
  134. PowerSupplyProperties usb_connected = DefaultPowerSupplyProperties();
  135. usb_connected.set_external_power(
  136. power_manager::PowerSupplyProperties_ExternalPower_USB);
  137. EXPECT_TRUE(MaybeShowUsbChargerNotification(usb_connected));
  138. EXPECT_EQ(1, message_center()->add_count());
  139. EXPECT_EQ(0, message_center()->remove_count());
  140. SetUsbChargerWasConnected(true);
  141. // Change in charge does not trigger the notification again.
  142. PowerSupplyProperties more_charge = DefaultPowerSupplyProperties();
  143. more_charge.set_external_power(
  144. power_manager::PowerSupplyProperties_ExternalPower_USB);
  145. more_charge.set_battery_time_to_full_sec(60 * 60);
  146. more_charge.set_battery_percent(75.0);
  147. EXPECT_FALSE(MaybeShowUsbChargerNotification(more_charge));
  148. EXPECT_EQ(1, message_center()->add_count());
  149. EXPECT_EQ(0, message_center()->remove_count());
  150. // Disconnecting a USB charger with the notification showing should close
  151. // the notification.
  152. EXPECT_TRUE(MaybeShowUsbChargerNotification(discharging));
  153. EXPECT_EQ(1, message_center()->add_count());
  154. EXPECT_EQ(1, message_center()->remove_count());
  155. SetUsbChargerWasConnected(false);
  156. // Notification shows when connecting a USB charger again.
  157. EXPECT_TRUE(MaybeShowUsbChargerNotification(usb_connected));
  158. EXPECT_EQ(2, message_center()->add_count());
  159. EXPECT_EQ(1, message_center()->remove_count());
  160. SetUsbChargerWasConnected(true);
  161. // Notification hides when external power switches to AC.
  162. PowerSupplyProperties ac_charger = DefaultPowerSupplyProperties();
  163. ac_charger.set_external_power(
  164. power_manager::PowerSupplyProperties_ExternalPower_AC);
  165. EXPECT_TRUE(MaybeShowUsbChargerNotification(ac_charger));
  166. EXPECT_EQ(2, message_center()->add_count());
  167. EXPECT_EQ(2, message_center()->remove_count());
  168. SetUsbChargerWasConnected(false);
  169. // Notification shows when external power switches back to USB.
  170. EXPECT_TRUE(MaybeShowUsbChargerNotification(usb_connected));
  171. EXPECT_EQ(3, message_center()->add_count());
  172. EXPECT_EQ(2, message_center()->remove_count());
  173. SetUsbChargerWasConnected(true);
  174. // Notification does not re-appear after being manually dismissed if
  175. // power supply flickers between AC and USB charger.
  176. message_center()->RemoveNotification(
  177. PowerNotificationController::kUsbNotificationId, true);
  178. EXPECT_EQ(3, message_center()->remove_count());
  179. EXPECT_TRUE(MaybeShowUsbChargerNotification(ac_charger));
  180. SetUsbChargerWasConnected(false);
  181. EXPECT_FALSE(MaybeShowUsbChargerNotification(usb_connected));
  182. EXPECT_EQ(3, message_center()->add_count());
  183. SetUsbChargerWasConnected(true);
  184. // Notification appears again after being manually dismissed if the charger
  185. // is removed, and then a USB charger is attached.
  186. MaybeShowUsbChargerNotification(discharging);
  187. EXPECT_EQ(3, message_center()->add_count());
  188. SetUsbChargerWasConnected(false);
  189. MaybeShowUsbChargerNotification(usb_connected);
  190. EXPECT_EQ(4, message_center()->add_count());
  191. SetUsbChargerWasConnected(true);
  192. }
  193. TEST_F(PowerNotificationControllerTest,
  194. AvoidUsbChargerNotificationWhenBatteryFull) {
  195. PowerSupplyProperties full_proto;
  196. full_proto.set_external_power(
  197. power_manager::PowerSupplyProperties_ExternalPower_USB);
  198. full_proto.set_battery_state(
  199. power_manager::PowerSupplyProperties_BatteryState_FULL);
  200. full_proto.set_battery_percent(100.0);
  201. full_proto.set_is_calculating_battery_time(false);
  202. PowerSupplyProperties not_full_proto;
  203. not_full_proto.set_external_power(
  204. power_manager::PowerSupplyProperties_ExternalPower_USB);
  205. not_full_proto.set_battery_state(
  206. power_manager::PowerSupplyProperties_BatteryState_CHARGING);
  207. full_proto.set_battery_percent(90.0);
  208. full_proto.set_is_calculating_battery_time(false);
  209. // When the battery is reported as full, a notification shouldn't be displayed
  210. // for a low-power charger: http://b/64913617
  211. SetUsbChargerWasConnected(false);
  212. SetBatteryWasFull(false);
  213. EXPECT_FALSE(MaybeShowUsbChargerNotification(full_proto));
  214. EXPECT_EQ(0, message_center()->add_count());
  215. EXPECT_EQ(0, message_center()->remove_count());
  216. // The notification should be displayed if the battery isn't full, though.
  217. SetUsbChargerWasConnected(false);
  218. SetBatteryWasFull(false);
  219. EXPECT_TRUE(MaybeShowUsbChargerNotification(not_full_proto));
  220. EXPECT_EQ(1, message_center()->add_count());
  221. EXPECT_EQ(0, message_center()->remove_count());
  222. // It should be dismissed if the battery becomes full again while the charger
  223. // is still connected.
  224. SetUsbChargerWasConnected(true);
  225. SetBatteryWasFull(false);
  226. EXPECT_TRUE(MaybeShowUsbChargerNotification(full_proto));
  227. EXPECT_EQ(1, message_center()->add_count());
  228. EXPECT_EQ(1, message_center()->remove_count());
  229. }
  230. TEST_F(PowerNotificationControllerTest,
  231. MaybeShowUsbChargerNotification_NoBattery) {
  232. // Notification does not show when powered by AC (including high-power
  233. // USB PD.
  234. PowerSupplyProperties ac_connected = DefaultPowerSupplyProperties();
  235. ac_connected.set_external_power(
  236. power_manager::PowerSupplyProperties_ExternalPower_AC);
  237. ac_connected.set_battery_state(
  238. power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT);
  239. ac_connected.set_preferred_minimum_external_power(60.0);
  240. EXPECT_FALSE(MaybeShowUsbChargerNotification(ac_connected));
  241. EXPECT_EQ(0, message_center()->add_count());
  242. EXPECT_EQ(0, message_center()->remove_count());
  243. // Notification shows when powered by low-power USB.
  244. PowerSupplyProperties usb_connected = DefaultPowerSupplyProperties();
  245. usb_connected.set_external_power(
  246. power_manager::PowerSupplyProperties_ExternalPower_USB);
  247. usb_connected.set_battery_state(
  248. power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT);
  249. usb_connected.set_preferred_minimum_external_power(60.0);
  250. EXPECT_TRUE(MaybeShowUsbChargerNotification(usb_connected));
  251. EXPECT_EQ(1, message_center()->add_count());
  252. EXPECT_EQ(0, message_center()->remove_count());
  253. auto* notification =
  254. message_center()->FindVisibleNotificationById("usb-charger");
  255. ASSERT_TRUE(notification);
  256. EXPECT_TRUE(notification->never_timeout());
  257. EXPECT_FALSE(notification->pinned());
  258. EXPECT_NE(std::string::npos, notification->message().find(u"60W"))
  259. << notification->message();
  260. }
  261. TEST_F(PowerNotificationControllerTest, MaybeShowDualRoleNotification) {
  262. PowerSupplyProperties discharging = DefaultPowerSupplyProperties();
  263. discharging.set_supports_dual_role_devices(true);
  264. MaybeShowDualRoleNotification(discharging);
  265. EXPECT_EQ(0, message_center()->add_count());
  266. EXPECT_EQ(0, message_center()->update_count());
  267. EXPECT_EQ(0, message_center()->remove_count());
  268. // Notification shows when connecting a dual-role device.
  269. PowerSupplyProperties dual_role = DefaultPowerSupplyProperties();
  270. dual_role.set_supports_dual_role_devices(true);
  271. power_manager::PowerSupplyProperties_PowerSource* source =
  272. dual_role.add_available_external_power_source();
  273. source->set_id("dual-role1");
  274. source->set_active_by_default(false);
  275. MaybeShowDualRoleNotification(dual_role);
  276. EXPECT_EQ(1, message_center()->add_count());
  277. EXPECT_EQ(0, message_center()->update_count());
  278. EXPECT_EQ(0, message_center()->remove_count());
  279. // Connecting another dual-role device updates the notification to be plural.
  280. source = dual_role.add_available_external_power_source();
  281. source->set_id("dual-role2");
  282. source->set_active_by_default(false);
  283. MaybeShowDualRoleNotification(dual_role);
  284. EXPECT_EQ(1, message_center()->add_count());
  285. EXPECT_EQ(1, message_center()->update_count());
  286. EXPECT_EQ(0, message_center()->remove_count());
  287. // Connecting a 3rd dual-role device doesn't affect the notification.
  288. source = dual_role.add_available_external_power_source();
  289. source->set_id("dual-role3");
  290. source->set_active_by_default(false);
  291. MaybeShowDualRoleNotification(dual_role);
  292. EXPECT_EQ(1, message_center()->add_count());
  293. EXPECT_EQ(1, message_center()->update_count());
  294. EXPECT_EQ(0, message_center()->remove_count());
  295. // Connecting a legacy USB device removes the notification.
  296. PowerSupplyProperties legacy(dual_role);
  297. power_manager::PowerSupplyProperties_PowerSource* legacy_source =
  298. legacy.add_available_external_power_source();
  299. legacy_source->set_id("legacy");
  300. legacy_source->set_active_by_default(true);
  301. legacy.set_external_power_source_id("legacy");
  302. legacy.set_external_power(
  303. power_manager::PowerSupplyProperties_ExternalPower_USB);
  304. MaybeShowDualRoleNotification(legacy);
  305. EXPECT_EQ(1, message_center()->add_count());
  306. EXPECT_EQ(1, message_center()->update_count());
  307. EXPECT_EQ(1, message_center()->remove_count());
  308. // Removing the legacy USB device adds the notification again.
  309. MaybeShowDualRoleNotification(dual_role);
  310. EXPECT_EQ(2, message_center()->add_count());
  311. EXPECT_EQ(1, message_center()->update_count());
  312. EXPECT_EQ(1, message_center()->remove_count());
  313. // Charging from the device updates the notification.
  314. dual_role.set_external_power_source_id("dual-role1");
  315. dual_role.set_external_power(
  316. power_manager::PowerSupplyProperties_ExternalPower_USB);
  317. MaybeShowDualRoleNotification(dual_role);
  318. EXPECT_EQ(2, message_center()->add_count());
  319. EXPECT_EQ(2, message_center()->update_count());
  320. EXPECT_EQ(1, message_center()->remove_count());
  321. // Adding a device as a sink doesn't change the notification, because the
  322. // notification exposes the source.
  323. source = dual_role.add_available_external_power_source();
  324. source->set_active_by_default(false);
  325. MaybeShowDualRoleNotification(dual_role);
  326. EXPECT_EQ(2, message_center()->add_count());
  327. EXPECT_EQ(2, message_center()->update_count());
  328. EXPECT_EQ(1, message_center()->remove_count());
  329. // Changing the source to a sink changes the notification.
  330. dual_role.set_external_power_source_id("");
  331. dual_role.set_external_power(
  332. power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED);
  333. MaybeShowDualRoleNotification(dual_role);
  334. EXPECT_EQ(2, message_center()->add_count());
  335. EXPECT_EQ(3, message_center()->update_count());
  336. EXPECT_EQ(1, message_center()->remove_count());
  337. // An unrelated change has no effect.
  338. dual_role.set_battery_time_to_empty_sec(2 * 60 * 60);
  339. MaybeShowDualRoleNotification(dual_role);
  340. EXPECT_EQ(2, message_center()->add_count());
  341. EXPECT_EQ(3, message_center()->update_count());
  342. EXPECT_EQ(1, message_center()->remove_count());
  343. // Removing devices hides the notification.
  344. MaybeShowDualRoleNotification(discharging);
  345. EXPECT_EQ(2, message_center()->add_count());
  346. EXPECT_EQ(3, message_center()->update_count());
  347. EXPECT_EQ(2, message_center()->remove_count());
  348. }
  349. TEST_F(PowerNotificationControllerTest, UpdateNotificationState) {
  350. // No notifications when no battery present.
  351. PowerSupplyProperties no_battery = DefaultPowerSupplyProperties();
  352. no_battery.set_external_power(
  353. power_manager::PowerSupplyProperties_ExternalPower_AC);
  354. no_battery.set_battery_state(
  355. power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT);
  356. {
  357. SCOPED_TRACE("No notifications when no battery present");
  358. UpdateNotificationState(no_battery,
  359. PowerNotificationController::NOTIFICATION_NONE,
  360. false, false);
  361. }
  362. // No notification when calculating remaining battery time.
  363. PowerSupplyProperties calculating = DefaultPowerSupplyProperties();
  364. calculating.set_is_calculating_battery_time(true);
  365. {
  366. SCOPED_TRACE("No notification when calculating remaining battery time");
  367. UpdateNotificationState(calculating,
  368. PowerNotificationController::NOTIFICATION_NONE,
  369. false, false);
  370. }
  371. // No notification when charging.
  372. PowerSupplyProperties charging = DefaultPowerSupplyProperties();
  373. charging.set_external_power(
  374. power_manager::PowerSupplyProperties_ExternalPower_AC);
  375. charging.set_battery_state(
  376. power_manager::PowerSupplyProperties_BatteryState_CHARGING);
  377. {
  378. SCOPED_TRACE("No notification when charging");
  379. UpdateNotificationState(
  380. charging, PowerNotificationController::NOTIFICATION_NONE, false, false);
  381. }
  382. // When the rounded minutes-to-empty are above the threshold, no notification
  383. // should be shown.
  384. PowerSupplyProperties low = DefaultPowerSupplyProperties();
  385. low.set_battery_time_to_empty_sec(
  386. PowerNotificationController::kLowPowerMinutes * 60 + 30);
  387. {
  388. SCOPED_TRACE("No notification when time to empty above threshold");
  389. UpdateNotificationState(low, PowerNotificationController::NOTIFICATION_NONE,
  390. false, false);
  391. }
  392. // When the rounded value matches the threshold, the notification should
  393. // appear.
  394. low.set_battery_time_to_empty_sec(
  395. PowerNotificationController::kLowPowerMinutes * 60 + 29);
  396. {
  397. SCOPED_TRACE("Notification when time to empty matches threshold");
  398. UpdateNotificationState(
  399. low, PowerNotificationController::NOTIFICATION_LOW_POWER, true, false);
  400. }
  401. // It should persist at lower values.
  402. low.set_battery_time_to_empty_sec(
  403. PowerNotificationController::kLowPowerMinutes * 60 - 20);
  404. {
  405. SCOPED_TRACE("Notification persists at lower values");
  406. UpdateNotificationState(
  407. low, PowerNotificationController::NOTIFICATION_LOW_POWER, false, false);
  408. }
  409. // The critical low battery notification should be shown when the rounded
  410. // value is at the lower threshold.
  411. PowerSupplyProperties critical = DefaultPowerSupplyProperties();
  412. critical.set_battery_time_to_empty_sec(
  413. PowerNotificationController::kCriticalMinutes * 60 + 29);
  414. {
  415. SCOPED_TRACE("Critical notification when time to empty is critical");
  416. UpdateNotificationState(critical,
  417. PowerNotificationController::NOTIFICATION_CRITICAL,
  418. true, true);
  419. }
  420. // The notification should be dismissed when the no-warning threshold is
  421. // reached.
  422. PowerSupplyProperties safe = DefaultPowerSupplyProperties();
  423. safe.set_battery_time_to_empty_sec(
  424. PowerNotificationController::kNoWarningMinutes * 60 - 29);
  425. {
  426. SCOPED_TRACE("Notification removed when battery not low");
  427. UpdateNotificationState(
  428. safe, PowerNotificationController::NOTIFICATION_NONE, false, true);
  429. }
  430. // Test that rounded percentages are used when a USB charger is connected.
  431. PowerSupplyProperties low_usb = DefaultPowerSupplyProperties();
  432. low_usb.set_external_power(
  433. power_manager::PowerSupplyProperties_ExternalPower_USB);
  434. low_usb.set_battery_percent(PowerNotificationController::kLowPowerPercentage +
  435. 0.5);
  436. {
  437. SCOPED_TRACE("No notification for rounded battery percent");
  438. UpdateNotificationState(
  439. low_usb, PowerNotificationController::NOTIFICATION_NONE, true, false);
  440. }
  441. low_usb.set_battery_percent(PowerNotificationController::kLowPowerPercentage +
  442. 0.49);
  443. {
  444. SCOPED_TRACE("Notification for rounded low power percent");
  445. UpdateNotificationState(low_usb,
  446. PowerNotificationController::NOTIFICATION_LOW_POWER,
  447. true, false);
  448. }
  449. PowerSupplyProperties critical_usb = DefaultPowerSupplyProperties();
  450. critical_usb.set_external_power(
  451. power_manager::PowerSupplyProperties_ExternalPower_USB);
  452. critical_usb.set_battery_percent(
  453. PowerNotificationController::kCriticalPercentage + 0.2);
  454. {
  455. SCOPED_TRACE("Notification for rounded critical power percent");
  456. UpdateNotificationState(critical_usb,
  457. PowerNotificationController::NOTIFICATION_CRITICAL,
  458. true, true);
  459. }
  460. PowerSupplyProperties safe_usb = DefaultPowerSupplyProperties();
  461. safe_usb.set_external_power(
  462. power_manager::PowerSupplyProperties_ExternalPower_USB);
  463. safe_usb.set_battery_percent(
  464. PowerNotificationController::kNoWarningPercentage - 0.1);
  465. {
  466. SCOPED_TRACE("Notification removed for rounded percent above threshold");
  467. UpdateNotificationState(
  468. safe_usb, PowerNotificationController::NOTIFICATION_NONE, false, true);
  469. }
  470. }
  471. // Test that a notification isn't shown if powerd sends a -1 time-to-empty value
  472. // to indicate that it couldn't produce an estimate: https://crbug.com/930358
  473. TEST_F(PowerNotificationControllerTest, IgnoreMissingBatteryEstimates) {
  474. PowerSupplyProperties proto = DefaultPowerSupplyProperties();
  475. proto.set_battery_time_to_empty_sec(-1);
  476. UpdateNotificationState(proto, PowerNotificationController::NOTIFICATION_NONE,
  477. false, false);
  478. }
  479. } // namespace ash