123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- // Copyright 2021 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 <memory>
- #include <string>
- #include "ash/constants/ash_features.h"
- #include "ash/public/cpp/microphone_mute_notification_delegate.h"
- #include "ash/system/microphone_mute/microphone_mute_notification_controller.h"
- #include "ash/test/ash_test_base.h"
- #include "base/check.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/test/scoped_feature_list.h"
- #include "chromeos/ash/components/dbus/audio/fake_cras_audio_client.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "ui/message_center/message_center.h"
- #include "ui/message_center/public/cpp/notification.h"
- #include "ui/message_center/public/cpp/notification_types.h"
- namespace ash {
- class FakeMicrophoneMuteNotificationDelegate
- : public MicrophoneMuteNotificationDelegate {
- public:
- absl::optional<std::u16string> GetAppAccessingMicrophone() override {
- return app_name_;
- }
- void SetAppAccessingMicrophone(
- const absl::optional<std::u16string> app_name) {
- app_name_ = app_name;
- }
- absl::optional<std::u16string> app_name_;
- };
- class MicrophoneMuteNotificationControllerTest : public AshTestBase {
- public:
- MicrophoneMuteNotificationControllerTest() {
- scoped_feature_list_.InitAndEnableFeature(features::kMicMuteNotifications);
- }
- ~MicrophoneMuteNotificationControllerTest() override = default;
- // AshTestBase:
- void SetUp() override {
- AshTestBase::SetUp();
- controller_ = std::make_unique<MicrophoneMuteNotificationController>();
- delegate_ = std::make_unique<FakeMicrophoneMuteNotificationDelegate>();
- }
- void TearDown() override {
- controller_.reset();
- delegate_.reset();
- SetMicrophoneMuteSwitchState(/*muted=*/false);
- AshTestBase::TearDown();
- }
- protected:
- message_center::Notification* GetNotification() {
- const message_center::NotificationList::Notifications& notifications =
- message_center::MessageCenter::Get()->GetVisibleNotifications();
- for (auto* notification : notifications) {
- if (notification->id() ==
- MicrophoneMuteNotificationController::kNotificationId) {
- return notification;
- }
- }
- return nullptr;
- }
- message_center::Notification* GetPopupNotification() {
- const message_center::NotificationList::PopupNotifications& notifications =
- message_center::MessageCenter::Get()->GetPopupNotifications();
- for (auto* notification : notifications) {
- if (notification->id() ==
- MicrophoneMuteNotificationController::kNotificationId) {
- return notification;
- }
- }
- return nullptr;
- }
- void MarkPopupAsShown() {
- message_center::MessageCenter::Get()->MarkSinglePopupAsShown(
- MicrophoneMuteNotificationController::kNotificationId, true);
- }
- void ClickOnNotificationButton() {
- message_center::MessageCenter::Get()->ClickOnNotificationButton(
- MicrophoneMuteNotificationController::kNotificationId,
- /*button_index=*/0);
- }
- void SetMicrophoneMuteSwitchState(bool muted) {
- ui::MicrophoneMuteSwitchMonitor::Get()->SetMicrophoneMuteSwitchValue(muted);
- }
- void MuteMicrophone() { CrasAudioHandler::Get()->SetInputMute(true); }
- void UnMuteMicrophone() { CrasAudioHandler::Get()->SetInputMute(false); }
- void SetNumberOfActiveInputStreams(int number_of_active_input_streams) {
- FakeCrasAudioClient::Get()->SetActiveInputStreamsWithPermission(
- {{"CRAS_CLIENT_TYPE_CHROME", number_of_active_input_streams}});
- }
- void LaunchApp(absl::optional<std::u16string> app_name) {
- delegate_->SetAppAccessingMicrophone(app_name);
- }
- private:
- base::test::ScopedFeatureList scoped_feature_list_;
- std::unique_ptr<MicrophoneMuteNotificationController> controller_;
- std::unique_ptr<FakeMicrophoneMuteNotificationDelegate> delegate_;
- };
- TEST_F(MicrophoneMuteNotificationControllerTest, SimpleMuteUnMute) {
- // No notification initially.
- EXPECT_FALSE(GetNotification());
- // Or when we mute.
- MuteMicrophone();
- EXPECT_FALSE(GetNotification());
- // Or when we unmute.
- UnMuteMicrophone();
- EXPECT_FALSE(GetNotification());
- }
- TEST_F(MicrophoneMuteNotificationControllerTest, LaunchAppNotUsingMicrophone) {
- // No notification initially.
- EXPECT_FALSE(GetNotification());
- // No notification when we unmute.
- UnMuteMicrophone();
- EXPECT_FALSE(GetNotification());
- // Launch an app that's not using the mic, should be no notification.
- LaunchApp(absl::nullopt);
- SetNumberOfActiveInputStreams(0);
- EXPECT_FALSE(GetNotification());
- // Mute the mic, still no notification because no app is using the mic.
- MuteMicrophone();
- EXPECT_FALSE(GetNotification());
- }
- TEST_F(MicrophoneMuteNotificationControllerTest, LaunchAppUsingMicrophone) {
- // No notification initially.
- EXPECT_FALSE(GetNotification());
- // No notification when we unmute.
- UnMuteMicrophone();
- EXPECT_FALSE(GetNotification());
- // Mute the mic, still no notification.
- MuteMicrophone();
- EXPECT_FALSE(GetNotification());
- // Launch an app that's using the mic. The microphone mute notification should
- // show as a popup
- LaunchApp(u"junior");
- SetNumberOfActiveInputStreams(1);
- EXPECT_TRUE(GetNotification());
- EXPECT_TRUE(GetPopupNotification());
- // Unmute again, notification goes down.
- UnMuteMicrophone();
- EXPECT_FALSE(GetNotification());
- }
- TEST_F(MicrophoneMuteNotificationControllerTest,
- SilentNotificationOnMuteWhileMicInUse) {
- // No notification initially.
- EXPECT_FALSE(GetNotification());
- // Launch an app that's using the mic, no notification because the microphone
- // is not muted.
- LaunchApp(u"junior");
- SetNumberOfActiveInputStreams(1);
- EXPECT_FALSE(GetNotification());
- // Mute the mic, a notification should be shown, but not as a popup.
- MuteMicrophone();
- EXPECT_TRUE(GetNotification());
- EXPECT_FALSE(GetPopupNotification());
- }
- TEST_F(MicrophoneMuteNotificationControllerTest,
- ShowPopupNotificationOnStreamAddition) {
- // Launch an app while microphone is muted.
- MuteMicrophone();
- LaunchApp(u"junior");
- SetNumberOfActiveInputStreams(1);
- ASSERT_TRUE(GetNotification());
- ASSERT_TRUE(GetPopupNotification());
- // Mark the notification as read.
- MarkPopupAsShown();
- ASSERT_FALSE(GetPopupNotification());
- // Add an app, and verify the notification popup gets shown.
- LaunchApp(u"rose");
- SetNumberOfActiveInputStreams(2);
- EXPECT_TRUE(GetNotification());
- EXPECT_TRUE(GetPopupNotification());
- }
- TEST_F(MicrophoneMuteNotificationControllerTest,
- RemovingStreamDoesNotShowPopup) {
- // Launch 2 apps while microphone is muted.
- MuteMicrophone();
- LaunchApp(u"junior");
- LaunchApp(u"rose");
- SetNumberOfActiveInputStreams(2);
- ASSERT_TRUE(GetNotification());
- ASSERT_TRUE(GetPopupNotification());
- // Mark the notification as read.
- MarkPopupAsShown();
- ASSERT_FALSE(GetPopupNotification());
- // Remove an active stream, and verify that the notification popup is not
- // reshown.
- SetNumberOfActiveInputStreams(1);
- EXPECT_TRUE(GetNotification());
- EXPECT_FALSE(GetPopupNotification());
- // The notification should be removed if all input streams are removed.
- LaunchApp(absl::nullopt);
- SetNumberOfActiveInputStreams(0);
- EXPECT_FALSE(GetNotification());
- }
- TEST_F(MicrophoneMuteNotificationControllerTest, MuteNotificationActionButton) {
- MuteMicrophone();
- LaunchApp(u"junior");
- SetNumberOfActiveInputStreams(1);
- // The mute notification should have an action button.
- message_center::Notification* notification = GetNotification();
- ASSERT_TRUE(notification);
- EXPECT_EQ(1u, notification->buttons().size());
- // Clicking the action button should unmute device.
- ClickOnNotificationButton();
- EXPECT_FALSE(chromeos::CrasAudioHandler::Get()->IsInputMuted());
- EXPECT_FALSE(GetNotification());
- }
- TEST_F(MicrophoneMuteNotificationControllerTest,
- NoNotificationActionButtonIfMutedByHwSwitch) {
- SetMicrophoneMuteSwitchState(/*muted=*/true);
- LaunchApp(u"junior");
- SetNumberOfActiveInputStreams(1);
- // The mute notification should not have an action button if device is muted
- // by a mute switch.
- message_center::Notification* notification = GetNotification();
- ASSERT_TRUE(notification);
- EXPECT_EQ(0u, notification->buttons().size());
- SetMicrophoneMuteSwitchState(/*muted=*/false);
- ASSERT_FALSE(chromeos::CrasAudioHandler::Get()->IsInputMuted());
- EXPECT_FALSE(GetNotification());
- }
- TEST_F(MicrophoneMuteNotificationControllerTest,
- TogglingMuteSwitchRemovesNotificationActionButton) {
- // Mute microphone, and activate an audio input stream.
- MuteMicrophone();
- LaunchApp(u"junior");
- SetNumberOfActiveInputStreams(1);
- // The mute notification should have an action button.
- message_center::Notification* notification = GetNotification();
- ASSERT_TRUE(notification);
- EXPECT_EQ(1u, notification->buttons().size());
- // Toggle microphone mute switch and verify the action button disappears.
- SetMicrophoneMuteSwitchState(/*muted=*/true);
- notification = GetNotification();
- ASSERT_TRUE(notification);
- EXPECT_EQ(0u, notification->buttons().size());
- SetMicrophoneMuteSwitchState(/*muted=*/false);
- ASSERT_FALSE(chromeos::CrasAudioHandler::Get()->IsInputMuted());
- EXPECT_FALSE(GetNotification());
- }
- TEST_F(MicrophoneMuteNotificationControllerTest,
- TogglingMuteSwitchDoesNotHideNotificationPopup) {
- // Mute microphone, and activate an audio input stream.
- MuteMicrophone();
- LaunchApp(u"junior");
- SetNumberOfActiveInputStreams(1);
- // Verify the notification popup is shown.
- ASSERT_TRUE(GetNotification());
- ASSERT_TRUE(GetPopupNotification());
- // Toggle microphone mute switch and verify that toggling mute switch alone
- // does not hide the notification popup.
- SetMicrophoneMuteSwitchState(/*muted=*/true);
- EXPECT_TRUE(GetNotification());
- EXPECT_TRUE(GetPopupNotification());
- SetMicrophoneMuteSwitchState(/*muted=*/false);
- ASSERT_FALSE(chromeos::CrasAudioHandler::Get()->IsInputMuted());
- EXPECT_FALSE(GetNotification());
- }
- TEST_F(MicrophoneMuteNotificationControllerTest,
- RemovingAllInputStreamsWhileHwSwitchToggled) {
- SetMicrophoneMuteSwitchState(/*muted=*/true);
- LaunchApp(u"junior");
- SetNumberOfActiveInputStreams(2);
- EXPECT_TRUE(GetNotification());
- EXPECT_TRUE(GetPopupNotification());
- SetNumberOfActiveInputStreams(0);
- EXPECT_FALSE(GetNotification());
- }
- TEST_F(MicrophoneMuteNotificationControllerTest,
- ToggleMicrophoneMuteSwitchWhileInputStreamActive) {
- // Launch an app using microphone, and toggle mute switch.
- LaunchApp(u"junior");
- SetNumberOfActiveInputStreams(1);
- SetMicrophoneMuteSwitchState(/*muted=*/true);
- // Notification should be shown, but not as a popup.
- EXPECT_TRUE(GetNotification());
- EXPECT_FALSE(GetPopupNotification());
- // Add another audio input stream, and verify the notification popup shows.
- LaunchApp(u"junior1");
- SetNumberOfActiveInputStreams(2);
- EXPECT_TRUE(GetNotification());
- EXPECT_TRUE(GetPopupNotification());
- // Mark notification as read, and then remove an audio input stream.
- MarkPopupAsShown();
- ASSERT_FALSE(GetPopupNotification());
- SetNumberOfActiveInputStreams(1);
- // Verify that notification popup is not reshown.
- EXPECT_TRUE(GetNotification());
- EXPECT_FALSE(GetPopupNotification());
- // Adding another stream shows a popup again.
- LaunchApp(u"rose");
- SetNumberOfActiveInputStreams(2);
- EXPECT_TRUE(GetNotification());
- EXPECT_TRUE(GetPopupNotification());
- }
- } // namespace ash
|