123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646 |
- // Copyright 2020 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/system/power/peripheral_battery_listener.h"
- #include <memory>
- #include <string>
- #include "ash/constants/ash_features.h"
- #include "ash/shell.h"
- #include "ash/system/power/peripheral_battery_notifier.h"
- #include "ash/system/power/peripheral_battery_tests.h"
- #include "ash/test/ash_test_base.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/string_piece.h"
- #include "base/strings/string_util.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/test/scoped_feature_list.h"
- #include "base/test/task_environment.h"
- #include "device/bluetooth/bluetooth_adapter_factory.h"
- #include "device/bluetooth/bluetooth_device.h"
- #include "device/bluetooth/test/mock_bluetooth_adapter.h"
- #include "device/bluetooth/test/mock_bluetooth_device.h"
- #include "ui/events/devices/device_data_manager.h"
- #include "ui/events/devices/device_data_manager_test_api.h"
- #include "ui/events/devices/touchscreen_device.h"
- #include "ui/message_center/message_center.h"
- #include "ui/message_center/public/cpp/notification.h"
- using testing::NiceMock;
- using BatteryInfo = device::BluetoothDevice::BatteryInfo;
- using BatteryType = device::BluetoothDevice::BatteryType;
- namespace {
- const std::u16string& NotificationMessagePrefix() {
- static const std::u16string prefix(u"Battery low (");
- return prefix;
- }
- const std::u16string& NotificationMessageSuffix() {
- static const std::u16string suffix(u"%)");
- return suffix;
- }
- } // namespace
- namespace ash {
- class PeripheralBatteryNotifierListenerTest : public AshTestBase {
- public:
- // Constants for active field of PeripheralBatteryStylusReceived().
- const bool kBluetoothBatteryUpdate = true;
- const bool kBatteryPolledUpdate = false;
- const bool kBatteryEventUpdate = true;
- PeripheralBatteryNotifierListenerTest()
- : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
- PeripheralBatteryNotifierListenerTest(
- const PeripheralBatteryNotifierListenerTest&) = delete;
- PeripheralBatteryNotifierListenerTest& operator=(
- const PeripheralBatteryNotifierListenerTest&) = delete;
- ~PeripheralBatteryNotifierListenerTest() override = default;
- void SetUp() override {
- AshTestBase::SetUp();
- ASSERT_TRUE(ui::DeviceDataManager::HasInstance());
- // Simulate the complete listing of input devices, required by the listener.
- if (complete_devices_)
- ui::DeviceDataManagerTestApi().OnDeviceListsComplete();
- mock_adapter_ =
- base::MakeRefCounted<NiceMock<device::MockBluetoothAdapter>>();
- mock_device_1_ = std::make_unique<NiceMock<device::MockBluetoothDevice>>(
- mock_adapter_.get(), /*bluetooth_class=*/0, kBluetoothDeviceName1,
- kBluetoothDeviceAddress1, /*paired=*/true, /*connected=*/true);
- mock_device_2_ = std::make_unique<NiceMock<device::MockBluetoothDevice>>(
- mock_adapter_.get(), /*bluetooth_class=*/0, kBluetoothDeviceName2,
- kBluetoothDeviceAddress2, /*paired=*/true, /*connected=*/true);
- device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_);
- message_center_ = message_center::MessageCenter::Get();
- battery_listener_ = std::make_unique<PeripheralBatteryListener>();
- battery_notifier_ =
- std::make_unique<PeripheralBatteryNotifier>(battery_listener_.get());
- // No notifications should have been posted yet.
- ASSERT_EQ(0u, message_center_->NotificationCount());
- }
- void TearDown() override {
- battery_notifier_.reset();
- battery_listener_.reset();
- AshTestBase::TearDown();
- }
- void SendBatteryUpdate(const std::string& path,
- const std::string& name,
- int level) {
- battery_listener_->PeripheralBatteryStatusReceived(
- path, name, level,
- power_manager::
- PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
- /*serial_number=*/kStylusEligibleSerialNumbers[0],
- kBatteryPolledUpdate);
- }
- void SendBatteryUpdate(
- const std::string& path,
- const std::string& name,
- int level,
- power_manager::PeripheralBatteryStatus_ChargeStatus status,
- const std::string& serial_number,
- bool active_update) {
- battery_listener_->PeripheralBatteryStatusReceived(
- path, name, level, status, serial_number, active_update);
- }
- // Extracts the battery percentage from the message of a notification.
- uint8_t ExtractBatteryPercentage(message_center::Notification* notification) {
- const std::u16string& message = notification->message();
- EXPECT_TRUE(base::StartsWith(message, NotificationMessagePrefix(),
- base::CompareCase::SENSITIVE));
- EXPECT_TRUE(base::EndsWith(message, NotificationMessageSuffix(),
- base::CompareCase::SENSITIVE));
- int prefix_size = NotificationMessagePrefix().size();
- int suffix_size = NotificationMessageSuffix().size();
- int key_len = message.size() - prefix_size - suffix_size;
- EXPECT_GT(key_len, 0);
- int battery_percentage;
- EXPECT_TRUE(base::StringToInt(message.substr(prefix_size, key_len),
- &battery_percentage));
- EXPECT_GE(battery_percentage, 0);
- EXPECT_LE(battery_percentage, 100);
- return battery_percentage;
- }
- base::TimeTicks GetTestingClock() { return base::TimeTicks::Now(); }
- void ClockAdvance(base::TimeDelta delta) {
- task_environment()->AdvanceClock(delta);
- }
- protected:
- scoped_refptr<NiceMock<device::MockBluetoothAdapter>> mock_adapter_;
- std::unique_ptr<device::MockBluetoothDevice> mock_device_1_;
- std::unique_ptr<device::MockBluetoothDevice> mock_device_2_;
- message_center::MessageCenter* message_center_;
- std::unique_ptr<PeripheralBatteryNotifier> battery_notifier_;
- std::unique_ptr<PeripheralBatteryListener> battery_listener_;
- void set_complete_devices(bool complete_devices) {
- complete_devices_ = complete_devices;
- }
- // SetUp() doesn't complete devices if this is set to false.
- bool complete_devices_ = true;
- };
- class PeripheralBatteryNotifierListenerIncompleteDevicesTest
- : public PeripheralBatteryNotifierListenerTest {
- public:
- PeripheralBatteryNotifierListenerIncompleteDevicesTest() {
- set_complete_devices(false);
- }
- PeripheralBatteryNotifierListenerIncompleteDevicesTest(
- const PeripheralBatteryNotifierListenerIncompleteDevicesTest&) = delete;
- PeripheralBatteryNotifierListenerIncompleteDevicesTest& operator=(
- const PeripheralBatteryNotifierListenerIncompleteDevicesTest&) = delete;
- ~PeripheralBatteryNotifierListenerIncompleteDevicesTest() override {}
- };
- TEST_F(PeripheralBatteryNotifierListenerTest, Basic) {
- // Level 50 at time 100, no low-battery notification.
- ClockAdvance(base::Seconds(100));
- SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, 50);
- EXPECT_EQ(1u,
- battery_notifier_->battery_notifications_.count(kTestBatteryId));
- const PeripheralBatteryNotifier::NotificationInfo& info =
- battery_notifier_->battery_notifications_[kTestBatteryId];
- EXPECT_EQ(absl::nullopt, info.level);
- EXPECT_EQ(GetTestingClock(), info.last_notification_timestamp);
- EXPECT_FALSE(
- message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
- // Level 5 at time 110, low-battery notification.
- ClockAdvance(base::Seconds(10));
- SendBatteryUpdate(
- kTestBatteryPath, kTestDeviceName, 5,
- power_manager::
- PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
- /*serial_number=*/"", kBatteryEventUpdate);
- EXPECT_EQ(5, info.level);
- EXPECT_EQ(GetTestingClock(), info.last_notification_timestamp);
- EXPECT_TRUE(
- message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
- // Verify that the low-battery notification for stylus does not show up.
- EXPECT_FALSE(message_center_->FindVisibleNotificationById(
- PeripheralBatteryNotifier::kStylusNotificationId));
- // Level -1 at time 115, cancel previous notification
- ClockAdvance(base::Seconds(5));
- SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, -1);
- EXPECT_EQ(absl::nullopt, info.level);
- EXPECT_EQ(GetTestingClock() - base::Seconds(5),
- info.last_notification_timestamp);
- EXPECT_FALSE(
- message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
- // Level 50 at time 120, no low-battery notification.
- ClockAdvance(base::Seconds(5));
- SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, 50);
- EXPECT_EQ(absl::nullopt, info.level);
- EXPECT_EQ(GetTestingClock() - base::Seconds(10),
- info.last_notification_timestamp);
- EXPECT_FALSE(
- message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
- // Level 5 at time 130, no low-battery notification (throttling).
- ClockAdvance(base::Seconds(10));
- SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, 5);
- EXPECT_EQ(5, info.level);
- EXPECT_EQ(GetTestingClock() - base::Seconds(20),
- info.last_notification_timestamp);
- EXPECT_FALSE(
- message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
- }
- TEST_F(PeripheralBatteryNotifierListenerTest, InvalidBatteryInfo) {
- const std::string invalid_path1 = "invalid-path";
- const std::string invalid_path2 = "/sys/class/power_supply/hid-battery";
- SendBatteryUpdate(invalid_path1, kTestDeviceName, 10);
- EXPECT_TRUE(battery_notifier_->battery_notifications_.empty());
- SendBatteryUpdate(invalid_path2, kTestDeviceName, 10);
- EXPECT_TRUE(battery_notifier_->battery_notifications_.empty());
- SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, -2);
- EXPECT_TRUE(battery_notifier_->battery_notifications_.empty());
- SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, 101);
- EXPECT_TRUE(battery_notifier_->battery_notifications_.empty());
- SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, -1);
- EXPECT_TRUE(battery_notifier_->battery_notifications_.empty());
- }
- // Verify that for Bluetooth devices, the correct address gets stored in the
- // BatteryInfo's bluetooth_address member, and for non-Bluetooth devices, that
- // bluetooth_address member is empty.
- TEST_F(PeripheralBatteryNotifierListenerTest, ExtractBluetoothAddress) {
- const std::string bluetooth_path =
- "/sys/class/power_supply/hid-A0:b1:C2:d3:E4:f5-battery";
- const std::string expected_bluetooth_address = "a0:b1:c2:d3:e4:f5";
- const std::string expected_bluetooth_id =
- "battery_notification_bluetooth-a0:b1:c2:d3:e4:f5";
- const std::string non_bluetooth_path =
- "/sys/class/power_supply/hid-notbluetooth-battery";
- SendBatteryUpdate(
- bluetooth_path, kTestDeviceName, 10,
- power_manager::
- PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
- /*serial_number=*/"", kBluetoothBatteryUpdate);
- SendBatteryUpdate(
- non_bluetooth_path, kTestDeviceName, 10,
- power_manager::
- PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
- /*serial_number=*/"", kBatteryPolledUpdate);
- EXPECT_EQ(2u, battery_notifier_->battery_notifications_.size());
- }
- TEST_F(PeripheralBatteryNotifierListenerTest, DeviceRemove) {
- SendBatteryUpdate(kTestBatteryPath, kTestDeviceName, 5);
- EXPECT_EQ(1u,
- battery_notifier_->battery_notifications_.count(kTestBatteryId));
- EXPECT_TRUE(
- message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
- battery_listener_->RemoveBluetoothBattery(kTestBatteryAddress);
- EXPECT_FALSE(
- message_center_->FindVisibleNotificationById(kTestBatteryNotificationId));
- }
- TEST_F(PeripheralBatteryNotifierListenerIncompleteDevicesTest,
- StylusNotification) {
- const std::string kTestStylusBatteryPath =
- "/sys/class/power_supply/hid-AAAA:BBBB:CCCC.DDDD-battery";
- const std::string kTestStylusName = "test_stylus";
- base::test::ScopedFeatureList flags;
- flags.InitAndEnableFeature(features::kStylusBatteryStatus);
- // Add an external stylus to our test device manager.
- ui::TouchscreenDevice stylus(/*id=*/0, ui::INPUT_DEVICE_USB, kTestStylusName,
- gfx::Size(),
- /*touch_points=*/1, /*has_stylus=*/true);
- stylus.sys_path = base::FilePath(kTestStylusBatteryPath);
- ui::DeviceDataManagerTestApi().SetTouchscreenDevices({stylus});
- // Verify that when the battery level is 5, a stylus low battery notification
- // is not shown due to input device list not being complete. Also check that
- // a non stylus device low battery notification will not show up.
- SendBatteryUpdate(
- kTestStylusBatteryPath, kTestStylusName, 5,
- power_manager::
- PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
- kStylusEligibleSerialNumbers[0], kBatteryEventUpdate);
- EXPECT_FALSE(message_center_->FindVisibleNotificationById(
- PeripheralBatteryNotifier::kStylusNotificationId));
- EXPECT_FALSE(
- message_center_->FindVisibleNotificationById(kTestBatteryAddress));
- // Complete devices
- ui::DeviceDataManagerTestApi().OnDeviceListsComplete();
- // Verify that when the battery level is 5, a stylus low battery notification
- // is now shown. Also check that a non stylus device low battery notification
- // will still not show up.
- SendBatteryUpdate(
- kTestStylusBatteryPath, kTestStylusName, 5,
- power_manager::
- PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
- kStylusEligibleSerialNumbers[0], kBatteryEventUpdate);
- EXPECT_TRUE(message_center_->FindVisibleNotificationById(
- PeripheralBatteryNotifier::kStylusNotificationId));
- EXPECT_FALSE(
- message_center_->FindVisibleNotificationById(kTestBatteryAddress));
- }
- TEST_F(PeripheralBatteryNotifierListenerIncompleteDevicesTest,
- StylusNotificationDisabled) {
- const std::string kTestStylusBatteryPath =
- "/sys/class/power_supply/hid-AAAA:BBBB:CCCC.DDDD-battery";
- const std::string kTestStylusName = "test_stylus";
- base::test::ScopedFeatureList flags;
- flags.InitAndDisableFeature(features::kStylusBatteryStatus);
- // Add an external stylus to our test device manager.
- ui::TouchscreenDevice stylus(/*id=*/0, ui::INPUT_DEVICE_USB, kTestStylusName,
- gfx::Size(),
- /*touch_points=*/1, /*has_stylus=*/true);
- stylus.sys_path = base::FilePath(kTestStylusBatteryPath);
- ui::DeviceDataManagerTestApi().SetTouchscreenDevices({stylus});
- // Verify that when the battery level is 5, a stylus low battery notification
- // is not shown due to input device list not being complete. Also check that
- // a non stylus device low battery notification will not show up.
- SendBatteryUpdate(
- kTestStylusBatteryPath, kTestStylusName, 5,
- power_manager::
- PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
- /*serial_number=*/"", kBatteryEventUpdate);
- EXPECT_FALSE(message_center_->FindVisibleNotificationById(
- PeripheralBatteryNotifier::kStylusNotificationId));
- EXPECT_FALSE(
- message_center_->FindVisibleNotificationById(kTestBatteryAddress));
- // Complete devices
- ui::DeviceDataManagerTestApi().OnDeviceListsComplete();
- // Verify that when the battery level is 5, a stylus low battery notification
- // is now shown. Also check that a non stylus device low battery notification
- // will still not show up.
- SendBatteryUpdate(
- kTestStylusBatteryPath, kTestStylusName, 5,
- power_manager::
- PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
- /*serial_number=*/"", kBatteryEventUpdate);
- EXPECT_FALSE(message_center_->FindVisibleNotificationById(
- PeripheralBatteryNotifier::kStylusNotificationId));
- EXPECT_FALSE(
- message_center_->FindVisibleNotificationById(kTestBatteryAddress));
- }
- TEST_F(PeripheralBatteryNotifierListenerTest, StylusNotification) {
- const std::string kTestStylusBatteryPath =
- "/sys/class/power_supply/hid-AAAA:BBBB:CCCC.DDDD-battery";
- const std::string kTestStylusName = "test_stylus";
- base::test::ScopedFeatureList flags;
- flags.InitAndEnableFeature(features::kStylusBatteryStatus);
- // Add an external stylus to our test device manager.
- ui::TouchscreenDevice stylus(/*id=*/0, ui::INPUT_DEVICE_USB, kTestStylusName,
- gfx::Size(),
- /*touch_points=*/1, /*has_stylus=*/true);
- stylus.sys_path = base::FilePath(kTestStylusBatteryPath);
- ui::DeviceDataManagerTestApi().SetTouchscreenDevices({stylus});
- // Verify that when the battery level is 50, no stylus low battery
- // notification is shown.
- SendBatteryUpdate(kTestStylusBatteryPath, kTestStylusName, 50);
- EXPECT_FALSE(message_center_->FindVisibleNotificationById(
- PeripheralBatteryNotifier::kStylusNotificationId));
- // Verify that when the battery level is 5, a stylus low battery notification
- // is shown. Also check that a non stylus device low battery notification will
- // not show up.
- SendBatteryUpdate(
- kTestStylusBatteryPath, kTestStylusName, 5,
- power_manager::
- PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
- kStylusEligibleSerialNumbers[0], kBatteryPolledUpdate);
- EXPECT_TRUE(message_center_->FindVisibleNotificationById(
- PeripheralBatteryNotifier::kStylusNotificationId));
- EXPECT_FALSE(
- message_center_->FindVisibleNotificationById(kTestBatteryAddress));
- // Verify that when the battery level is -1, the previous stylus low battery
- // notification is cancelled.
- SendBatteryUpdate(
- kTestStylusBatteryPath, kTestStylusName, -1,
- power_manager::
- PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING,
- kStylusEligibleSerialNumbers[0], kBatteryPolledUpdate);
- EXPECT_FALSE(message_center_->FindVisibleNotificationById(
- PeripheralBatteryNotifier::kStylusNotificationId));
- }
- TEST_F(PeripheralBatteryNotifierListenerTest, StylusNotificationDisabled) {
- const std::string kTestStylusBatteryPath =
- "/sys/class/power_supply/hid-AAAA:BBBB:CCCC.DDDD-battery";
- const std::string kTestStylusName = "test_stylus";
- base::test::ScopedFeatureList flags;
- flags.InitAndDisableFeature(features::kStylusBatteryStatus);
- // Add an external stylus to our test device manager.
- ui::TouchscreenDevice stylus(/*id=*/0, ui::INPUT_DEVICE_USB, kTestStylusName,
- gfx::Size(),
- /*touch_points=*/1, /*has_stylus=*/true);
- stylus.sys_path = base::FilePath(kTestStylusBatteryPath);
- ui::DeviceDataManagerTestApi().SetTouchscreenDevices({stylus});
- // Verify that when the battery level is 50, no stylus low battery
- // notification is shown.
- SendBatteryUpdate(kTestStylusBatteryPath, kTestStylusName, 50);
- EXPECT_FALSE(message_center_->FindVisibleNotificationById(
- PeripheralBatteryNotifier::kStylusNotificationId));
- // Verify that when the battery level is 5, a stylus low battery notification
- // is shown. Also check that a non stylus device low battery notification will
- // not show up.
- SendBatteryUpdate(kTestStylusBatteryPath, kTestStylusName, 5);
- EXPECT_FALSE(message_center_->FindVisibleNotificationById(
- PeripheralBatteryNotifier::kStylusNotificationId));
- EXPECT_FALSE(
- message_center_->FindVisibleNotificationById(kTestBatteryAddress));
- // Verify that when the battery level is -1, the previous stylus low battery
- // notification is cancelled.
- SendBatteryUpdate(kTestStylusBatteryPath, kTestStylusName, -1);
- EXPECT_FALSE(message_center_->FindVisibleNotificationById(
- PeripheralBatteryNotifier::kStylusNotificationId));
- }
- TEST_F(PeripheralBatteryNotifierListenerTest,
- Bluetooth_OnlyShowNotificationForLowBatteryLevels) {
- // Should not create a notification for battery changes above the threshold.
- mock_device_1_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/80));
- EXPECT_EQ(0u, message_center_->NotificationCount());
- mock_device_1_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/100));
- EXPECT_EQ(0u, message_center_->NotificationCount());
- // Should trigger notification.
- mock_device_1_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/10));
- EXPECT_EQ(1u, message_center_->NotificationCount());
- message_center::Notification* notification =
- message_center_->FindVisibleNotificationById(
- kBluetoothDeviceNotificationId1);
- EXPECT_EQ(mock_device_1_->GetNameForDisplay(), notification->title());
- EXPECT_EQ(10, ExtractBatteryPercentage(notification));
- }
- TEST_F(PeripheralBatteryNotifierListenerTest,
- Bluetooth_CreatesANotificationForEachDevice) {
- mock_device_1_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/5));
- mock_device_2_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/0));
- // Verify 2 notifications were posted with the correct values.
- EXPECT_EQ(2u, message_center_->NotificationCount());
- message_center::Notification* notification_1 =
- message_center_->FindVisibleNotificationById(
- kBluetoothDeviceNotificationId1);
- message_center::Notification* notification_2 =
- message_center_->FindVisibleNotificationById(
- kBluetoothDeviceNotificationId2);
- EXPECT_TRUE(notification_1);
- EXPECT_EQ(mock_device_1_->GetNameForDisplay(), notification_1->title());
- EXPECT_EQ(5, ExtractBatteryPercentage(notification_1));
- EXPECT_TRUE(notification_2);
- EXPECT_EQ(mock_device_2_->GetNameForDisplay(), notification_2->title());
- EXPECT_EQ(0, ExtractBatteryPercentage(notification_2));
- }
- TEST_F(PeripheralBatteryNotifierListenerTest,
- Bluetooth_RemovesNotificationForDisconnectedDevices) {
- mock_device_1_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/5));
- mock_device_2_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/0));
- // Verify 2 notifications were posted.
- EXPECT_EQ(2u, message_center_->NotificationCount());
- // Verify only the notification for device 1 gets removed.
- battery_listener_->DeviceConnectedStateChanged(mock_adapter_.get(),
- mock_device_1_.get(), false);
- EXPECT_EQ(1u, message_center_->NotificationCount());
- EXPECT_TRUE(message_center_->FindVisibleNotificationById(
- kBluetoothDeviceNotificationId2));
- // Remove the second notification.
- battery_listener_->DeviceRemoved(mock_adapter_.get(), mock_device_2_.get());
- EXPECT_EQ(0u, message_center_->NotificationCount());
- }
- TEST_F(PeripheralBatteryNotifierListenerTest,
- Bluetooth_CancelNotificationForInvalidBatteryLevel) {
- mock_device_1_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/1));
- EXPECT_TRUE(message_center_->FindVisibleNotificationById(
- kBluetoothDeviceNotificationId1));
- // The notification should get canceled.
- mock_device_1_->RemoveBatteryInfo(BatteryType::kDefault);
- EXPECT_FALSE(message_center_->FindVisibleNotificationById(
- kBluetoothDeviceNotificationId1));
- }
- // Don't post a notification if the battery level drops again under the
- // threshold before kNotificationInterval is completed.
- TEST_F(PeripheralBatteryNotifierListenerTest,
- DontShowSecondNotificationWithinASmallTimeInterval) {
- ClockAdvance(base::Seconds(100));
- // Post a notification.
- mock_device_1_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/1));
- EXPECT_TRUE(message_center_->FindVisibleNotificationById(
- kBluetoothDeviceNotificationId1));
- // Cancel the notification.
- ClockAdvance(base::Seconds(1));
- mock_device_1_->RemoveBatteryInfo(BatteryType::kDefault);
- EXPECT_FALSE(message_center_->FindVisibleNotificationById(
- kBluetoothDeviceNotificationId1));
- // The battery level falls below the threshold after a short time period. No
- // notification should get posted.
- ClockAdvance(base::Seconds(1));
- mock_device_1_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/1));
- EXPECT_FALSE(message_center_->FindVisibleNotificationById(
- kBluetoothDeviceNotificationId1));
- }
- // Post a notification if the battery is under threshold, then unknown level and
- // then is again under the threshold after kNotificationInterval is completed.
- TEST_F(PeripheralBatteryNotifierListenerTest,
- PostNotificationIfBatteryGoesFromUnknownLevelToBelowThreshold) {
- ClockAdvance(base::Seconds(100));
- // Post a notification.
- mock_device_1_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/1));
- EXPECT_TRUE(message_center_->FindVisibleNotificationById(
- kBluetoothDeviceNotificationId1));
- // Cancel the notification.
- ClockAdvance(base::Seconds(1));
- mock_device_1_->RemoveBatteryInfo(BatteryType::kDefault);
- EXPECT_FALSE(message_center_->FindVisibleNotificationById(
- kBluetoothDeviceNotificationId1));
- // Post notification if we are out of the kNotificationInterval.
- ClockAdvance(base::Seconds(100));
- mock_device_1_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/1));
- EXPECT_TRUE(message_center_->FindVisibleNotificationById(
- kBluetoothDeviceNotificationId1));
- }
- // Don't Post another notification if the battery level keeps low and the user
- // dismissed the previous notification.
- TEST_F(PeripheralBatteryNotifierListenerTest,
- DontRepostNotificationIfUserDismissedPreviousOne) {
- ClockAdvance(base::Seconds(100));
- mock_device_1_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/5));
- EXPECT_EQ(1u, message_center_->NotificationCount());
- // Simulate the user clears the notification.
- message_center_->RemoveAllNotifications(
- /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL);
- // The battery level remains low, but shouldn't post a notification.
- ClockAdvance(base::Seconds(100));
- mock_device_1_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/3));
- EXPECT_EQ(0u, message_center_->NotificationCount());
- }
- // If there is an existing notification and the battery level remains low,
- // update its content.
- TEST_F(PeripheralBatteryNotifierListenerTest, UpdateNotificationIfVisible) {
- ClockAdvance(base::Seconds(100));
- mock_device_1_->SetBatteryInfo(BatteryInfo(BatteryType::kDefault, 5));
- EXPECT_EQ(1u, message_center_->NotificationCount());
- // The battery level remains low, should update the notification.
- ClockAdvance(base::Seconds(100));
- mock_device_1_->SetBatteryInfo(
- BatteryInfo(BatteryType::kDefault, /*percentage=*/3));
- message_center::Notification* notification =
- message_center_->FindVisibleNotificationById(
- kBluetoothDeviceNotificationId1);
- EXPECT_TRUE(notification);
- EXPECT_EQ(mock_device_1_->GetNameForDisplay(), notification->title());
- EXPECT_EQ(3, ExtractBatteryPercentage(notification));
- }
- } // namespace ash
|