peripheral_battery_notifier_listener_integration_test.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. // Copyright 2020 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/peripheral_battery_listener.h"
  5. #include <memory>
  6. #include <string>
  7. #include "ash/constants/ash_features.h"
  8. #include "ash/shell.h"
  9. #include "ash/system/power/peripheral_battery_notifier.h"
  10. #include "ash/system/power/peripheral_battery_tests.h"
  11. #include "ash/test/ash_test_base.h"
  12. #include "base/strings/string_number_conversions.h"
  13. #include "base/strings/string_piece.h"
  14. #include "base/strings/string_util.h"
  15. #include "base/strings/utf_string_conversions.h"
  16. #include "base/test/scoped_feature_list.h"
  17. #include "base/test/task_environment.h"
  18. #include "device/bluetooth/bluetooth_adapter_factory.h"
  19. #include "device/bluetooth/bluetooth_device.h"
  20. #include "device/bluetooth/test/mock_bluetooth_adapter.h"
  21. #include "device/bluetooth/test/mock_bluetooth_device.h"
  22. #include "ui/events/devices/device_data_manager.h"
  23. #include "ui/events/devices/device_data_manager_test_api.h"
  24. #include "ui/events/devices/touchscreen_device.h"
  25. #include "ui/message_center/message_center.h"
  26. #include "ui/message_center/public/cpp/notification.h"
  27. using testing::NiceMock;
  28. using BatteryInfo = device::BluetoothDevice::BatteryInfo;
  29. using BatteryType = device::BluetoothDevice::BatteryType;
  30. namespace {
  31. const std::u16string& NotificationMessagePrefix() {
  32. static const std::u16string prefix(u"Battery low (");
  33. return prefix;
  34. }
  35. const std::u16string& NotificationMessageSuffix() {
  36. static const std::u16string suffix(u"%)");
  37. return suffix;
  38. }
  39. } // namespace
  40. namespace ash {
  41. class PeripheralBatteryNotifierListenerTest : public AshTestBase {
  42. public:
  43. // Constants for active field of PeripheralBatteryStylusReceived().
  44. const bool kBluetoothBatteryUpdate = true;
  45. const bool kBatteryPolledUpdate = false;
  46. const bool kBatteryEventUpdate = true;
  47. PeripheralBatteryNotifierListenerTest()
  48. : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
  49. PeripheralBatteryNotifierListenerTest(
  50. const PeripheralBatteryNotifierListenerTest&) = delete;
  51. PeripheralBatteryNotifierListenerTest& operator=(
  52. const PeripheralBatteryNotifierListenerTest&) = delete;
  53. ~PeripheralBatteryNotifierListenerTest() override = default;
  54. void SetUp() override {
  55. AshTestBase::SetUp();
  56. ASSERT_TRUE(ui::DeviceDataManager::HasInstance());
  57. // Simulate the complete listing of input devices, required by the listener.
  58. if (complete_devices_)
  59. ui::DeviceDataManagerTestApi().OnDeviceListsComplete();
  60. mock_adapter_ =
  61. base::MakeRefCounted<NiceMock<device::MockBluetoothAdapter>>();
  62. mock_device_1_ = std::make_unique<NiceMock<device::MockBluetoothDevice>>(
  63. mock_adapter_.get(), /*bluetooth_class=*/0, kBluetoothDeviceName1,
  64. kBluetoothDeviceAddress1, /*paired=*/true, /*connected=*/true);
  65. mock_device_2_ = std::make_unique<NiceMock<device::MockBluetoothDevice>>(
  66. mock_adapter_.get(), /*bluetooth_class=*/0, kBluetoothDeviceName2,
  67. kBluetoothDeviceAddress2, /*paired=*/true, /*connected=*/true);
  68. device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_);
  69. message_center_ = message_center::MessageCenter::Get();
  70. battery_listener_ = std::make_unique<PeripheralBatteryListener>();
  71. battery_notifier_ =
  72. std::make_unique<PeripheralBatteryNotifier>(battery_listener_.get());
  73. // No notifications should have been posted yet.
  74. ASSERT_EQ(0u, message_center_->NotificationCount());
  75. }
  76. void TearDown() override {
  77. battery_notifier_.reset();
  78. battery_listener_.reset();
  79. AshTestBase::TearDown();
  80. }
  81. void SendBatteryUpdate(const std::string& path,
  82. const std::string& name,
  83. int level) {
  84. battery_listener_->PeripheralBatteryStatusReceived(
  85. path, name, level,
  86. power_manager::
  87. PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
  88. /*serial_number=*/kStylusEligibleSerialNumbers[0],
  89. kBatteryPolledUpdate);
  90. }
  91. void SendBatteryUpdate(
  92. const std::string& path,
  93. const std::string& name,
  94. int level,
  95. power_manager::PeripheralBatteryStatus_ChargeStatus status,
  96. const std::string& serial_number,
  97. bool active_update) {
  98. battery_listener_->PeripheralBatteryStatusReceived(
  99. path, name, level, status, serial_number, active_update);
  100. }
  101. // Extracts the battery percentage from the message of a notification.
  102. uint8_t ExtractBatteryPercentage(message_center::Notification* notification) {
  103. const std::u16string& message = notification->message();
  104. EXPECT_TRUE(base::StartsWith(message, NotificationMessagePrefix(),
  105. base::CompareCase::SENSITIVE));
  106. EXPECT_TRUE(base::EndsWith(message, NotificationMessageSuffix(),
  107. base::CompareCase::SENSITIVE));
  108. int prefix_size = NotificationMessagePrefix().size();
  109. int suffix_size = NotificationMessageSuffix().size();
  110. int key_len = message.size() - prefix_size - suffix_size;
  111. EXPECT_GT(key_len, 0);
  112. int battery_percentage;
  113. EXPECT_TRUE(base::StringToInt(message.substr(prefix_size, key_len),
  114. &battery_percentage));
  115. EXPECT_GE(battery_percentage, 0);
  116. EXPECT_LE(battery_percentage, 100);
  117. return battery_percentage;
  118. }
  119. base::TimeTicks GetTestingClock() { return base::TimeTicks::Now(); }
  120. void ClockAdvance(base::TimeDelta delta) {
  121. task_environment()->AdvanceClock(delta);
  122. }
  123. protected:
  124. scoped_refptr<NiceMock<device::MockBluetoothAdapter>> mock_adapter_;
  125. std::unique_ptr<device::MockBluetoothDevice> mock_device_1_;
  126. std::unique_ptr<device::MockBluetoothDevice> mock_device_2_;
  127. message_center::MessageCenter* message_center_;
  128. std::unique_ptr<PeripheralBatteryNotifier> battery_notifier_;
  129. std::unique_ptr<PeripheralBatteryListener> battery_listener_;
  130. void set_complete_devices(bool complete_devices) {
  131. complete_devices_ = complete_devices;
  132. }
  133. // SetUp() doesn't complete devices if this is set to false.
  134. bool complete_devices_ = true;
  135. };
  136. class PeripheralBatteryNotifierListenerIncompleteDevicesTest
  137. : public PeripheralBatteryNotifierListenerTest {
  138. public:
  139. PeripheralBatteryNotifierListenerIncompleteDevicesTest() {
  140. set_complete_devices(false);
  141. }
  142. PeripheralBatteryNotifierListenerIncompleteDevicesTest(
  143. const PeripheralBatteryNotifierListenerIncompleteDevicesTest&) = delete;
  144. PeripheralBatteryNotifierListenerIncompleteDevicesTest& operator=(
  145. const PeripheralBatteryNotifierListenerIncompleteDevicesTest&) = delete;
  146. ~PeripheralBatteryNotifierListenerIncompleteDevicesTest() override {}
  147. };
  148. TEST_F(PeripheralBatteryNotifierListenerTest, Basic) {
  149. // Level 50 at time 100, no low-battery notification.
  150. ClockAdvance(base::Seconds(100));
  151. SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, 50);
  152. EXPECT_EQ(1u,
  153. battery_notifier_->battery_notifications_.count(kTestBatteryId));
  154. const PeripheralBatteryNotifier::NotificationInfo& info =
  155. battery_notifier_->battery_notifications_[kTestBatteryId];
  156. EXPECT_EQ(absl::nullopt, info.level);
  157. EXPECT_EQ(GetTestingClock(), info.last_notification_timestamp);
  158. EXPECT_FALSE(
  159. message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
  160. // Level 5 at time 110, low-battery notification.
  161. ClockAdvance(base::Seconds(10));
  162. SendBatteryUpdate(
  163. kTestBatteryPath, kTestDeviceName, 5,
  164. power_manager::
  165. PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
  166. /*serial_number=*/"", kBatteryEventUpdate);
  167. EXPECT_EQ(5, info.level);
  168. EXPECT_EQ(GetTestingClock(), info.last_notification_timestamp);
  169. EXPECT_TRUE(
  170. message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
  171. // Verify that the low-battery notification for stylus does not show up.
  172. EXPECT_FALSE(message_center_->FindVisibleNotificationById(
  173. PeripheralBatteryNotifier::kStylusNotificationId));
  174. // Level -1 at time 115, cancel previous notification
  175. ClockAdvance(base::Seconds(5));
  176. SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, -1);
  177. EXPECT_EQ(absl::nullopt, info.level);
  178. EXPECT_EQ(GetTestingClock() - base::Seconds(5),
  179. info.last_notification_timestamp);
  180. EXPECT_FALSE(
  181. message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
  182. // Level 50 at time 120, no low-battery notification.
  183. ClockAdvance(base::Seconds(5));
  184. SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, 50);
  185. EXPECT_EQ(absl::nullopt, info.level);
  186. EXPECT_EQ(GetTestingClock() - base::Seconds(10),
  187. info.last_notification_timestamp);
  188. EXPECT_FALSE(
  189. message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
  190. // Level 5 at time 130, no low-battery notification (throttling).
  191. ClockAdvance(base::Seconds(10));
  192. SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, 5);
  193. EXPECT_EQ(5, info.level);
  194. EXPECT_EQ(GetTestingClock() - base::Seconds(20),
  195. info.last_notification_timestamp);
  196. EXPECT_FALSE(
  197. message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
  198. }
  199. TEST_F(PeripheralBatteryNotifierListenerTest, InvalidBatteryInfo) {
  200. const std::string invalid_path1 = "invalid-path";
  201. const std::string invalid_path2 = "/sys/class/power_supply/hid-battery";
  202. SendBatteryUpdate(invalid_path1, kTestDeviceName, 10);
  203. EXPECT_TRUE(battery_notifier_->battery_notifications_.empty());
  204. SendBatteryUpdate(invalid_path2, kTestDeviceName, 10);
  205. EXPECT_TRUE(battery_notifier_->battery_notifications_.empty());
  206. SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, -2);
  207. EXPECT_TRUE(battery_notifier_->battery_notifications_.empty());
  208. SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, 101);
  209. EXPECT_TRUE(battery_notifier_->battery_notifications_.empty());
  210. SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, -1);
  211. EXPECT_TRUE(battery_notifier_->battery_notifications_.empty());
  212. }
  213. // Verify that for Bluetooth devices, the correct address gets stored in the
  214. // BatteryInfo's bluetooth_address member, and for non-Bluetooth devices, that
  215. // bluetooth_address member is empty.
  216. TEST_F(PeripheralBatteryNotifierListenerTest, ExtractBluetoothAddress) {
  217. const std::string bluetooth_path =
  218. "/sys/class/power_supply/hid-A0:b1:C2:d3:E4:f5-battery";
  219. const std::string expected_bluetooth_address = "a0:b1:c2:d3:e4:f5";
  220. const std::string expected_bluetooth_id =
  221. "battery_notification_bluetooth-a0:b1:c2:d3:e4:f5";
  222. const std::string non_bluetooth_path =
  223. "/sys/class/power_supply/hid-notbluetooth-battery";
  224. SendBatteryUpdate(
  225. bluetooth_path, kTestDeviceName, 10,
  226. power_manager::
  227. PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
  228. /*serial_number=*/"", kBluetoothBatteryUpdate);
  229. SendBatteryUpdate(
  230. non_bluetooth_path, kTestDeviceName, 10,
  231. power_manager::
  232. PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
  233. /*serial_number=*/"", kBatteryPolledUpdate);
  234. EXPECT_EQ(2u, battery_notifier_->battery_notifications_.size());
  235. }
  236. TEST_F(PeripheralBatteryNotifierListenerTest, DeviceRemove) {
  237. SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, 5);
  238. EXPECT_EQ(1u,
  239. battery_notifier_->battery_notifications_.count(kTestBatteryId));
  240. EXPECT_TRUE(
  241. message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
  242. battery_listener_->RemoveBluetoothBattery(kTestBatteryAddress);
  243. EXPECT_FALSE(
  244. message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
  245. }
  246. TEST_F(PeripheralBatteryNotifierListenerIncompleteDevicesTest,
  247. StylusNotification) {
  248. const std::string kTestStylusBatteryPath =
  249. "/sys/class/power_supply/hid-AAAA:BBBB:CCCC.DDDD-battery";
  250. const std::string kTestStylusName = "test_stylus";
  251. base::test::ScopedFeatureList flags;
  252. flags.InitAndEnableFeature(features::kStylusBatteryStatus);
  253. // Add an external stylus to our test device manager.
  254. ui::TouchscreenDevice stylus(/*id=*/0, ui::INPUT_DEVICE_USB, kTestStylusName,
  255. gfx::Size(),
  256. /*touch_points=*/1, /*has_stylus=*/true);
  257. stylus.sys_path = base::FilePath(kTestStylusBatteryPath);
  258. ui::DeviceDataManagerTestApi().SetTouchscreenDevices({stylus});
  259. // Verify that when the battery level is 5, a stylus low battery notification
  260. // is not shown due to input device list not being complete. Also check that
  261. // a non stylus device low battery notification will not show up.
  262. SendBatteryUpdate(
  263. kTestStylusBatteryPath, kTestStylusName, 5,
  264. power_manager::
  265. PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
  266. kStylusEligibleSerialNumbers[0], kBatteryEventUpdate);
  267. EXPECT_FALSE(message_center_->FindVisibleNotificationById(
  268. PeripheralBatteryNotifier::kStylusNotificationId));
  269. EXPECT_FALSE(
  270. message_center_->FindVisibleNotificationById(kTestBatteryAddress));
  271. // Complete devices
  272. ui::DeviceDataManagerTestApi().OnDeviceListsComplete();
  273. // Verify that when the battery level is 5, a stylus low battery notification
  274. // is now shown. Also check that a non stylus device low battery notification
  275. // will still not show up.
  276. SendBatteryUpdate(
  277. kTestStylusBatteryPath, kTestStylusName, 5,
  278. power_manager::
  279. PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
  280. kStylusEligibleSerialNumbers[0], kBatteryEventUpdate);
  281. EXPECT_TRUE(message_center_->FindVisibleNotificationById(
  282. PeripheralBatteryNotifier::kStylusNotificationId));
  283. EXPECT_FALSE(
  284. message_center_->FindVisibleNotificationById(kTestBatteryAddress));
  285. }
  286. TEST_F(PeripheralBatteryNotifierListenerIncompleteDevicesTest,
  287. StylusNotificationDisabled) {
  288. const std::string kTestStylusBatteryPath =
  289. "/sys/class/power_supply/hid-AAAA:BBBB:CCCC.DDDD-battery";
  290. const std::string kTestStylusName = "test_stylus";
  291. base::test::ScopedFeatureList flags;
  292. flags.InitAndDisableFeature(features::kStylusBatteryStatus);
  293. // Add an external stylus to our test device manager.
  294. ui::TouchscreenDevice stylus(/*id=*/0, ui::INPUT_DEVICE_USB, kTestStylusName,
  295. gfx::Size(),
  296. /*touch_points=*/1, /*has_stylus=*/true);
  297. stylus.sys_path = base::FilePath(kTestStylusBatteryPath);
  298. ui::DeviceDataManagerTestApi().SetTouchscreenDevices({stylus});
  299. // Verify that when the battery level is 5, a stylus low battery notification
  300. // is not shown due to input device list not being complete. Also check that
  301. // a non stylus device low battery notification will not show up.
  302. SendBatteryUpdate(
  303. kTestStylusBatteryPath, kTestStylusName, 5,
  304. power_manager::
  305. PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
  306. /*serial_number=*/"", kBatteryEventUpdate);
  307. EXPECT_FALSE(message_center_->FindVisibleNotificationById(
  308. PeripheralBatteryNotifier::kStylusNotificationId));
  309. EXPECT_FALSE(
  310. message_center_->FindVisibleNotificationById(kTestBatteryAddress));
  311. // Complete devices
  312. ui::DeviceDataManagerTestApi().OnDeviceListsComplete();
  313. // Verify that when the battery level is 5, a stylus low battery notification
  314. // is now shown. Also check that a non stylus device low battery notification
  315. // will still not show up.
  316. SendBatteryUpdate(
  317. kTestStylusBatteryPath, kTestStylusName, 5,
  318. power_manager::
  319. PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
  320. /*serial_number=*/"", kBatteryEventUpdate);
  321. EXPECT_FALSE(message_center_->FindVisibleNotificationById(
  322. PeripheralBatteryNotifier::kStylusNotificationId));
  323. EXPECT_FALSE(
  324. message_center_->FindVisibleNotificationById(kTestBatteryAddress));
  325. }
  326. TEST_F(PeripheralBatteryNotifierListenerTest, StylusNotification) {
  327. const std::string kTestStylusBatteryPath =
  328. "/sys/class/power_supply/hid-AAAA:BBBB:CCCC.DDDD-battery";
  329. const std::string kTestStylusName = "test_stylus";
  330. base::test::ScopedFeatureList flags;
  331. flags.InitAndEnableFeature(features::kStylusBatteryStatus);
  332. // Add an external stylus to our test device manager.
  333. ui::TouchscreenDevice stylus(/*id=*/0, ui::INPUT_DEVICE_USB, kTestStylusName,
  334. gfx::Size(),
  335. /*touch_points=*/1, /*has_stylus=*/true);
  336. stylus.sys_path = base::FilePath(kTestStylusBatteryPath);
  337. ui::DeviceDataManagerTestApi().SetTouchscreenDevices({stylus});
  338. // Verify that when the battery level is 50, no stylus low battery
  339. // notification is shown.
  340. SendBatteryUpdate(kTestStylusBatteryPath, kTestStylusName, 50);
  341. EXPECT_FALSE(message_center_->FindVisibleNotificationById(
  342. PeripheralBatteryNotifier::kStylusNotificationId));
  343. // Verify that when the battery level is 5, a stylus low battery notification
  344. // is shown. Also check that a non stylus device low battery notification will
  345. // not show up.
  346. SendBatteryUpdate(
  347. kTestStylusBatteryPath, kTestStylusName, 5,
  348. power_manager::
  349. PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
  350. kStylusEligibleSerialNumbers[0], kBatteryPolledUpdate);
  351. EXPECT_TRUE(message_center_->FindVisibleNotificationById(
  352. PeripheralBatteryNotifier::kStylusNotificationId));
  353. EXPECT_FALSE(
  354. message_center_->FindVisibleNotificationById(kTestBatteryAddress));
  355. // Verify that when the battery level is -1, the previous stylus low battery
  356. // notification is cancelled.
  357. SendBatteryUpdate(
  358. kTestStylusBatteryPath, kTestStylusName, -1,
  359. power_manager::
  360. PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
  361. kStylusEligibleSerialNumbers[0], kBatteryPolledUpdate);
  362. EXPECT_FALSE(message_center_->FindVisibleNotificationById(
  363. PeripheralBatteryNotifier::kStylusNotificationId));
  364. }
  365. TEST_F(PeripheralBatteryNotifierListenerTest, StylusNotificationDisabled) {
  366. const std::string kTestStylusBatteryPath =
  367. "/sys/class/power_supply/hid-AAAA:BBBB:CCCC.DDDD-battery";
  368. const std::string kTestStylusName = "test_stylus";
  369. base::test::ScopedFeatureList flags;
  370. flags.InitAndDisableFeature(features::kStylusBatteryStatus);
  371. // Add an external stylus to our test device manager.
  372. ui::TouchscreenDevice stylus(/*id=*/0, ui::INPUT_DEVICE_USB, kTestStylusName,
  373. gfx::Size(),
  374. /*touch_points=*/1, /*has_stylus=*/true);
  375. stylus.sys_path = base::FilePath(kTestStylusBatteryPath);
  376. ui::DeviceDataManagerTestApi().SetTouchscreenDevices({stylus});
  377. // Verify that when the battery level is 50, no stylus low battery
  378. // notification is shown.
  379. SendBatteryUpdate(kTestStylusBatteryPath, kTestStylusName, 50);
  380. EXPECT_FALSE(message_center_->FindVisibleNotificationById(
  381. PeripheralBatteryNotifier::kStylusNotificationId));
  382. // Verify that when the battery level is 5, a stylus low battery notification
  383. // is shown. Also check that a non stylus device low battery notification will
  384. // not show up.
  385. SendBatteryUpdate(kTestStylusBatteryPath, kTestStylusName, 5);
  386. EXPECT_FALSE(message_center_->FindVisibleNotificationById(
  387. PeripheralBatteryNotifier::kStylusNotificationId));
  388. EXPECT_FALSE(
  389. message_center_->FindVisibleNotificationById(kTestBatteryAddress));
  390. // Verify that when the battery level is -1, the previous stylus low battery
  391. // notification is cancelled.
  392. SendBatteryUpdate(kTestStylusBatteryPath, kTestStylusName, -1);
  393. EXPECT_FALSE(message_center_->FindVisibleNotificationById(
  394. PeripheralBatteryNotifier::kStylusNotificationId));
  395. }
  396. TEST_F(PeripheralBatteryNotifierListenerTest,
  397. Bluetooth_OnlyShowNotificationForLowBatteryLevels) {
  398. // Should not create a notification for battery changes above the threshold.
  399. mock_device_1_->SetBatteryInfo(
  400. BatteryInfo(BatteryType::kDefault, /*percentage=*/80));
  401. EXPECT_EQ(0u, message_center_->NotificationCount());
  402. mock_device_1_->SetBatteryInfo(
  403. BatteryInfo(BatteryType::kDefault, /*percentage=*/100));
  404. EXPECT_EQ(0u, message_center_->NotificationCount());
  405. // Should trigger notification.
  406. mock_device_1_->SetBatteryInfo(
  407. BatteryInfo(BatteryType::kDefault, /*percentage=*/10));
  408. EXPECT_EQ(1u, message_center_->NotificationCount());
  409. message_center::Notification* notification =
  410. message_center_->FindVisibleNotificationById(
  411. kBluetoothDeviceNotificationId1);
  412. EXPECT_EQ(mock_device_1_->GetNameForDisplay(), notification->title());
  413. EXPECT_EQ(10, ExtractBatteryPercentage(notification));
  414. }
  415. TEST_F(PeripheralBatteryNotifierListenerTest,
  416. Bluetooth_CreatesANotificationForEachDevice) {
  417. mock_device_1_->SetBatteryInfo(
  418. BatteryInfo(BatteryType::kDefault, /*percentage=*/5));
  419. mock_device_2_->SetBatteryInfo(
  420. BatteryInfo(BatteryType::kDefault, /*percentage=*/0));
  421. // Verify 2 notifications were posted with the correct values.
  422. EXPECT_EQ(2u, message_center_->NotificationCount());
  423. message_center::Notification* notification_1 =
  424. message_center_->FindVisibleNotificationById(
  425. kBluetoothDeviceNotificationId1);
  426. message_center::Notification* notification_2 =
  427. message_center_->FindVisibleNotificationById(
  428. kBluetoothDeviceNotificationId2);
  429. EXPECT_TRUE(notification_1);
  430. EXPECT_EQ(mock_device_1_->GetNameForDisplay(), notification_1->title());
  431. EXPECT_EQ(5, ExtractBatteryPercentage(notification_1));
  432. EXPECT_TRUE(notification_2);
  433. EXPECT_EQ(mock_device_2_->GetNameForDisplay(), notification_2->title());
  434. EXPECT_EQ(0, ExtractBatteryPercentage(notification_2));
  435. }
  436. TEST_F(PeripheralBatteryNotifierListenerTest,
  437. Bluetooth_RemovesNotificationForDisconnectedDevices) {
  438. mock_device_1_->SetBatteryInfo(
  439. BatteryInfo(BatteryType::kDefault, /*percentage=*/5));
  440. mock_device_2_->SetBatteryInfo(
  441. BatteryInfo(BatteryType::kDefault, /*percentage=*/0));
  442. // Verify 2 notifications were posted.
  443. EXPECT_EQ(2u, message_center_->NotificationCount());
  444. // Verify only the notification for device 1 gets removed.
  445. battery_listener_->DeviceConnectedStateChanged(mock_adapter_.get(),
  446. mock_device_1_.get(), false);
  447. EXPECT_EQ(1u, message_center_->NotificationCount());
  448. EXPECT_TRUE(message_center_->FindVisibleNotificationById(
  449. kBluetoothDeviceNotificationId2));
  450. // Remove the second notification.
  451. battery_listener_->DeviceRemoved(mock_adapter_.get(), mock_device_2_.get());
  452. EXPECT_EQ(0u, message_center_->NotificationCount());
  453. }
  454. TEST_F(PeripheralBatteryNotifierListenerTest,
  455. Bluetooth_CancelNotificationForInvalidBatteryLevel) {
  456. mock_device_1_->SetBatteryInfo(
  457. BatteryInfo(BatteryType::kDefault, /*percentage=*/1));
  458. EXPECT_TRUE(message_center_->FindVisibleNotificationById(
  459. kBluetoothDeviceNotificationId1));
  460. // The notification should get canceled.
  461. mock_device_1_->RemoveBatteryInfo(BatteryType::kDefault);
  462. EXPECT_FALSE(message_center_->FindVisibleNotificationById(
  463. kBluetoothDeviceNotificationId1));
  464. }
  465. // Don't post a notification if the battery level drops again under the
  466. // threshold before kNotificationInterval is completed.
  467. TEST_F(PeripheralBatteryNotifierListenerTest,
  468. DontShowSecondNotificationWithinASmallTimeInterval) {
  469. ClockAdvance(base::Seconds(100));
  470. // Post a notification.
  471. mock_device_1_->SetBatteryInfo(
  472. BatteryInfo(BatteryType::kDefault, /*percentage=*/1));
  473. EXPECT_TRUE(message_center_->FindVisibleNotificationById(
  474. kBluetoothDeviceNotificationId1));
  475. // Cancel the notification.
  476. ClockAdvance(base::Seconds(1));
  477. mock_device_1_->RemoveBatteryInfo(BatteryType::kDefault);
  478. EXPECT_FALSE(message_center_->FindVisibleNotificationById(
  479. kBluetoothDeviceNotificationId1));
  480. // The battery level falls below the threshold after a short time period. No
  481. // notification should get posted.
  482. ClockAdvance(base::Seconds(1));
  483. mock_device_1_->SetBatteryInfo(
  484. BatteryInfo(BatteryType::kDefault, /*percentage=*/1));
  485. EXPECT_FALSE(message_center_->FindVisibleNotificationById(
  486. kBluetoothDeviceNotificationId1));
  487. }
  488. // Post a notification if the battery is under threshold, then unknown level and
  489. // then is again under the threshold after kNotificationInterval is completed.
  490. TEST_F(PeripheralBatteryNotifierListenerTest,
  491. PostNotificationIfBatteryGoesFromUnknownLevelToBelowThreshold) {
  492. ClockAdvance(base::Seconds(100));
  493. // Post a notification.
  494. mock_device_1_->SetBatteryInfo(
  495. BatteryInfo(BatteryType::kDefault, /*percentage=*/1));
  496. EXPECT_TRUE(message_center_->FindVisibleNotificationById(
  497. kBluetoothDeviceNotificationId1));
  498. // Cancel the notification.
  499. ClockAdvance(base::Seconds(1));
  500. mock_device_1_->RemoveBatteryInfo(BatteryType::kDefault);
  501. EXPECT_FALSE(message_center_->FindVisibleNotificationById(
  502. kBluetoothDeviceNotificationId1));
  503. // Post notification if we are out of the kNotificationInterval.
  504. ClockAdvance(base::Seconds(100));
  505. mock_device_1_->SetBatteryInfo(
  506. BatteryInfo(BatteryType::kDefault, /*percentage=*/1));
  507. EXPECT_TRUE(message_center_->FindVisibleNotificationById(
  508. kBluetoothDeviceNotificationId1));
  509. }
  510. // Don't Post another notification if the battery level keeps low and the user
  511. // dismissed the previous notification.
  512. TEST_F(PeripheralBatteryNotifierListenerTest,
  513. DontRepostNotificationIfUserDismissedPreviousOne) {
  514. ClockAdvance(base::Seconds(100));
  515. mock_device_1_->SetBatteryInfo(
  516. BatteryInfo(BatteryType::kDefault, /*percentage=*/5));
  517. EXPECT_EQ(1u, message_center_->NotificationCount());
  518. // Simulate the user clears the notification.
  519. message_center_->RemoveAllNotifications(
  520. /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL);
  521. // The battery level remains low, but shouldn't post a notification.
  522. ClockAdvance(base::Seconds(100));
  523. mock_device_1_->SetBatteryInfo(
  524. BatteryInfo(BatteryType::kDefault, /*percentage=*/3));
  525. EXPECT_EQ(0u, message_center_->NotificationCount());
  526. }
  527. // If there is an existing notification and the battery level remains low,
  528. // update its content.
  529. TEST_F(PeripheralBatteryNotifierListenerTest, UpdateNotificationIfVisible) {
  530. ClockAdvance(base::Seconds(100));
  531. mock_device_1_->SetBatteryInfo(BatteryInfo(BatteryType::kDefault, 5));
  532. EXPECT_EQ(1u, message_center_->NotificationCount());
  533. // The battery level remains low, should update the notification.
  534. ClockAdvance(base::Seconds(100));
  535. mock_device_1_->SetBatteryInfo(
  536. BatteryInfo(BatteryType::kDefault, /*percentage=*/3));
  537. message_center::Notification* notification =
  538. message_center_->FindVisibleNotificationById(
  539. kBluetoothDeviceNotificationId1);
  540. EXPECT_TRUE(notification);
  541. EXPECT_EQ(mock_device_1_->GetNameForDisplay(), notification->title());
  542. EXPECT_EQ(3, ExtractBatteryPercentage(notification));
  543. }
  544. } // namespace ash