1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "services/media_session/audio_focus_manager.h"
11 #include "base/containers/adapters.h"
12 #include "base/functional/bind.h"
13 #include "base/functional/callback.h"
14 #include "base/ranges/algorithm.h"
15 #include "base/run_loop.h"
16 #include "base/test/power_monitor_test.h"
17 #include "base/test/task_environment.h"
18 #include "build/build_config.h"
19 #include "build/chromeos_buildflags.h"
20 #include "mojo/public/cpp/bindings/remote.h"
21 #include "services/media_session/audio_focus_request.h"
22 #include "services/media_session/media_session_service_impl.h"
23 #include "services/media_session/public/cpp/test/audio_focus_test_util.h"
24 #include "services/media_session/public/cpp/test/mock_media_session.h"
25 #include "services/media_session/public/mojom/audio_focus.mojom.h"
26 #include "services/media_session/public/mojom/media_session.mojom.h"
27 #include "testing/gtest/include/gtest/gtest.h"
29 namespace media_session {
33 const char kExampleSourceName[] = "test";
34 const char kExampleSourceName2[] = "test2";
36 } // anonymous namespace
38 // This tests the Audio Focus Manager API. The parameter determines whether
39 // audio focus is enabled or not. If it is not enabled it should track the media
40 // sessions but not enforce single session focus.
41 class AudioFocusManagerTest
42 : public testing::TestWithParam<mojom::EnforcementMode> {
44 AudioFocusManagerTest() = default;
46 AudioFocusManagerTest(const AudioFocusManagerTest&) = delete;
47 AudioFocusManagerTest& operator=(const AudioFocusManagerTest&) = delete;
49 void SetUp() override {
50 // Create an instance of the MediaSessionService.
51 service_ = std::make_unique<MediaSessionServiceImpl>();
52 service_->BindAudioFocusManager(
53 audio_focus_remote_.BindNewPipeAndPassReceiver());
54 service_->BindAudioFocusManagerDebug(
55 audio_focus_debug_remote_.BindNewPipeAndPassReceiver());
56 service_->BindMediaControllerManager(
57 controller_manager_remote_.BindNewPipeAndPassReceiver());
59 audio_focus_remote_->SetEnforcementMode(GetParam());
60 audio_focus_remote_.FlushForTesting();
63 void TearDown() override {
65 base::RunLoop().RunUntilIdle();
70 AudioFocusManager::RequestId GetAudioFocusedSession() {
71 const auto audio_focus_requests = GetRequests();
72 for (const auto& request : base::Reversed(audio_focus_requests)) {
73 if (request->audio_focus_type == mojom::AudioFocusType::kGain)
74 return request->request_id.value();
76 return base::UnguessableToken::Null();
79 int GetTransientCount() {
80 return GetCountForType(mojom::AudioFocusType::kGainTransient);
83 int GetTransientMaybeDuckCount() {
84 return GetCountForType(mojom::AudioFocusType::kGainTransientMayDuck);
87 int GetAmbientCount() {
88 return GetCountForType(mojom::AudioFocusType::kAmbient);
91 void AbandonAudioFocusNoReset(test::MockMediaSession* session) {
92 session->audio_focus_request()->AbandonAudioFocus();
93 session->FlushForTesting();
94 audio_focus_remote_.FlushForTesting();
97 AudioFocusManager::RequestId RequestAudioFocus(
98 test::MockMediaSession* session,
99 mojom::AudioFocusType audio_focus_type) {
100 return session->RequestAudioFocusFromService(audio_focus_remote_,
104 bool RequestGroupedAudioFocus(const base::UnguessableToken& request_id,
105 test::MockMediaSession* session,
106 mojom::AudioFocusType audio_focus_type,
107 const base::UnguessableToken& group_id) {
108 return session->RequestGroupedAudioFocusFromService(
109 request_id, audio_focus_remote_, audio_focus_type, group_id);
112 mojom::MediaSessionDebugInfoPtr GetDebugInfo(
113 AudioFocusManager::RequestId request_id) {
114 mojom::MediaSessionDebugInfoPtr result;
115 base::OnceCallback<void(mojom::MediaSessionDebugInfoPtr)> callback =
117 [](mojom::MediaSessionDebugInfoPtr* out_result,
118 mojom::MediaSessionDebugInfoPtr result) {
119 *out_result = std::move(result);
123 GetDebugService()->GetDebugInfoForRequest(request_id, std::move(callback));
125 audio_focus_remote_.FlushForTesting();
126 audio_focus_debug_remote_.FlushForTesting();
131 mojom::MediaSessionInfo::SessionState GetState(
132 test::MockMediaSession* session) {
133 mojom::MediaSessionInfo::SessionState state = session->GetState();
135 if (!IsEnforcementEnabled()) {
136 // If audio focus enforcement is disabled then we should never see ducking
138 EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking, state);
144 std::unique_ptr<test::TestAudioFocusObserver> CreateObserver() {
145 std::unique_ptr<test::TestAudioFocusObserver> observer =
146 std::make_unique<test::TestAudioFocusObserver>();
148 GetService()->AddObserver(observer->BindNewPipeAndPassRemote());
150 audio_focus_remote_.FlushForTesting();
154 std::unique_ptr<test::TestAudioFocusObserver> CreateSourceObserver(
155 const base::UnguessableToken& source_id) {
156 std::unique_ptr<test::TestAudioFocusObserver> observer =
157 std::make_unique<test::TestAudioFocusObserver>();
159 GetService()->AddSourceObserver(source_id,
160 observer->BindNewPipeAndPassRemote());
162 audio_focus_remote_.FlushForTesting();
166 mojom::MediaSessionInfo::SessionState GetStateFromParam(
167 mojom::MediaSessionInfo::SessionState state) {
168 // If enforcement is enabled then returns the provided state, otherwise
169 // returns kActive because without enforcement we did not change state.
170 if (IsEnforcementEnabled())
172 return mojom::MediaSessionInfo::SessionState::kActive;
175 void SetSource(const base::UnguessableToken& identity,
176 const std::string& name) {
177 GetService()->SetSource(identity, name);
178 audio_focus_remote_.FlushForTesting();
181 mojo::Remote<mojom::AudioFocusManager> CreateAudioFocusManagerRemote() {
182 mojo::Remote<mojom::AudioFocusManager> remote;
183 service_->BindAudioFocusManager(remote.BindNewPipeAndPassReceiver());
187 const std::string GetSourceNameForLastRequest() {
188 std::vector<mojom::AudioFocusRequestStatePtr> requests = GetRequests();
189 EXPECT_TRUE(requests.back());
190 return requests.back()->source_name.value();
193 bool IsEnforcementEnabled() const {
194 return GetParam() == mojom::EnforcementMode::kSingleSession ||
195 GetParam() == mojom::EnforcementMode::kSingleGroup;
198 bool IsGroupingEnabled() const {
199 return GetParam() != mojom::EnforcementMode::kSingleSession;
202 void GenerateSuspendEvent() { power_source_.GenerateSuspendEvent(); }
204 mojo::Remote<mojom::MediaControllerManager>& controller_manager() {
205 return controller_manager_remote_;
208 std::vector<mojom::AudioFocusRequestStatePtr> GetSourceFocusRequests(
209 const base::UnguessableToken& source_id) {
210 std::vector<mojom::AudioFocusRequestStatePtr> result;
212 GetService()->GetSourceFocusRequests(
215 [](std::vector<mojom::AudioFocusRequestStatePtr>* out,
216 std::vector<mojom::AudioFocusRequestStatePtr> requests) {
217 *out = std::move(requests);
221 audio_focus_remote_.FlushForTesting();
225 const base::UnguessableToken& GetIdentityForLastRequest() const {
226 return service_->audio_focus_manager_for_testing()
227 .audio_focus_stack_.back()
231 void FlushForTesting() { audio_focus_remote_.FlushForTesting(); }
234 int GetCountForType(mojom::AudioFocusType type) {
235 const auto audio_focus_requests = GetRequests();
236 return base::ranges::count(
237 audio_focus_requests, type,
238 &mojom::AudioFocusRequestState::audio_focus_type);
241 std::vector<mojom::AudioFocusRequestStatePtr> GetRequests() {
242 std::vector<mojom::AudioFocusRequestStatePtr> result;
244 GetService()->GetFocusRequests(base::BindOnce(
245 [](std::vector<mojom::AudioFocusRequestStatePtr>* out,
246 std::vector<mojom::AudioFocusRequestStatePtr> requests) {
247 for (auto& request : requests)
248 out->push_back(request.Clone());
252 audio_focus_remote_.FlushForTesting();
256 mojom::AudioFocusManager* GetService() const {
257 return audio_focus_remote_.get();
260 mojom::AudioFocusManagerDebug* GetDebugService() const {
261 return audio_focus_debug_remote_.get();
264 void FlushForTestingIfEnabled() {
265 if (!IsEnforcementEnabled())
268 audio_focus_remote_.FlushForTesting();
271 base::test::TaskEnvironment task_environment_;
273 std::unique_ptr<MediaSessionServiceImpl> service_;
275 mojo::Remote<mojom::AudioFocusManager> audio_focus_remote_;
276 mojo::Remote<mojom::AudioFocusManagerDebug> audio_focus_debug_remote_;
277 mojo::Remote<mojom::MediaControllerManager> controller_manager_remote_;
279 base::test::ScopedPowerMonitorTestSource power_source_;
282 INSTANTIATE_TEST_SUITE_P(
284 AudioFocusManagerTest,
285 testing::Values(mojom::EnforcementMode::kDefault,
286 mojom::EnforcementMode::kNone,
287 mojom::EnforcementMode::kSingleGroup,
288 mojom::EnforcementMode::kSingleSession));
290 TEST_P(AudioFocusManagerTest, RequestAudioFocusGain_ReplaceFocusedEntry) {
291 test::MockMediaSession media_session_1;
292 test::MockMediaSession media_session_2;
293 test::MockMediaSession media_session_3;
295 EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
296 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kInactive,
297 GetState(&media_session_1));
298 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kInactive,
299 GetState(&media_session_2));
300 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kInactive,
301 GetState(&media_session_3));
303 AudioFocusManager::RequestId request_id_1 =
304 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
305 EXPECT_EQ(request_id_1, GetAudioFocusedSession());
306 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
307 GetState(&media_session_1));
309 AudioFocusManager::RequestId request_id_2 =
310 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
311 EXPECT_EQ(request_id_2, GetAudioFocusedSession());
313 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
314 GetState(&media_session_1));
316 AudioFocusManager::RequestId request_id_3 =
317 RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGain);
318 EXPECT_EQ(request_id_3, GetAudioFocusedSession());
320 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
321 GetState(&media_session_2));
324 TEST_P(AudioFocusManagerTest, RequestAudioFocusGain_Duplicate) {
325 test::MockMediaSession media_session;
327 EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
329 AudioFocusManager::RequestId request_id =
330 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
331 EXPECT_EQ(request_id, GetAudioFocusedSession());
333 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
334 EXPECT_EQ(request_id, GetAudioFocusedSession());
337 TEST_P(AudioFocusManagerTest, RequestAudioFocusGain_FromTransient) {
338 test::MockMediaSession media_session;
340 AudioFocusManager::RequestId request_id =
341 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGainTransient);
342 EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
343 EXPECT_EQ(1, GetTransientCount());
345 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
346 EXPECT_EQ(request_id, GetAudioFocusedSession());
347 EXPECT_EQ(0, GetTransientCount());
350 TEST_P(AudioFocusManagerTest, RequestAudioFocusGain_FromTransientMayDuck) {
351 test::MockMediaSession media_session;
353 AudioFocusManager::RequestId request_id = RequestAudioFocus(
354 &media_session, mojom::AudioFocusType::kGainTransientMayDuck);
355 EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
356 EXPECT_EQ(1, GetTransientMaybeDuckCount());
358 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
359 EXPECT_EQ(request_id, GetAudioFocusedSession());
360 EXPECT_EQ(0, GetTransientMaybeDuckCount());
363 TEST_P(AudioFocusManagerTest, RequestAudioFocusTransient_FromGain) {
364 test::MockMediaSession media_session;
366 AudioFocusManager::RequestId request_id =
367 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
369 EXPECT_EQ(request_id, GetAudioFocusedSession());
370 EXPECT_EQ(0, GetTransientCount());
372 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGainTransient);
373 EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
374 EXPECT_EQ(1, GetTransientCount());
375 EXPECT_NE(mojom::MediaSessionInfo::SessionState::kSuspended,
376 GetState(&media_session));
379 TEST_P(AudioFocusManagerTest, RequestAudioFocusTransientMayDuck_FromGain) {
380 test::MockMediaSession media_session;
382 AudioFocusManager::RequestId request_id =
383 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
385 EXPECT_EQ(request_id, GetAudioFocusedSession());
386 EXPECT_EQ(0, GetTransientMaybeDuckCount());
388 RequestAudioFocus(&media_session,
389 mojom::AudioFocusType::kGainTransientMayDuck);
390 EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
391 EXPECT_EQ(1, GetTransientMaybeDuckCount());
392 EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
393 GetState(&media_session));
396 TEST_P(AudioFocusManagerTest, RequestAudioFocusTransient_FromGainWhileDucking) {
397 test::MockMediaSession media_session_1;
398 test::MockMediaSession media_session_2;
400 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
401 EXPECT_EQ(0, GetTransientMaybeDuckCount());
402 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
403 GetState(&media_session_1));
405 RequestAudioFocus(&media_session_2,
406 mojom::AudioFocusType::kGainTransientMayDuck);
407 EXPECT_EQ(0, GetTransientCount());
408 EXPECT_EQ(1, GetTransientMaybeDuckCount());
409 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
410 GetState(&media_session_1));
412 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGainTransient);
413 EXPECT_EQ(1, GetTransientCount());
414 EXPECT_EQ(1, GetTransientMaybeDuckCount());
415 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
416 GetState(&media_session_1));
419 TEST_P(AudioFocusManagerTest,
420 RequestAudioFocusTransientMayDuck_FromGainWhileDucking) {
421 test::MockMediaSession media_session_1;
422 test::MockMediaSession media_session_2;
424 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
425 EXPECT_EQ(0, GetTransientMaybeDuckCount());
426 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
427 GetState(&media_session_1));
429 RequestAudioFocus(&media_session_2,
430 mojom::AudioFocusType::kGainTransientMayDuck);
431 EXPECT_EQ(1, GetTransientMaybeDuckCount());
432 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
433 GetState(&media_session_1));
435 RequestAudioFocus(&media_session_1,
436 mojom::AudioFocusType::kGainTransientMayDuck);
437 EXPECT_EQ(2, GetTransientMaybeDuckCount());
438 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
439 GetState(&media_session_1));
442 TEST_P(AudioFocusManagerTest, AbandonAudioFocus_RemovesFocusedEntry) {
443 test::MockMediaSession media_session;
445 AudioFocusManager::RequestId request_id =
446 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
447 EXPECT_EQ(request_id, GetAudioFocusedSession());
449 media_session.AbandonAudioFocusFromClient();
450 EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
453 TEST_P(AudioFocusManagerTest, AbandonAudioFocus_MultipleCalls) {
454 test::MockMediaSession media_session;
456 AudioFocusManager::RequestId request_id =
457 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
458 EXPECT_EQ(request_id, GetAudioFocusedSession());
460 AbandonAudioFocusNoReset(&media_session);
462 std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
463 media_session.AbandonAudioFocusFromClient();
465 EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
466 EXPECT_TRUE(observer->focus_lost_session().is_null());
469 TEST_P(AudioFocusManagerTest, AbandonAudioFocus_RemovesTransientMayDuckEntry) {
470 test::MockMediaSession media_session;
472 RequestAudioFocus(&media_session,
473 mojom::AudioFocusType::kGainTransientMayDuck);
474 EXPECT_EQ(1, GetTransientMaybeDuckCount());
477 std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
478 media_session.AbandonAudioFocusFromClient();
480 EXPECT_EQ(0, GetTransientMaybeDuckCount());
481 EXPECT_TRUE(observer->focus_lost_session()->session_info.Equals(
482 test::GetMediaSessionInfoSync(&media_session)));
486 TEST_P(AudioFocusManagerTest, AbandonAudioFocus_RemovesTransientEntry) {
487 test::MockMediaSession media_session;
489 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGainTransient);
490 EXPECT_EQ(1, GetTransientCount());
493 std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
494 media_session.AbandonAudioFocusFromClient();
496 EXPECT_EQ(0, GetTransientCount());
497 EXPECT_TRUE(observer->focus_lost_session()->session_info.Equals(
498 test::GetMediaSessionInfoSync(&media_session)));
502 TEST_P(AudioFocusManagerTest, AbandonAudioFocus_WhileDuckingThenResume) {
503 test::MockMediaSession media_session_1;
504 test::MockMediaSession media_session_2;
506 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
507 EXPECT_EQ(0, GetTransientMaybeDuckCount());
508 EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
509 GetState(&media_session_1));
511 RequestAudioFocus(&media_session_2,
512 mojom::AudioFocusType::kGainTransientMayDuck);
513 EXPECT_EQ(1, GetTransientMaybeDuckCount());
514 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
515 GetState(&media_session_1));
517 media_session_1.AbandonAudioFocusFromClient();
518 EXPECT_EQ(1, GetTransientMaybeDuckCount());
520 media_session_2.AbandonAudioFocusFromClient();
521 EXPECT_EQ(0, GetTransientMaybeDuckCount());
523 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
524 EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
525 GetState(&media_session_1));
528 TEST_P(AudioFocusManagerTest, AbandonAudioFocus_StopsDucking) {
529 test::MockMediaSession media_session_1;
530 test::MockMediaSession media_session_2;
532 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
533 EXPECT_EQ(0, GetTransientMaybeDuckCount());
534 EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
535 GetState(&media_session_1));
537 RequestAudioFocus(&media_session_2,
538 mojom::AudioFocusType::kGainTransientMayDuck);
539 EXPECT_EQ(1, GetTransientMaybeDuckCount());
540 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
541 GetState(&media_session_1));
543 media_session_2.AbandonAudioFocusFromClient();
544 EXPECT_EQ(0, GetTransientMaybeDuckCount());
545 EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
546 GetState(&media_session_1));
549 TEST_P(AudioFocusManagerTest, AbandonAudioFocus_ResumesPlayback) {
550 test::MockMediaSession media_session_1;
551 test::MockMediaSession media_session_2;
553 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
554 EXPECT_EQ(0, GetTransientCount());
555 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
556 GetState(&media_session_1));
558 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
559 EXPECT_EQ(1, GetTransientCount());
561 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
562 GetState(&media_session_1));
564 media_session_2.AbandonAudioFocusFromClient();
565 EXPECT_EQ(0, GetTransientCount());
566 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
567 GetState(&media_session_1));
570 TEST_P(AudioFocusManagerTest, DuckWhilePlaying) {
571 test::MockMediaSession media_session_1;
572 test::MockMediaSession media_session_2;
574 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
575 EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
576 GetState(&media_session_1));
578 RequestAudioFocus(&media_session_2,
579 mojom::AudioFocusType::kGainTransientMayDuck);
580 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
581 GetState(&media_session_1));
584 TEST_P(AudioFocusManagerTest, GainSuspendsTransient) {
585 test::MockMediaSession media_session_1;
586 test::MockMediaSession media_session_2;
588 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
590 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
592 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
593 GetState(&media_session_2));
596 TEST_P(AudioFocusManagerTest, GainSuspendsTransientMayDuck) {
597 test::MockMediaSession media_session_1;
598 test::MockMediaSession media_session_2;
600 RequestAudioFocus(&media_session_2,
601 mojom::AudioFocusType::kGainTransientMayDuck);
603 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
605 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
606 GetState(&media_session_2));
609 TEST_P(AudioFocusManagerTest, DuckWithMultipleTransientMayDucks) {
610 test::MockMediaSession media_session_1;
611 test::MockMediaSession media_session_2;
612 test::MockMediaSession media_session_3;
613 test::MockMediaSession media_session_4;
615 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
616 EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
617 GetState(&media_session_1));
619 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
620 EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
621 GetState(&media_session_2));
623 RequestAudioFocus(&media_session_3,
624 mojom::AudioFocusType::kGainTransientMayDuck);
625 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
626 GetState(&media_session_1));
627 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
628 GetState(&media_session_2));
630 RequestAudioFocus(&media_session_4,
631 mojom::AudioFocusType::kGainTransientMayDuck);
632 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
633 GetState(&media_session_1));
634 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
635 GetState(&media_session_2));
637 media_session_3.AbandonAudioFocusFromClient();
638 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
639 GetState(&media_session_1));
640 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
641 GetState(&media_session_2));
643 media_session_4.AbandonAudioFocusFromClient();
644 EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
645 GetState(&media_session_1));
646 EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
647 GetState(&media_session_2));
650 TEST_P(AudioFocusManagerTest, MediaSessionDestroyed_ReleasesFocus) {
652 test::MockMediaSession media_session;
654 AudioFocusManager::RequestId request_id =
655 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
656 EXPECT_EQ(request_id, GetAudioFocusedSession());
659 // If the media session is destroyed without abandoning audio focus we do not
660 // know until we next interact with the manager.
661 test::MockMediaSession media_session;
662 RequestAudioFocus(&media_session,
663 mojom::AudioFocusType::kGainTransientMayDuck);
664 EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
667 TEST_P(AudioFocusManagerTest, MediaSessionDestroyed_ReleasesTransient) {
669 test::MockMediaSession media_session;
670 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGainTransient);
671 EXPECT_EQ(1, GetTransientCount());
674 // If the media session is destroyed without abandoning audio focus we do not
675 // know until we next interact with the manager.
676 test::MockMediaSession media_session;
677 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
678 EXPECT_EQ(0, GetTransientCount());
681 TEST_P(AudioFocusManagerTest, MediaSessionDestroyed_ReleasesTransientMayDucks) {
683 test::MockMediaSession media_session;
684 RequestAudioFocus(&media_session,
685 mojom::AudioFocusType::kGainTransientMayDuck);
686 EXPECT_EQ(1, GetTransientMaybeDuckCount());
689 // If the media session is destroyed without abandoning audio focus we do not
690 // know until we next interact with the manager.
691 test::MockMediaSession media_session;
692 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
693 EXPECT_EQ(0, GetTransientMaybeDuckCount());
696 TEST_P(AudioFocusManagerTest, GainDucksForceDuck) {
697 test::MockMediaSession media_session_1(true /* force_duck */);
698 test::MockMediaSession media_session_2;
700 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
702 AudioFocusManager::RequestId request_id_2 =
703 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
705 EXPECT_EQ(request_id_2, GetAudioFocusedSession());
706 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
707 GetState(&media_session_1));
710 TEST_P(AudioFocusManagerTest, ForceDuckSessionShouldAlwaysBeDuckedFromGain) {
711 test::MockMediaSession media_session_1(true /* force_duck */);
712 test::MockMediaSession media_session_2;
713 test::MockMediaSession media_session_3;
715 AudioFocusManager::RequestId request_id_1 =
716 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
717 AudioFocusManager::RequestId request_id_2 =
718 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
720 AudioFocusManager::RequestId request_id_3 =
721 RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGain);
722 EXPECT_EQ(request_id_3, GetAudioFocusedSession());
725 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
726 GetState(&media_session_2));
727 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
728 GetState(&media_session_1));
730 media_session_3.AbandonAudioFocusFromClient();
731 EXPECT_EQ(request_id_2, GetAudioFocusedSession());
732 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
733 GetState(&media_session_1));
735 media_session_2.AbandonAudioFocusFromClient();
736 EXPECT_EQ(request_id_1, GetAudioFocusedSession());
737 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
738 GetState(&media_session_1));
741 TEST_P(AudioFocusManagerTest,
742 ForceDuckSessionShouldAlwaysBeDuckedFromTransient) {
743 test::MockMediaSession media_session_1(true /* force_duck */);
744 test::MockMediaSession media_session_2;
746 AudioFocusManager::RequestId request_id_1 =
747 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
748 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
750 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
751 GetState(&media_session_2));
752 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
753 GetState(&media_session_1));
755 media_session_2.AbandonAudioFocusFromClient();
756 EXPECT_EQ(request_id_1, GetAudioFocusedSession());
757 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
758 GetState(&media_session_1));
761 TEST_P(AudioFocusManagerTest, AudioFocusObserver_RequestNoop) {
762 test::MockMediaSession media_session;
763 AudioFocusManager::RequestId request_id;
766 std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
768 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
770 EXPECT_EQ(request_id, GetAudioFocusedSession());
771 EXPECT_EQ(mojom::AudioFocusType::kGain,
772 observer->focus_gained_session()->audio_focus_type);
776 std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
777 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
779 EXPECT_EQ(request_id, GetAudioFocusedSession());
780 EXPECT_TRUE(observer->focus_gained_session().is_null());
784 TEST_P(AudioFocusManagerTest, AudioFocusObserver_TransientMayDuck) {
785 test::MockMediaSession media_session;
788 std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
789 RequestAudioFocus(&media_session,
790 mojom::AudioFocusType::kGainTransientMayDuck);
792 EXPECT_EQ(1, GetTransientMaybeDuckCount());
793 EXPECT_EQ(mojom::AudioFocusType::kGainTransientMayDuck,
794 observer->focus_gained_session()->audio_focus_type);
798 std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
799 media_session.AbandonAudioFocusFromClient();
801 EXPECT_EQ(0, GetTransientMaybeDuckCount());
802 EXPECT_TRUE(observer->focus_lost_session()->session_info.Equals(
803 test::GetMediaSessionInfoSync(&media_session)));
807 TEST_P(AudioFocusManagerTest, GetDebugInfo) {
808 test::MockMediaSession media_session;
809 AudioFocusManager::RequestId request_id =
810 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
812 mojom::MediaSessionDebugInfoPtr debug_info = GetDebugInfo(request_id);
813 EXPECT_FALSE(debug_info->name.empty());
814 EXPECT_FALSE(debug_info->owner.empty());
815 EXPECT_FALSE(debug_info->state.empty());
818 TEST_P(AudioFocusManagerTest, GetDebugInfo_BadRequestId) {
819 mojom::MediaSessionDebugInfoPtr debug_info =
820 GetDebugInfo(base::UnguessableToken::Create());
821 EXPECT_TRUE(debug_info->name.empty());
824 TEST_P(AudioFocusManagerTest,
825 RequestAudioFocusTransient_FromGainWhileSuspended) {
826 test::MockMediaSession media_session_1;
827 test::MockMediaSession media_session_2;
829 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
830 EXPECT_EQ(0, GetTransientCount());
831 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
832 GetState(&media_session_1));
834 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
835 EXPECT_EQ(1, GetTransientCount());
837 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
838 GetState(&media_session_1));
840 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGainTransient);
841 EXPECT_EQ(2, GetTransientCount());
842 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
843 GetState(&media_session_1));
846 TEST_P(AudioFocusManagerTest,
847 RequestAudioFocusTransientMayDuck_FromGainWhileSuspended) {
848 test::MockMediaSession media_session_1;
849 test::MockMediaSession media_session_2;
851 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
852 EXPECT_EQ(0, GetTransientCount());
853 EXPECT_EQ(0, GetTransientMaybeDuckCount());
854 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
855 GetState(&media_session_1));
857 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
858 EXPECT_EQ(1, GetTransientCount());
859 EXPECT_EQ(0, GetTransientMaybeDuckCount());
861 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
862 GetState(&media_session_1));
864 RequestAudioFocus(&media_session_1,
865 mojom::AudioFocusType::kGainTransientMayDuck);
866 EXPECT_EQ(1, GetTransientCount());
867 EXPECT_EQ(1, GetTransientMaybeDuckCount());
868 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
869 GetState(&media_session_1));
872 TEST_P(AudioFocusManagerTest, Source_AssociatedWithBinding) {
873 base::UnguessableToken identity = base::UnguessableToken::Create();
874 SetSource(identity, kExampleSourceName);
876 base::UnguessableToken new_identity = base::UnguessableToken::Create();
877 mojo::Remote<mojom::AudioFocusManager> new_ptr =
878 CreateAudioFocusManagerRemote();
879 new_ptr->SetSource(new_identity, kExampleSourceName2);
880 new_ptr.FlushForTesting();
882 test::MockMediaSession media_session_1;
883 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
884 EXPECT_EQ(kExampleSourceName, GetSourceNameForLastRequest());
885 EXPECT_EQ(identity, GetIdentityForLastRequest());
887 test::MockMediaSession media_session_2;
888 media_session_2.RequestAudioFocusFromService(new_ptr,
889 mojom::AudioFocusType::kGain);
890 EXPECT_EQ(kExampleSourceName2, GetSourceNameForLastRequest());
891 EXPECT_EQ(new_identity, GetIdentityForLastRequest());
894 TEST_P(AudioFocusManagerTest, Source_Empty) {
895 test::MockMediaSession media_session;
896 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
897 EXPECT_TRUE(GetSourceNameForLastRequest().empty());
898 EXPECT_EQ(base::UnguessableToken::Null(), GetIdentityForLastRequest());
901 TEST_P(AudioFocusManagerTest, Source_Updated) {
902 base::UnguessableToken identity = base::UnguessableToken::Create();
903 SetSource(identity, kExampleSourceName);
905 test::MockMediaSession media_session;
906 RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
907 EXPECT_EQ(kExampleSourceName, GetSourceNameForLastRequest());
908 EXPECT_EQ(identity, GetIdentityForLastRequest());
910 base::UnguessableToken new_identity = base::UnguessableToken::Create();
911 SetSource(new_identity, kExampleSourceName2);
912 EXPECT_EQ(kExampleSourceName, GetSourceNameForLastRequest());
913 EXPECT_EQ(identity, GetIdentityForLastRequest());
916 TEST_P(AudioFocusManagerTest,
917 AbandonAudioFocus_ObserverFocusGain_NoTopSession) {
918 test::MockMediaSession media_session;
920 RequestAudioFocus(&media_session,
921 mojom::AudioFocusType::kGainTransientMayDuck);
922 EXPECT_EQ(1, GetTransientMaybeDuckCount());
923 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
924 GetState(&media_session));
927 std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
928 media_session.AbandonAudioFocusFromClient();
930 EXPECT_EQ(0, GetTransientMaybeDuckCount());
931 EXPECT_TRUE(observer->focus_lost_session()->session_info.Equals(
932 test::GetMediaSessionInfoSync(&media_session)));
933 EXPECT_TRUE(observer->focus_gained_session().is_null());
935 auto notifications = observer->notifications();
936 EXPECT_EQ(1u, notifications.size());
937 EXPECT_EQ(test::TestAudioFocusObserver::NotificationType::kFocusLost,
942 TEST_P(AudioFocusManagerTest,
943 AbandonAudioFocus_ObserverFocusGain_NewTopSession) {
944 test::MockMediaSession media_session_1;
945 test::MockMediaSession media_session_2;
947 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
948 EXPECT_EQ(0, GetTransientMaybeDuckCount());
949 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
950 GetState(&media_session_1));
952 RequestAudioFocus(&media_session_2,
953 mojom::AudioFocusType::kGainTransientMayDuck);
954 EXPECT_EQ(1, GetTransientMaybeDuckCount());
955 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
956 GetState(&media_session_1));
958 mojom::MediaSessionInfoPtr media_session_1_info =
959 test::GetMediaSessionInfoSync(&media_session_1);
962 std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
963 media_session_2.AbandonAudioFocusFromClient();
965 EXPECT_EQ(0, GetTransientMaybeDuckCount());
966 EXPECT_TRUE(observer->focus_lost_session()->session_info.Equals(
967 test::GetMediaSessionInfoSync(&media_session_2)));
968 EXPECT_TRUE(observer->focus_gained_session()->session_info.Equals(
969 media_session_1_info));
971 // FocusLost should always come before FocusGained so observers always know
972 // the current session that has focus.
973 auto notifications = observer->notifications();
974 EXPECT_EQ(2u, notifications.size());
975 EXPECT_EQ(test::TestAudioFocusObserver::NotificationType::kFocusLost,
977 EXPECT_EQ(test::TestAudioFocusObserver::NotificationType::kFocusGained,
982 TEST_P(AudioFocusManagerTest, AudioFocusGrouping_LayeredFocus) {
983 test::MockMediaSession media_session_1;
984 test::MockMediaSession media_session_2;
985 test::MockMediaSession media_session_3;
987 base::UnguessableToken group_id = base::UnguessableToken::Create();
989 ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
991 mojom::AudioFocusType::kGain, group_id));
992 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
993 GetState(&media_session_1));
995 RequestAudioFocus(&media_session_2,
996 mojom::AudioFocusType::kGainTransientMayDuck);
997 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
998 GetState(&media_session_1));
1000 // When we request audio focus for media_session_3 the group will take audio
1001 // focus and we suspend the ducking session.
1002 ASSERT_TRUE(RequestGroupedAudioFocus(
1003 base::UnguessableToken::Create(), &media_session_3,
1004 mojom::AudioFocusType::kGainTransient, group_id));
1005 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1006 GetState(&media_session_3));
1009 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
1010 GetState(&media_session_2));
1011 EXPECT_EQ(GetStateFromParam(
1013 ? mojom::MediaSessionInfo::SessionState::kActive
1014 : mojom::MediaSessionInfo::SessionState::kSuspended),
1015 GetState(&media_session_1));
1018 TEST_P(AudioFocusManagerTest, AudioFocusGrouping_TransientResume) {
1019 test::MockMediaSession media_session_1;
1020 test::MockMediaSession media_session_2;
1021 test::MockMediaSession media_session_3;
1022 test::MockMediaSession media_session_4;
1024 base::UnguessableToken group_id = base::UnguessableToken::Create();
1026 ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
1028 mojom::AudioFocusType::kGain, group_id));
1029 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1030 GetState(&media_session_1));
1032 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
1033 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1034 GetState(&media_session_2));
1036 ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
1038 mojom::AudioFocusType::kGain, group_id));
1039 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1040 GetState(&media_session_3));
1042 RequestAudioFocus(&media_session_4, mojom::AudioFocusType::kGainTransient);
1044 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
1045 GetState(&media_session_1));
1047 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
1048 GetState(&media_session_2));
1050 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
1051 GetState(&media_session_3));
1053 media_session_4.AbandonAudioFocusFromClient();
1055 // TODO(https://crbug.com/916177): This should wait on a more precise
1056 // condition than RunLoop idling, but it's not clear exactly what that
1058 base::RunLoop().RunUntilIdle();
1060 EXPECT_EQ(IsGroupingEnabled()
1061 ? mojom::MediaSessionInfo::SessionState::kActive
1062 : mojom::MediaSessionInfo::SessionState::kSuspended,
1063 GetState(&media_session_1));
1065 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
1066 GetState(&media_session_2));
1067 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1068 GetState(&media_session_3));
1071 TEST_P(AudioFocusManagerTest, AudioFocusGrouping_DoNotSuspendSameGroup) {
1072 test::MockMediaSession media_session_1;
1073 test::MockMediaSession media_session_2;
1075 base::UnguessableToken group_id = base::UnguessableToken::Create();
1077 ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
1079 mojom::AudioFocusType::kGain, group_id));
1080 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1081 GetState(&media_session_1));
1083 ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
1085 mojom::AudioFocusType::kGain, group_id));
1086 EXPECT_EQ(IsGroupingEnabled()
1087 ? mojom::MediaSessionInfo::SessionState::kActive
1088 : mojom::MediaSessionInfo::SessionState::kSuspended,
1089 GetState(&media_session_1));
1090 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1091 GetState(&media_session_2));
1094 TEST_P(AudioFocusManagerTest, AudioFocusGrouping_DuckSameGroup) {
1095 test::MockMediaSession media_session_1;
1096 test::MockMediaSession media_session_2;
1098 base::UnguessableToken group_id = base::UnguessableToken::Create();
1100 ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
1102 mojom::AudioFocusType::kGain, group_id));
1103 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1104 GetState(&media_session_1));
1106 ASSERT_TRUE(RequestGroupedAudioFocus(
1107 base::UnguessableToken::Create(), &media_session_2,
1108 mojom::AudioFocusType::kGainTransientMayDuck, group_id));
1109 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
1110 GetState(&media_session_1));
1113 TEST_P(AudioFocusManagerTest, AudioFocusGrouping_TransientSameGroup) {
1114 test::MockMediaSession media_session_1;
1115 test::MockMediaSession media_session_2;
1117 base::UnguessableToken group_id = base::UnguessableToken::Create();
1119 ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
1121 mojom::AudioFocusType::kGain, group_id));
1122 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1123 GetState(&media_session_1));
1125 ASSERT_TRUE(RequestGroupedAudioFocus(
1126 base::UnguessableToken::Create(), &media_session_2,
1127 mojom::AudioFocusType::kGainTransient, group_id));
1128 EXPECT_EQ(IsGroupingEnabled()
1129 ? mojom::MediaSessionInfo::SessionState::kActive
1130 : mojom::MediaSessionInfo::SessionState::kSuspended,
1131 GetState(&media_session_1));
1132 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1133 GetState(&media_session_2));
1136 TEST_P(AudioFocusManagerTest, RequestAudioFocus_PreferStop_LossToGain) {
1137 test::MockMediaSession media_session_1;
1138 test::MockMediaSession media_session_2;
1140 media_session_1.SetPreferStop(true);
1142 AudioFocusManager::RequestId request_id_1 =
1143 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1144 EXPECT_EQ(request_id_1, GetAudioFocusedSession());
1145 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1146 GetState(&media_session_1));
1148 AudioFocusManager::RequestId request_id_2 =
1149 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
1150 EXPECT_EQ(request_id_2, GetAudioFocusedSession());
1151 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kInactive),
1152 GetState(&media_session_1));
1155 TEST_P(AudioFocusManagerTest,
1156 RequestAudioFocus_PreferStop_LossToGainTransient) {
1157 test::MockMediaSession media_session_1;
1158 test::MockMediaSession media_session_2;
1160 media_session_1.SetPreferStop(true);
1162 AudioFocusManager::RequestId request_id_1 =
1163 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1164 EXPECT_EQ(request_id_1, GetAudioFocusedSession());
1165 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1166 GetState(&media_session_1));
1168 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
1170 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
1171 GetState(&media_session_1));
1174 TEST_P(AudioFocusManagerTest, GainFocusTypeHasEffectEvenIfSuspended) {
1175 test::MockMediaSession media_session_1;
1176 test::MockMediaSession media_session_2;
1177 test::MockMediaSession media_session_3;
1179 AudioFocusManager::RequestId request_id_1 =
1180 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1181 EXPECT_EQ(request_id_1, GetAudioFocusedSession());
1183 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
1185 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
1186 GetState(&media_session_1));
1188 // When the second session becomes suspended and that event originated from
1189 // the session itself then we should keep the other session suspended.
1190 media_session_2.Suspend(mojom::MediaSession::SuspendType::kUI);
1191 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
1192 GetState(&media_session_2));
1195 test::MockMediaSessionMojoObserver observer(media_session_1);
1196 observer.WaitForState(
1197 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
1200 // When the second session is resumed then we should still keep the other
1201 // session suspended.
1202 media_session_2.Resume(mojom::MediaSession::SuspendType::kUI);
1203 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1204 GetState(&media_session_2));
1207 test::MockMediaSessionMojoObserver observer(media_session_1);
1208 observer.WaitForState(
1209 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
1212 // If a new session takes focus then this should suspend all sessions.
1213 RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGainTransient);
1216 test::MockMediaSessionMojoObserver observer(media_session_2);
1217 observer.WaitForState(
1218 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
1222 test::MockMediaSessionMojoObserver observer(media_session_1);
1223 observer.WaitForState(
1224 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
1227 // If the second session regains focus then it should suspend all sessions.
1228 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
1229 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1230 GetState(&media_session_2));
1233 test::MockMediaSessionMojoObserver observer(media_session_1);
1234 observer.WaitForState(
1235 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
1239 test::MockMediaSessionMojoObserver observer(media_session_3);
1240 observer.WaitForState(
1241 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
1245 TEST_P(AudioFocusManagerTest, TransientFocusTypeHasNoEffectIfSuspended) {
1246 test::MockMediaSession media_session_1;
1247 test::MockMediaSession media_session_2;
1248 test::MockMediaSession media_session_3;
1250 AudioFocusManager::RequestId request_id_1 =
1251 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1252 EXPECT_EQ(request_id_1, GetAudioFocusedSession());
1254 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
1256 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
1257 GetState(&media_session_1));
1259 // When the transient session becomes suspended and that event originates from
1260 // the session itself then we should stop pausing the other session.
1261 media_session_2.Suspend(mojom::MediaSession::SuspendType::kUI);
1262 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
1263 GetState(&media_session_2));
1266 test::MockMediaSessionMojoObserver observer(media_session_1);
1267 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1270 // When the transient session is resumed then we should pause the other
1272 media_session_2.Resume(mojom::MediaSession::SuspendType::kUI);
1273 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1274 GetState(&media_session_2));
1277 test::MockMediaSessionMojoObserver observer(media_session_1);
1278 observer.WaitForState(
1279 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
1282 // If we have a new session take focus then this should suspend all the other
1283 // sessions and the transient session should have no effect.
1284 RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGainTransient);
1287 test::MockMediaSessionMojoObserver observer(media_session_2);
1288 observer.WaitForState(
1289 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
1293 test::MockMediaSessionMojoObserver observer(media_session_1);
1294 observer.WaitForState(
1295 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
1298 // If the second session regains focus then it should start pausing again.
1299 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
1300 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1301 GetState(&media_session_2));
1304 test::MockMediaSessionMojoObserver observer(media_session_1);
1305 observer.WaitForState(
1306 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
1310 test::MockMediaSessionMojoObserver observer(media_session_3);
1311 observer.WaitForState(
1312 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
1316 TEST_P(AudioFocusManagerTest, TransientDuckFocusTypeHasNoEffectIfSuspended) {
1317 test::MockMediaSession media_session_1;
1318 test::MockMediaSession media_session_2;
1319 test::MockMediaSession media_session_3;
1321 AudioFocusManager::RequestId request_id_1 =
1322 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1323 EXPECT_EQ(request_id_1, GetAudioFocusedSession());
1325 RequestAudioFocus(&media_session_2,
1326 mojom::AudioFocusType::kGainTransientMayDuck);
1327 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
1328 GetState(&media_session_1));
1330 // When the ducking session becomes suspended and that event originates from
1331 // the session itself then we should stop ducking.
1332 media_session_2.Suspend(mojom::MediaSession::SuspendType::kUI);
1333 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
1334 GetState(&media_session_2));
1337 test::MockMediaSessionMojoObserver observer(media_session_1);
1338 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1341 // When the ducking session is resumed then we should resume ducking.
1342 media_session_2.Resume(mojom::MediaSession::SuspendType::kUI);
1343 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1344 GetState(&media_session_2));
1347 test::MockMediaSessionMojoObserver observer(media_session_1);
1348 observer.WaitForState(
1349 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking));
1352 // If we have a new session take focus then this should suspend all the other
1353 // sessions and we should not have any ducking from the ducking session (since
1354 // it is suspended).
1355 RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGainTransient);
1358 test::MockMediaSessionMojoObserver observer(media_session_2);
1359 observer.WaitForState(
1360 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
1364 test::MockMediaSessionMojoObserver observer(media_session_1);
1365 observer.WaitForState(
1366 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
1369 // If the ducking session regains focus then it should start ducking again.
1370 RequestAudioFocus(&media_session_2,
1371 mojom::AudioFocusType::kGainTransientMayDuck);
1372 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1373 GetState(&media_session_2));
1376 test::MockMediaSessionMojoObserver observer(media_session_1);
1377 observer.WaitForState(
1378 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking));
1382 test::MockMediaSessionMojoObserver observer(media_session_3);
1383 observer.WaitForState(
1384 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking));
1388 TEST_P(AudioFocusManagerTest, AmbientFocusHasNoEffect) {
1389 test::MockMediaSession media_session_1;
1390 test::MockMediaSession media_session_2;
1392 AudioFocusManager::RequestId request_id_1 =
1393 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1394 EXPECT_EQ(request_id_1, GetAudioFocusedSession());
1395 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1396 GetState(&media_session_1));
1398 EXPECT_EQ(0, GetAmbientCount());
1399 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kAmbient);
1401 EXPECT_EQ(1, GetAmbientCount());
1402 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1403 GetState(&media_session_1));
1404 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1405 GetState(&media_session_2));
1407 media_session_2.AbandonAudioFocusFromClient();
1409 EXPECT_EQ(0, GetAmbientCount());
1410 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1411 GetState(&media_session_1));
1414 TEST_P(AudioFocusManagerTest, AudioFocusObserver_NotTopMost) {
1415 test::MockMediaSession media_session_1;
1416 test::MockMediaSession media_session_2;
1418 AudioFocusManager::RequestId request_id_1 =
1419 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1420 EXPECT_EQ(request_id_1, GetAudioFocusedSession());
1421 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1422 GetState(&media_session_1));
1424 RequestAudioFocus(&media_session_2,
1425 mojom::AudioFocusType::kGainTransientMayDuck);
1426 EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
1427 GetState(&media_session_1));
1428 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1429 GetState(&media_session_2));
1432 std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
1433 media_session_1.AbandonAudioFocusFromClient();
1435 EXPECT_TRUE(observer->focus_lost_session()->session_info.Equals(
1436 test::GetMediaSessionInfoSync(&media_session_1)));
1440 TEST_P(AudioFocusManagerTest, SuspendAllSessionOnPowerSuspend) {
1441 test::MockMediaSession media_session_1;
1442 test::MockMediaSession media_session_2;
1445 test::MockMediaSessionMojoObserver observer(media_session_1);
1446 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1447 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1451 test::MockMediaSessionMojoObserver observer(media_session_2);
1452 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
1453 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1456 test::MockMediaSessionMojoObserver observer_1(media_session_1);
1457 test::MockMediaSessionMojoObserver observer_2(media_session_2);
1459 GenerateSuspendEvent();
1461 observer_1.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
1462 observer_2.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
1465 TEST_P(AudioFocusManagerTest, TransientPauseShouldDelayControllerPause) {
1466 test::MockMediaSession media_session_1;
1467 test::MockMediaSession media_session_2;
1469 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1470 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1471 GetState(&media_session_1));
1473 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
1475 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
1476 GetState(&media_session_1));
1478 mojo::Remote<mojom::MediaController> controller;
1479 controller_manager()->CreateMediaControllerForSession(
1480 controller.BindNewPipeAndPassReceiver(), media_session_1.request_id());
1481 controller_manager().FlushForTesting();
1483 controller->Suspend();
1484 controller.FlushForTesting();
1485 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
1486 GetState(&media_session_1));
1488 // When we abandon the transient session then we will apply the last
1489 // controller action.
1490 media_session_2.AbandonAudioFocusFromClient();
1491 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
1492 GetState(&media_session_1));
1495 TEST_P(AudioFocusManagerTest, TransientPauseShouldDelayControllerStop) {
1496 test::MockMediaSession media_session_1;
1497 test::MockMediaSession media_session_2;
1499 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1500 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1501 GetState(&media_session_1));
1503 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
1505 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
1506 GetState(&media_session_1));
1508 mojo::Remote<mojom::MediaController> controller;
1509 controller_manager()->CreateMediaControllerForSession(
1510 controller.BindNewPipeAndPassReceiver(), media_session_1.request_id());
1511 controller_manager().FlushForTesting();
1514 controller.FlushForTesting();
1516 // If enforcement is enabled then the session was previously suspended by the
1517 // transient session and therefore we should be suspended. Otherwise, we
1518 // should be inactive because the stop command would not have been delayed.
1519 EXPECT_EQ(IsEnforcementEnabled()
1520 ? mojom::MediaSessionInfo::SessionState::kSuspended
1521 : mojom::MediaSessionInfo::SessionState::kInactive,
1522 GetState(&media_session_1));
1525 // When we abandon the transient session then we will apply the last
1526 // controller action.
1527 test::MockMediaSessionMojoObserver observer(media_session_1);
1528 media_session_2.AbandonAudioFocusFromClient();
1529 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kInactive);
1533 TEST_P(AudioFocusManagerTest, TransientPauseShouldDelayControllerResume) {
1534 test::MockMediaSession media_session_1;
1535 test::MockMediaSession media_session_2;
1537 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1538 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1539 GetState(&media_session_1));
1541 mojo::Remote<mojom::MediaController> controller;
1542 controller_manager()->CreateMediaControllerForSession(
1543 controller.BindNewPipeAndPassReceiver(), media_session_1.request_id());
1544 controller_manager().FlushForTesting();
1546 controller->Suspend();
1547 controller.FlushForTesting();
1548 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
1549 GetState(&media_session_1));
1551 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
1552 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
1553 GetState(&media_session_1));
1555 controller->Resume();
1556 controller.FlushForTesting();
1558 // If enforcement is enabled then the session was previously suspended by the
1559 // transient session and therefore we should be suspended. Otherwise, we
1560 // should be active because the resume command would not have been delayed.
1562 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
1563 GetState(&media_session_1));
1566 // When we abandon the transient session then we will apply the last
1567 // controller action.
1568 test::MockMediaSessionMojoObserver observer(media_session_1);
1569 media_session_2.AbandonAudioFocusFromClient();
1570 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1574 TEST_P(AudioFocusManagerTest, TransientPauseShouldDelayLastActionOnly) {
1575 test::MockMediaSession media_session_1;
1576 test::MockMediaSession media_session_2;
1578 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1579 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
1580 GetState(&media_session_1));
1582 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
1584 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
1585 GetState(&media_session_1));
1587 mojo::Remote<mojom::MediaController> controller;
1588 controller_manager()->CreateMediaControllerForSession(
1589 controller.BindNewPipeAndPassReceiver(), media_session_1.request_id());
1590 controller_manager().FlushForTesting();
1592 controller->Resume();
1593 controller.FlushForTesting();
1595 // The resume action should be delayed because we were suspended by the
1596 // transient session.
1598 GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
1599 GetState(&media_session_1));
1601 // Calling suspend while we are still suspended should cancel the delayed
1602 // resume action so we will never resume.
1603 controller->Suspend();
1604 controller.FlushForTesting();
1605 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
1606 GetState(&media_session_1));
1608 // When we abandon the transient session then we will apply the last
1609 // controller action.
1610 media_session_2.AbandonAudioFocusFromClient();
1611 EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
1612 GetState(&media_session_1));
1615 TEST_P(AudioFocusManagerTest, RequestIdValidation) {
1616 test::MockMediaSession media_session_1;
1617 test::MockMediaSession media_session_2;
1619 base::UnguessableToken request_id = base::UnguessableToken::Create();
1621 EXPECT_TRUE(RequestGroupedAudioFocus(request_id, &media_session_1,
1622 mojom::AudioFocusType::kGain,
1623 base::UnguessableToken::Create()));
1624 EXPECT_EQ(request_id, GetAudioFocusedSession());
1626 // The audio focus request should fail since we have already used that id.
1627 EXPECT_FALSE(RequestGroupedAudioFocus(request_id, &media_session_2,
1628 mojom::AudioFocusType::kGain,
1629 base::UnguessableToken::Create()));
1631 media_session_1.AbandonAudioFocusFromClient();
1632 EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
1634 // If we abandon focus then we should be able to use the id now.
1635 EXPECT_TRUE(RequestGroupedAudioFocus(request_id, &media_session_2,
1636 mojom::AudioFocusType::kGain,
1637 base::UnguessableToken::Create()));
1638 EXPECT_EQ(request_id, GetAudioFocusedSession());
1641 TEST_P(AudioFocusManagerTest, SourceObservers) {
1642 // Create two identity observers for two different identities.
1643 base::UnguessableToken identity_1 = base::UnguessableToken::Create();
1644 base::UnguessableToken identity_2 = base::UnguessableToken::Create();
1645 std::unique_ptr<test::TestAudioFocusObserver> observer_1 =
1646 CreateSourceObserver(identity_1);
1647 std::unique_ptr<test::TestAudioFocusObserver> observer_2 =
1648 CreateSourceObserver(identity_2);
1650 // Request audio focus for the first identity.
1651 SetSource(identity_1, kExampleSourceName);
1652 test::MockMediaSession media_session_1;
1653 base::UnguessableToken request_id_1 =
1654 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1656 // The observer for the first identity should see the gained focus, while the
1657 // observer for the second identity should see nothing.
1658 EXPECT_EQ(request_id_1, observer_1->focus_gained_session()->request_id);
1659 EXPECT_TRUE(observer_2->focus_gained_session().is_null());
1661 // Request audio focus for the second identity.
1662 SetSource(identity_2, kExampleSourceName);
1663 test::MockMediaSession media_session_2;
1664 base::UnguessableToken request_id_2 =
1665 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
1667 // The observer for the first identity should still show the first request,
1668 // while the observer for the second identity should see the new session.
1669 EXPECT_EQ(request_id_1, observer_1->focus_gained_session()->request_id);
1670 EXPECT_EQ(request_id_2, observer_2->focus_gained_session()->request_id);
1672 // Make another request in the second identity.
1673 test::MockMediaSession media_session_3;
1674 base::UnguessableToken request_id_3 =
1675 RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGain);
1677 // The observer for the first identity should still show the first request,
1678 // while the observer for the second identity should see the new session.
1679 EXPECT_EQ(request_id_1, observer_1->focus_gained_session()->request_id);
1680 EXPECT_EQ(request_id_3, observer_2->focus_gained_session()->request_id);
1682 // Abandon the topmost session.
1683 media_session_3.AbandonAudioFocusFromClient();
1686 // The observer for the second identity should get the new lost and gained
1687 // sessions, with no updates to the first observer.
1688 EXPECT_EQ(request_id_3, observer_2->focus_lost_session()->request_id);
1689 EXPECT_EQ(request_id_2, observer_2->focus_gained_session()->request_id);
1690 EXPECT_EQ(request_id_1, observer_1->focus_gained_session()->request_id);
1691 EXPECT_TRUE(observer_1->focus_lost_session().is_null());
1694 TEST_P(AudioFocusManagerTest, GetSourceFocusRequests) {
1695 // Establish identities.
1696 base::UnguessableToken identity_1 = base::UnguessableToken::Create();
1697 base::UnguessableToken identity_2 = base::UnguessableToken::Create();
1698 base::UnguessableToken identity_3 = base::UnguessableToken::Create();
1700 // Create a focus request for the first identity.
1701 SetSource(identity_1, kExampleSourceName);
1702 test::MockMediaSession media_session_1;
1703 base::UnguessableToken request_id_1 =
1704 RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
1706 // Create a focus request for the second identity.
1707 SetSource(identity_2, kExampleSourceName);
1708 test::MockMediaSession media_session_2;
1709 base::UnguessableToken request_id_2 =
1710 RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
1712 // Create another focus request for the first identity.
1713 SetSource(identity_1, kExampleSourceName);
1714 test::MockMediaSession media_session_3;
1715 base::UnguessableToken request_id_3 =
1716 RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGain);
1718 // Use the GetSourceFocusRequests API to get requests for each identity.
1719 std::vector<mojom::AudioFocusRequestStatePtr> identity_1_requests =
1720 GetSourceFocusRequests(identity_1);
1721 std::vector<mojom::AudioFocusRequestStatePtr> identity_2_requests =
1722 GetSourceFocusRequests(identity_2);
1723 std::vector<mojom::AudioFocusRequestStatePtr> identity_3_requests =
1724 GetSourceFocusRequests(identity_3);
1726 // Ensure that the API returned the right requests for the first identity.
1727 EXPECT_EQ(2u, identity_1_requests.size());
1728 EXPECT_EQ(request_id_1, identity_1_requests[0]->request_id);
1729 EXPECT_EQ(request_id_3, identity_1_requests[1]->request_id);
1731 // Ensure that the API returned the right requests for the second identity.
1732 EXPECT_EQ(1u, identity_2_requests.size());
1733 EXPECT_EQ(request_id_2, identity_2_requests[0]->request_id);
1735 // Ensure that the API returned nothing for the unused identity.
1736 EXPECT_TRUE(identity_3_requests.empty());
1739 } // namespace media_session