audio_focus_manager_unittest.cc 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "services/media_session/audio_focus_manager.h"
  5. #include <memory>
  6. #include <utility>
  7. #include <vector>
  8. #include "base/bind.h"
  9. #include "base/callback.h"
  10. #include "base/containers/adapters.h"
  11. #include "base/run_loop.h"
  12. #include "base/test/power_monitor_test.h"
  13. #include "base/test/task_environment.h"
  14. #include "build/build_config.h"
  15. #include "build/chromeos_buildflags.h"
  16. #include "mojo/public/cpp/bindings/remote.h"
  17. #include "services/media_session/audio_focus_request.h"
  18. #include "services/media_session/media_session_service_impl.h"
  19. #include "services/media_session/public/cpp/test/audio_focus_test_util.h"
  20. #include "services/media_session/public/cpp/test/mock_media_session.h"
  21. #include "services/media_session/public/mojom/audio_focus.mojom.h"
  22. #include "services/media_session/public/mojom/media_session.mojom.h"
  23. #include "testing/gtest/include/gtest/gtest.h"
  24. namespace media_session {
  25. namespace {
  26. const char kExampleSourceName[] = "test";
  27. const char kExampleSourceName2[] = "test2";
  28. } // anonymous namespace
  29. // This tests the Audio Focus Manager API. The parameter determines whether
  30. // audio focus is enabled or not. If it is not enabled it should track the media
  31. // sessions but not enforce single session focus.
  32. class AudioFocusManagerTest
  33. : public testing::TestWithParam<mojom::EnforcementMode> {
  34. public:
  35. AudioFocusManagerTest() = default;
  36. AudioFocusManagerTest(const AudioFocusManagerTest&) = delete;
  37. AudioFocusManagerTest& operator=(const AudioFocusManagerTest&) = delete;
  38. void SetUp() override {
  39. // Create an instance of the MediaSessionService.
  40. service_ = std::make_unique<MediaSessionServiceImpl>();
  41. service_->BindAudioFocusManager(
  42. audio_focus_remote_.BindNewPipeAndPassReceiver());
  43. service_->BindAudioFocusManagerDebug(
  44. audio_focus_debug_remote_.BindNewPipeAndPassReceiver());
  45. service_->BindMediaControllerManager(
  46. controller_manager_remote_.BindNewPipeAndPassReceiver());
  47. audio_focus_remote_->SetEnforcementMode(GetParam());
  48. audio_focus_remote_.FlushForTesting();
  49. }
  50. void TearDown() override {
  51. // Run pending tasks.
  52. base::RunLoop().RunUntilIdle();
  53. service_.reset();
  54. }
  55. AudioFocusManager::RequestId GetAudioFocusedSession() {
  56. const auto audio_focus_requests = GetRequests();
  57. for (const auto& request : base::Reversed(audio_focus_requests)) {
  58. if (request->audio_focus_type == mojom::AudioFocusType::kGain)
  59. return request->request_id.value();
  60. }
  61. return base::UnguessableToken::Null();
  62. }
  63. int GetTransientCount() {
  64. return GetCountForType(mojom::AudioFocusType::kGainTransient);
  65. }
  66. int GetTransientMaybeDuckCount() {
  67. return GetCountForType(mojom::AudioFocusType::kGainTransientMayDuck);
  68. }
  69. int GetAmbientCount() {
  70. return GetCountForType(mojom::AudioFocusType::kAmbient);
  71. }
  72. void AbandonAudioFocusNoReset(test::MockMediaSession* session) {
  73. session->audio_focus_request()->AbandonAudioFocus();
  74. session->FlushForTesting();
  75. audio_focus_remote_.FlushForTesting();
  76. }
  77. AudioFocusManager::RequestId RequestAudioFocus(
  78. test::MockMediaSession* session,
  79. mojom::AudioFocusType audio_focus_type) {
  80. return session->RequestAudioFocusFromService(audio_focus_remote_,
  81. audio_focus_type);
  82. }
  83. bool RequestGroupedAudioFocus(const base::UnguessableToken& request_id,
  84. test::MockMediaSession* session,
  85. mojom::AudioFocusType audio_focus_type,
  86. const base::UnguessableToken& group_id) {
  87. return session->RequestGroupedAudioFocusFromService(
  88. request_id, audio_focus_remote_, audio_focus_type, group_id);
  89. }
  90. mojom::MediaSessionDebugInfoPtr GetDebugInfo(
  91. AudioFocusManager::RequestId request_id) {
  92. mojom::MediaSessionDebugInfoPtr result;
  93. base::OnceCallback<void(mojom::MediaSessionDebugInfoPtr)> callback =
  94. base::BindOnce(
  95. [](mojom::MediaSessionDebugInfoPtr* out_result,
  96. mojom::MediaSessionDebugInfoPtr result) {
  97. *out_result = std::move(result);
  98. },
  99. &result);
  100. GetDebugService()->GetDebugInfoForRequest(request_id, std::move(callback));
  101. audio_focus_remote_.FlushForTesting();
  102. audio_focus_debug_remote_.FlushForTesting();
  103. return result;
  104. }
  105. mojom::MediaSessionInfo::SessionState GetState(
  106. test::MockMediaSession* session) {
  107. mojom::MediaSessionInfo::SessionState state = session->GetState();
  108. if (!IsEnforcementEnabled()) {
  109. // If audio focus enforcement is disabled then we should never see ducking
  110. // in the tests.
  111. EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking, state);
  112. }
  113. return state;
  114. }
  115. std::unique_ptr<test::TestAudioFocusObserver> CreateObserver() {
  116. std::unique_ptr<test::TestAudioFocusObserver> observer =
  117. std::make_unique<test::TestAudioFocusObserver>();
  118. GetService()->AddObserver(observer->BindNewPipeAndPassRemote());
  119. audio_focus_remote_.FlushForTesting();
  120. return observer;
  121. }
  122. std::unique_ptr<test::TestAudioFocusObserver> CreateSourceObserver(
  123. const base::UnguessableToken& source_id) {
  124. std::unique_ptr<test::TestAudioFocusObserver> observer =
  125. std::make_unique<test::TestAudioFocusObserver>();
  126. GetService()->AddSourceObserver(source_id,
  127. observer->BindNewPipeAndPassRemote());
  128. audio_focus_remote_.FlushForTesting();
  129. return observer;
  130. }
  131. mojom::MediaSessionInfo::SessionState GetStateFromParam(
  132. mojom::MediaSessionInfo::SessionState state) {
  133. // If enforcement is enabled then returns the provided state, otherwise
  134. // returns kActive because without enforcement we did not change state.
  135. if (IsEnforcementEnabled())
  136. return state;
  137. return mojom::MediaSessionInfo::SessionState::kActive;
  138. }
  139. void SetSource(const base::UnguessableToken& identity,
  140. const std::string& name) {
  141. GetService()->SetSource(identity, name);
  142. audio_focus_remote_.FlushForTesting();
  143. }
  144. mojo::Remote<mojom::AudioFocusManager> CreateAudioFocusManagerRemote() {
  145. mojo::Remote<mojom::AudioFocusManager> remote;
  146. service_->BindAudioFocusManager(remote.BindNewPipeAndPassReceiver());
  147. return remote;
  148. }
  149. const std::string GetSourceNameForLastRequest() {
  150. std::vector<mojom::AudioFocusRequestStatePtr> requests = GetRequests();
  151. EXPECT_TRUE(requests.back());
  152. return requests.back()->source_name.value();
  153. }
  154. bool IsEnforcementEnabled() const {
  155. #if BUILDFLAG(IS_CHROMEOS_ASH)
  156. // Enforcement is enabled by default on Chrome OS.
  157. if (GetParam() == mojom::EnforcementMode::kDefault)
  158. return true;
  159. #endif
  160. return GetParam() == mojom::EnforcementMode::kSingleSession ||
  161. GetParam() == mojom::EnforcementMode::kSingleGroup;
  162. }
  163. bool IsGroupingEnabled() const {
  164. return GetParam() != mojom::EnforcementMode::kSingleSession;
  165. }
  166. void GenerateSuspendEvent() { power_source_.GenerateSuspendEvent(); }
  167. mojo::Remote<mojom::MediaControllerManager>& controller_manager() {
  168. return controller_manager_remote_;
  169. }
  170. std::vector<mojom::AudioFocusRequestStatePtr> GetSourceFocusRequests(
  171. const base::UnguessableToken& source_id) {
  172. std::vector<mojom::AudioFocusRequestStatePtr> result;
  173. GetService()->GetSourceFocusRequests(
  174. source_id,
  175. base::BindOnce(
  176. [](std::vector<mojom::AudioFocusRequestStatePtr>* out,
  177. std::vector<mojom::AudioFocusRequestStatePtr> requests) {
  178. *out = std::move(requests);
  179. },
  180. &result));
  181. audio_focus_remote_.FlushForTesting();
  182. return result;
  183. }
  184. const base::UnguessableToken& GetIdentityForLastRequest() const {
  185. return service_->audio_focus_manager_for_testing()
  186. .audio_focus_stack_.back()
  187. ->identity();
  188. }
  189. void FlushForTesting() { audio_focus_remote_.FlushForTesting(); }
  190. private:
  191. int GetCountForType(mojom::AudioFocusType type) {
  192. const auto audio_focus_requests = GetRequests();
  193. return std::count_if(audio_focus_requests.begin(),
  194. audio_focus_requests.end(),
  195. [type](const auto& session) {
  196. return session->audio_focus_type == type;
  197. });
  198. }
  199. std::vector<mojom::AudioFocusRequestStatePtr> GetRequests() {
  200. std::vector<mojom::AudioFocusRequestStatePtr> result;
  201. GetService()->GetFocusRequests(base::BindOnce(
  202. [](std::vector<mojom::AudioFocusRequestStatePtr>* out,
  203. std::vector<mojom::AudioFocusRequestStatePtr> requests) {
  204. for (auto& request : requests)
  205. out->push_back(request.Clone());
  206. },
  207. &result));
  208. audio_focus_remote_.FlushForTesting();
  209. return result;
  210. }
  211. mojom::AudioFocusManager* GetService() const {
  212. return audio_focus_remote_.get();
  213. }
  214. mojom::AudioFocusManagerDebug* GetDebugService() const {
  215. return audio_focus_debug_remote_.get();
  216. }
  217. void FlushForTestingIfEnabled() {
  218. if (!IsEnforcementEnabled())
  219. return;
  220. audio_focus_remote_.FlushForTesting();
  221. }
  222. base::test::TaskEnvironment task_environment_;
  223. std::unique_ptr<MediaSessionServiceImpl> service_;
  224. mojo::Remote<mojom::AudioFocusManager> audio_focus_remote_;
  225. mojo::Remote<mojom::AudioFocusManagerDebug> audio_focus_debug_remote_;
  226. mojo::Remote<mojom::MediaControllerManager> controller_manager_remote_;
  227. base::test::ScopedPowerMonitorTestSource power_source_;
  228. };
  229. INSTANTIATE_TEST_SUITE_P(
  230. All,
  231. AudioFocusManagerTest,
  232. testing::Values(mojom::EnforcementMode::kDefault,
  233. mojom::EnforcementMode::kNone,
  234. mojom::EnforcementMode::kSingleGroup,
  235. mojom::EnforcementMode::kSingleSession));
  236. TEST_P(AudioFocusManagerTest, RequestAudioFocusGain_ReplaceFocusedEntry) {
  237. test::MockMediaSession media_session_1;
  238. test::MockMediaSession media_session_2;
  239. test::MockMediaSession media_session_3;
  240. EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
  241. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kInactive,
  242. GetState(&media_session_1));
  243. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kInactive,
  244. GetState(&media_session_2));
  245. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kInactive,
  246. GetState(&media_session_3));
  247. AudioFocusManager::RequestId request_id_1 =
  248. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  249. EXPECT_EQ(request_id_1, GetAudioFocusedSession());
  250. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  251. GetState(&media_session_1));
  252. AudioFocusManager::RequestId request_id_2 =
  253. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
  254. EXPECT_EQ(request_id_2, GetAudioFocusedSession());
  255. EXPECT_EQ(
  256. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  257. GetState(&media_session_1));
  258. AudioFocusManager::RequestId request_id_3 =
  259. RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGain);
  260. EXPECT_EQ(request_id_3, GetAudioFocusedSession());
  261. EXPECT_EQ(
  262. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  263. GetState(&media_session_2));
  264. }
  265. TEST_P(AudioFocusManagerTest, RequestAudioFocusGain_Duplicate) {
  266. test::MockMediaSession media_session;
  267. EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
  268. AudioFocusManager::RequestId request_id =
  269. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  270. EXPECT_EQ(request_id, GetAudioFocusedSession());
  271. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  272. EXPECT_EQ(request_id, GetAudioFocusedSession());
  273. }
  274. TEST_P(AudioFocusManagerTest, RequestAudioFocusGain_FromTransient) {
  275. test::MockMediaSession media_session;
  276. AudioFocusManager::RequestId request_id =
  277. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGainTransient);
  278. EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
  279. EXPECT_EQ(1, GetTransientCount());
  280. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  281. EXPECT_EQ(request_id, GetAudioFocusedSession());
  282. EXPECT_EQ(0, GetTransientCount());
  283. }
  284. TEST_P(AudioFocusManagerTest, RequestAudioFocusGain_FromTransientMayDuck) {
  285. test::MockMediaSession media_session;
  286. AudioFocusManager::RequestId request_id = RequestAudioFocus(
  287. &media_session, mojom::AudioFocusType::kGainTransientMayDuck);
  288. EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
  289. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  290. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  291. EXPECT_EQ(request_id, GetAudioFocusedSession());
  292. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  293. }
  294. TEST_P(AudioFocusManagerTest, RequestAudioFocusTransient_FromGain) {
  295. test::MockMediaSession media_session;
  296. AudioFocusManager::RequestId request_id =
  297. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  298. EXPECT_EQ(request_id, GetAudioFocusedSession());
  299. EXPECT_EQ(0, GetTransientCount());
  300. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGainTransient);
  301. EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
  302. EXPECT_EQ(1, GetTransientCount());
  303. EXPECT_NE(mojom::MediaSessionInfo::SessionState::kSuspended,
  304. GetState(&media_session));
  305. }
  306. TEST_P(AudioFocusManagerTest, RequestAudioFocusTransientMayDuck_FromGain) {
  307. test::MockMediaSession media_session;
  308. AudioFocusManager::RequestId request_id =
  309. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  310. EXPECT_EQ(request_id, GetAudioFocusedSession());
  311. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  312. RequestAudioFocus(&media_session,
  313. mojom::AudioFocusType::kGainTransientMayDuck);
  314. EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
  315. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  316. EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
  317. GetState(&media_session));
  318. }
  319. TEST_P(AudioFocusManagerTest, RequestAudioFocusTransient_FromGainWhileDucking) {
  320. test::MockMediaSession media_session_1;
  321. test::MockMediaSession media_session_2;
  322. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  323. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  324. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  325. GetState(&media_session_1));
  326. RequestAudioFocus(&media_session_2,
  327. mojom::AudioFocusType::kGainTransientMayDuck);
  328. EXPECT_EQ(0, GetTransientCount());
  329. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  330. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  331. GetState(&media_session_1));
  332. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGainTransient);
  333. EXPECT_EQ(1, GetTransientCount());
  334. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  335. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  336. GetState(&media_session_1));
  337. }
  338. TEST_P(AudioFocusManagerTest,
  339. RequestAudioFocusTransientMayDuck_FromGainWhileDucking) {
  340. test::MockMediaSession media_session_1;
  341. test::MockMediaSession media_session_2;
  342. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  343. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  344. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  345. GetState(&media_session_1));
  346. RequestAudioFocus(&media_session_2,
  347. mojom::AudioFocusType::kGainTransientMayDuck);
  348. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  349. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  350. GetState(&media_session_1));
  351. RequestAudioFocus(&media_session_1,
  352. mojom::AudioFocusType::kGainTransientMayDuck);
  353. EXPECT_EQ(2, GetTransientMaybeDuckCount());
  354. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  355. GetState(&media_session_1));
  356. }
  357. TEST_P(AudioFocusManagerTest, AbandonAudioFocus_RemovesFocusedEntry) {
  358. test::MockMediaSession media_session;
  359. AudioFocusManager::RequestId request_id =
  360. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  361. EXPECT_EQ(request_id, GetAudioFocusedSession());
  362. media_session.AbandonAudioFocusFromClient();
  363. EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
  364. }
  365. TEST_P(AudioFocusManagerTest, AbandonAudioFocus_MultipleCalls) {
  366. test::MockMediaSession media_session;
  367. AudioFocusManager::RequestId request_id =
  368. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  369. EXPECT_EQ(request_id, GetAudioFocusedSession());
  370. AbandonAudioFocusNoReset(&media_session);
  371. std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
  372. media_session.AbandonAudioFocusFromClient();
  373. EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
  374. EXPECT_TRUE(observer->focus_lost_session().is_null());
  375. }
  376. TEST_P(AudioFocusManagerTest, AbandonAudioFocus_RemovesTransientMayDuckEntry) {
  377. test::MockMediaSession media_session;
  378. RequestAudioFocus(&media_session,
  379. mojom::AudioFocusType::kGainTransientMayDuck);
  380. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  381. {
  382. std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
  383. media_session.AbandonAudioFocusFromClient();
  384. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  385. EXPECT_TRUE(observer->focus_lost_session()->session_info.Equals(
  386. test::GetMediaSessionInfoSync(&media_session)));
  387. }
  388. }
  389. TEST_P(AudioFocusManagerTest, AbandonAudioFocus_RemovesTransientEntry) {
  390. test::MockMediaSession media_session;
  391. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGainTransient);
  392. EXPECT_EQ(1, GetTransientCount());
  393. {
  394. std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
  395. media_session.AbandonAudioFocusFromClient();
  396. EXPECT_EQ(0, GetTransientCount());
  397. EXPECT_TRUE(observer->focus_lost_session()->session_info.Equals(
  398. test::GetMediaSessionInfoSync(&media_session)));
  399. }
  400. }
  401. TEST_P(AudioFocusManagerTest, AbandonAudioFocus_WhileDuckingThenResume) {
  402. test::MockMediaSession media_session_1;
  403. test::MockMediaSession media_session_2;
  404. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  405. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  406. EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
  407. GetState(&media_session_1));
  408. RequestAudioFocus(&media_session_2,
  409. mojom::AudioFocusType::kGainTransientMayDuck);
  410. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  411. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  412. GetState(&media_session_1));
  413. media_session_1.AbandonAudioFocusFromClient();
  414. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  415. media_session_2.AbandonAudioFocusFromClient();
  416. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  417. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  418. EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
  419. GetState(&media_session_1));
  420. }
  421. TEST_P(AudioFocusManagerTest, AbandonAudioFocus_StopsDucking) {
  422. test::MockMediaSession media_session_1;
  423. test::MockMediaSession media_session_2;
  424. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  425. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  426. EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
  427. GetState(&media_session_1));
  428. RequestAudioFocus(&media_session_2,
  429. mojom::AudioFocusType::kGainTransientMayDuck);
  430. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  431. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  432. GetState(&media_session_1));
  433. media_session_2.AbandonAudioFocusFromClient();
  434. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  435. EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
  436. GetState(&media_session_1));
  437. }
  438. TEST_P(AudioFocusManagerTest, AbandonAudioFocus_ResumesPlayback) {
  439. test::MockMediaSession media_session_1;
  440. test::MockMediaSession media_session_2;
  441. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  442. EXPECT_EQ(0, GetTransientCount());
  443. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  444. GetState(&media_session_1));
  445. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
  446. EXPECT_EQ(1, GetTransientCount());
  447. EXPECT_EQ(
  448. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  449. GetState(&media_session_1));
  450. media_session_2.AbandonAudioFocusFromClient();
  451. EXPECT_EQ(0, GetTransientCount());
  452. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  453. GetState(&media_session_1));
  454. }
  455. TEST_P(AudioFocusManagerTest, DuckWhilePlaying) {
  456. test::MockMediaSession media_session_1;
  457. test::MockMediaSession media_session_2;
  458. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  459. EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
  460. GetState(&media_session_1));
  461. RequestAudioFocus(&media_session_2,
  462. mojom::AudioFocusType::kGainTransientMayDuck);
  463. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  464. GetState(&media_session_1));
  465. }
  466. TEST_P(AudioFocusManagerTest, GainSuspendsTransient) {
  467. test::MockMediaSession media_session_1;
  468. test::MockMediaSession media_session_2;
  469. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
  470. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  471. EXPECT_EQ(
  472. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  473. GetState(&media_session_2));
  474. }
  475. TEST_P(AudioFocusManagerTest, GainSuspendsTransientMayDuck) {
  476. test::MockMediaSession media_session_1;
  477. test::MockMediaSession media_session_2;
  478. RequestAudioFocus(&media_session_2,
  479. mojom::AudioFocusType::kGainTransientMayDuck);
  480. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  481. EXPECT_EQ(
  482. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  483. GetState(&media_session_2));
  484. }
  485. TEST_P(AudioFocusManagerTest, DuckWithMultipleTransientMayDucks) {
  486. test::MockMediaSession media_session_1;
  487. test::MockMediaSession media_session_2;
  488. test::MockMediaSession media_session_3;
  489. test::MockMediaSession media_session_4;
  490. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  491. EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
  492. GetState(&media_session_1));
  493. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
  494. EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
  495. GetState(&media_session_2));
  496. RequestAudioFocus(&media_session_3,
  497. mojom::AudioFocusType::kGainTransientMayDuck);
  498. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  499. GetState(&media_session_1));
  500. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  501. GetState(&media_session_2));
  502. RequestAudioFocus(&media_session_4,
  503. mojom::AudioFocusType::kGainTransientMayDuck);
  504. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  505. GetState(&media_session_1));
  506. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  507. GetState(&media_session_2));
  508. media_session_3.AbandonAudioFocusFromClient();
  509. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  510. GetState(&media_session_1));
  511. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  512. GetState(&media_session_2));
  513. media_session_4.AbandonAudioFocusFromClient();
  514. EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
  515. GetState(&media_session_1));
  516. EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking,
  517. GetState(&media_session_2));
  518. }
  519. TEST_P(AudioFocusManagerTest, MediaSessionDestroyed_ReleasesFocus) {
  520. {
  521. test::MockMediaSession media_session;
  522. AudioFocusManager::RequestId request_id =
  523. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  524. EXPECT_EQ(request_id, GetAudioFocusedSession());
  525. }
  526. // If the media session is destroyed without abandoning audio focus we do not
  527. // know until we next interact with the manager.
  528. test::MockMediaSession media_session;
  529. RequestAudioFocus(&media_session,
  530. mojom::AudioFocusType::kGainTransientMayDuck);
  531. EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
  532. }
  533. TEST_P(AudioFocusManagerTest, MediaSessionDestroyed_ReleasesTransient) {
  534. {
  535. test::MockMediaSession media_session;
  536. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGainTransient);
  537. EXPECT_EQ(1, GetTransientCount());
  538. }
  539. // If the media session is destroyed without abandoning audio focus we do not
  540. // know until we next interact with the manager.
  541. test::MockMediaSession media_session;
  542. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  543. EXPECT_EQ(0, GetTransientCount());
  544. }
  545. TEST_P(AudioFocusManagerTest, MediaSessionDestroyed_ReleasesTransientMayDucks) {
  546. {
  547. test::MockMediaSession media_session;
  548. RequestAudioFocus(&media_session,
  549. mojom::AudioFocusType::kGainTransientMayDuck);
  550. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  551. }
  552. // If the media session is destroyed without abandoning audio focus we do not
  553. // know until we next interact with the manager.
  554. test::MockMediaSession media_session;
  555. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  556. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  557. }
  558. TEST_P(AudioFocusManagerTest, GainDucksForceDuck) {
  559. test::MockMediaSession media_session_1(true /* force_duck */);
  560. test::MockMediaSession media_session_2;
  561. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  562. AudioFocusManager::RequestId request_id_2 =
  563. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
  564. EXPECT_EQ(request_id_2, GetAudioFocusedSession());
  565. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  566. GetState(&media_session_1));
  567. }
  568. TEST_P(AudioFocusManagerTest, ForceDuckSessionShouldAlwaysBeDuckedFromGain) {
  569. test::MockMediaSession media_session_1(true /* force_duck */);
  570. test::MockMediaSession media_session_2;
  571. test::MockMediaSession media_session_3;
  572. AudioFocusManager::RequestId request_id_1 =
  573. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  574. AudioFocusManager::RequestId request_id_2 =
  575. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
  576. AudioFocusManager::RequestId request_id_3 =
  577. RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGain);
  578. EXPECT_EQ(request_id_3, GetAudioFocusedSession());
  579. EXPECT_EQ(
  580. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  581. GetState(&media_session_2));
  582. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  583. GetState(&media_session_1));
  584. media_session_3.AbandonAudioFocusFromClient();
  585. EXPECT_EQ(request_id_2, GetAudioFocusedSession());
  586. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  587. GetState(&media_session_1));
  588. media_session_2.AbandonAudioFocusFromClient();
  589. EXPECT_EQ(request_id_1, GetAudioFocusedSession());
  590. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  591. GetState(&media_session_1));
  592. }
  593. TEST_P(AudioFocusManagerTest,
  594. ForceDuckSessionShouldAlwaysBeDuckedFromTransient) {
  595. test::MockMediaSession media_session_1(true /* force_duck */);
  596. test::MockMediaSession media_session_2;
  597. AudioFocusManager::RequestId request_id_1 =
  598. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  599. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
  600. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  601. GetState(&media_session_2));
  602. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  603. GetState(&media_session_1));
  604. media_session_2.AbandonAudioFocusFromClient();
  605. EXPECT_EQ(request_id_1, GetAudioFocusedSession());
  606. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  607. GetState(&media_session_1));
  608. }
  609. TEST_P(AudioFocusManagerTest, AudioFocusObserver_RequestNoop) {
  610. test::MockMediaSession media_session;
  611. AudioFocusManager::RequestId request_id;
  612. {
  613. std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
  614. request_id =
  615. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  616. EXPECT_EQ(request_id, GetAudioFocusedSession());
  617. EXPECT_EQ(mojom::AudioFocusType::kGain,
  618. observer->focus_gained_session()->audio_focus_type);
  619. }
  620. {
  621. std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
  622. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  623. EXPECT_EQ(request_id, GetAudioFocusedSession());
  624. EXPECT_TRUE(observer->focus_gained_session().is_null());
  625. }
  626. }
  627. TEST_P(AudioFocusManagerTest, AudioFocusObserver_TransientMayDuck) {
  628. test::MockMediaSession media_session;
  629. {
  630. std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
  631. RequestAudioFocus(&media_session,
  632. mojom::AudioFocusType::kGainTransientMayDuck);
  633. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  634. EXPECT_EQ(mojom::AudioFocusType::kGainTransientMayDuck,
  635. observer->focus_gained_session()->audio_focus_type);
  636. }
  637. {
  638. std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
  639. media_session.AbandonAudioFocusFromClient();
  640. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  641. EXPECT_TRUE(observer->focus_lost_session()->session_info.Equals(
  642. test::GetMediaSessionInfoSync(&media_session)));
  643. }
  644. }
  645. TEST_P(AudioFocusManagerTest, GetDebugInfo) {
  646. test::MockMediaSession media_session;
  647. AudioFocusManager::RequestId request_id =
  648. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  649. mojom::MediaSessionDebugInfoPtr debug_info = GetDebugInfo(request_id);
  650. EXPECT_FALSE(debug_info->name.empty());
  651. EXPECT_FALSE(debug_info->owner.empty());
  652. EXPECT_FALSE(debug_info->state.empty());
  653. }
  654. TEST_P(AudioFocusManagerTest, GetDebugInfo_BadRequestId) {
  655. mojom::MediaSessionDebugInfoPtr debug_info =
  656. GetDebugInfo(base::UnguessableToken::Create());
  657. EXPECT_TRUE(debug_info->name.empty());
  658. }
  659. TEST_P(AudioFocusManagerTest,
  660. RequestAudioFocusTransient_FromGainWhileSuspended) {
  661. test::MockMediaSession media_session_1;
  662. test::MockMediaSession media_session_2;
  663. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  664. EXPECT_EQ(0, GetTransientCount());
  665. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  666. GetState(&media_session_1));
  667. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
  668. EXPECT_EQ(1, GetTransientCount());
  669. EXPECT_EQ(
  670. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  671. GetState(&media_session_1));
  672. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGainTransient);
  673. EXPECT_EQ(2, GetTransientCount());
  674. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  675. GetState(&media_session_1));
  676. }
  677. TEST_P(AudioFocusManagerTest,
  678. RequestAudioFocusTransientMayDuck_FromGainWhileSuspended) {
  679. test::MockMediaSession media_session_1;
  680. test::MockMediaSession media_session_2;
  681. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  682. EXPECT_EQ(0, GetTransientCount());
  683. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  684. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  685. GetState(&media_session_1));
  686. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
  687. EXPECT_EQ(1, GetTransientCount());
  688. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  689. EXPECT_EQ(
  690. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  691. GetState(&media_session_1));
  692. RequestAudioFocus(&media_session_1,
  693. mojom::AudioFocusType::kGainTransientMayDuck);
  694. EXPECT_EQ(1, GetTransientCount());
  695. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  696. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  697. GetState(&media_session_1));
  698. }
  699. TEST_P(AudioFocusManagerTest, Source_AssociatedWithBinding) {
  700. base::UnguessableToken identity = base::UnguessableToken::Create();
  701. SetSource(identity, kExampleSourceName);
  702. base::UnguessableToken new_identity = base::UnguessableToken::Create();
  703. mojo::Remote<mojom::AudioFocusManager> new_ptr =
  704. CreateAudioFocusManagerRemote();
  705. new_ptr->SetSource(new_identity, kExampleSourceName2);
  706. new_ptr.FlushForTesting();
  707. test::MockMediaSession media_session_1;
  708. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  709. EXPECT_EQ(kExampleSourceName, GetSourceNameForLastRequest());
  710. EXPECT_EQ(identity, GetIdentityForLastRequest());
  711. test::MockMediaSession media_session_2;
  712. media_session_2.RequestAudioFocusFromService(new_ptr,
  713. mojom::AudioFocusType::kGain);
  714. EXPECT_EQ(kExampleSourceName2, GetSourceNameForLastRequest());
  715. EXPECT_EQ(new_identity, GetIdentityForLastRequest());
  716. }
  717. TEST_P(AudioFocusManagerTest, Source_Empty) {
  718. test::MockMediaSession media_session;
  719. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  720. EXPECT_TRUE(GetSourceNameForLastRequest().empty());
  721. EXPECT_EQ(base::UnguessableToken::Null(), GetIdentityForLastRequest());
  722. }
  723. TEST_P(AudioFocusManagerTest, Source_Updated) {
  724. base::UnguessableToken identity = base::UnguessableToken::Create();
  725. SetSource(identity, kExampleSourceName);
  726. test::MockMediaSession media_session;
  727. RequestAudioFocus(&media_session, mojom::AudioFocusType::kGain);
  728. EXPECT_EQ(kExampleSourceName, GetSourceNameForLastRequest());
  729. EXPECT_EQ(identity, GetIdentityForLastRequest());
  730. base::UnguessableToken new_identity = base::UnguessableToken::Create();
  731. SetSource(new_identity, kExampleSourceName2);
  732. EXPECT_EQ(kExampleSourceName, GetSourceNameForLastRequest());
  733. EXPECT_EQ(identity, GetIdentityForLastRequest());
  734. }
  735. TEST_P(AudioFocusManagerTest,
  736. AbandonAudioFocus_ObserverFocusGain_NoTopSession) {
  737. test::MockMediaSession media_session;
  738. RequestAudioFocus(&media_session,
  739. mojom::AudioFocusType::kGainTransientMayDuck);
  740. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  741. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  742. GetState(&media_session));
  743. {
  744. std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
  745. media_session.AbandonAudioFocusFromClient();
  746. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  747. EXPECT_TRUE(observer->focus_lost_session()->session_info.Equals(
  748. test::GetMediaSessionInfoSync(&media_session)));
  749. EXPECT_TRUE(observer->focus_gained_session().is_null());
  750. auto notifications = observer->notifications();
  751. EXPECT_EQ(1u, notifications.size());
  752. EXPECT_EQ(test::TestAudioFocusObserver::NotificationType::kFocusLost,
  753. notifications[0]);
  754. }
  755. }
  756. TEST_P(AudioFocusManagerTest,
  757. AbandonAudioFocus_ObserverFocusGain_NewTopSession) {
  758. test::MockMediaSession media_session_1;
  759. test::MockMediaSession media_session_2;
  760. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  761. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  762. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  763. GetState(&media_session_1));
  764. RequestAudioFocus(&media_session_2,
  765. mojom::AudioFocusType::kGainTransientMayDuck);
  766. EXPECT_EQ(1, GetTransientMaybeDuckCount());
  767. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  768. GetState(&media_session_1));
  769. mojom::MediaSessionInfoPtr media_session_1_info =
  770. test::GetMediaSessionInfoSync(&media_session_1);
  771. {
  772. std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
  773. media_session_2.AbandonAudioFocusFromClient();
  774. EXPECT_EQ(0, GetTransientMaybeDuckCount());
  775. EXPECT_TRUE(observer->focus_lost_session()->session_info.Equals(
  776. test::GetMediaSessionInfoSync(&media_session_2)));
  777. EXPECT_TRUE(observer->focus_gained_session()->session_info.Equals(
  778. media_session_1_info));
  779. // FocusLost should always come before FocusGained so observers always know
  780. // the current session that has focus.
  781. auto notifications = observer->notifications();
  782. EXPECT_EQ(2u, notifications.size());
  783. EXPECT_EQ(test::TestAudioFocusObserver::NotificationType::kFocusLost,
  784. notifications[0]);
  785. EXPECT_EQ(test::TestAudioFocusObserver::NotificationType::kFocusGained,
  786. notifications[1]);
  787. }
  788. }
  789. TEST_P(AudioFocusManagerTest, AudioFocusGrouping_LayeredFocus) {
  790. test::MockMediaSession media_session_1;
  791. test::MockMediaSession media_session_2;
  792. test::MockMediaSession media_session_3;
  793. base::UnguessableToken group_id = base::UnguessableToken::Create();
  794. ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
  795. &media_session_1,
  796. mojom::AudioFocusType::kGain, group_id));
  797. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  798. GetState(&media_session_1));
  799. RequestAudioFocus(&media_session_2,
  800. mojom::AudioFocusType::kGainTransientMayDuck);
  801. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  802. GetState(&media_session_1));
  803. // When we request audio focus for media_session_3 the group will take audio
  804. // focus and we suspend the ducking session.
  805. ASSERT_TRUE(RequestGroupedAudioFocus(
  806. base::UnguessableToken::Create(), &media_session_3,
  807. mojom::AudioFocusType::kGainTransient, group_id));
  808. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  809. GetState(&media_session_3));
  810. EXPECT_EQ(
  811. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  812. GetState(&media_session_2));
  813. EXPECT_EQ(GetStateFromParam(
  814. IsGroupingEnabled()
  815. ? mojom::MediaSessionInfo::SessionState::kActive
  816. : mojom::MediaSessionInfo::SessionState::kSuspended),
  817. GetState(&media_session_1));
  818. }
  819. TEST_P(AudioFocusManagerTest, AudioFocusGrouping_TransientResume) {
  820. test::MockMediaSession media_session_1;
  821. test::MockMediaSession media_session_2;
  822. test::MockMediaSession media_session_3;
  823. test::MockMediaSession media_session_4;
  824. base::UnguessableToken group_id = base::UnguessableToken::Create();
  825. ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
  826. &media_session_1,
  827. mojom::AudioFocusType::kGain, group_id));
  828. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  829. GetState(&media_session_1));
  830. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
  831. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  832. GetState(&media_session_2));
  833. ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
  834. &media_session_3,
  835. mojom::AudioFocusType::kGain, group_id));
  836. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  837. GetState(&media_session_3));
  838. RequestAudioFocus(&media_session_4, mojom::AudioFocusType::kGainTransient);
  839. EXPECT_EQ(
  840. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  841. GetState(&media_session_1));
  842. EXPECT_EQ(
  843. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  844. GetState(&media_session_2));
  845. EXPECT_EQ(
  846. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  847. GetState(&media_session_3));
  848. media_session_4.AbandonAudioFocusFromClient();
  849. // TODO(https://crbug.com/916177): This should wait on a more precise
  850. // condition than RunLoop idling, but it's not clear exactly what that
  851. // should be.
  852. base::RunLoop().RunUntilIdle();
  853. EXPECT_EQ(IsGroupingEnabled()
  854. ? mojom::MediaSessionInfo::SessionState::kActive
  855. : mojom::MediaSessionInfo::SessionState::kSuspended,
  856. GetState(&media_session_1));
  857. EXPECT_EQ(
  858. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  859. GetState(&media_session_2));
  860. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  861. GetState(&media_session_3));
  862. }
  863. TEST_P(AudioFocusManagerTest, AudioFocusGrouping_DoNotSuspendSameGroup) {
  864. test::MockMediaSession media_session_1;
  865. test::MockMediaSession media_session_2;
  866. base::UnguessableToken group_id = base::UnguessableToken::Create();
  867. ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
  868. &media_session_1,
  869. mojom::AudioFocusType::kGain, group_id));
  870. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  871. GetState(&media_session_1));
  872. ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
  873. &media_session_2,
  874. mojom::AudioFocusType::kGain, group_id));
  875. EXPECT_EQ(IsGroupingEnabled()
  876. ? mojom::MediaSessionInfo::SessionState::kActive
  877. : mojom::MediaSessionInfo::SessionState::kSuspended,
  878. GetState(&media_session_1));
  879. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  880. GetState(&media_session_2));
  881. }
  882. TEST_P(AudioFocusManagerTest, AudioFocusGrouping_DuckSameGroup) {
  883. test::MockMediaSession media_session_1;
  884. test::MockMediaSession media_session_2;
  885. base::UnguessableToken group_id = base::UnguessableToken::Create();
  886. ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
  887. &media_session_1,
  888. mojom::AudioFocusType::kGain, group_id));
  889. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  890. GetState(&media_session_1));
  891. ASSERT_TRUE(RequestGroupedAudioFocus(
  892. base::UnguessableToken::Create(), &media_session_2,
  893. mojom::AudioFocusType::kGainTransientMayDuck, group_id));
  894. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  895. GetState(&media_session_1));
  896. }
  897. TEST_P(AudioFocusManagerTest, AudioFocusGrouping_TransientSameGroup) {
  898. test::MockMediaSession media_session_1;
  899. test::MockMediaSession media_session_2;
  900. base::UnguessableToken group_id = base::UnguessableToken::Create();
  901. ASSERT_TRUE(RequestGroupedAudioFocus(base::UnguessableToken::Create(),
  902. &media_session_1,
  903. mojom::AudioFocusType::kGain, group_id));
  904. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  905. GetState(&media_session_1));
  906. ASSERT_TRUE(RequestGroupedAudioFocus(
  907. base::UnguessableToken::Create(), &media_session_2,
  908. mojom::AudioFocusType::kGainTransient, group_id));
  909. EXPECT_EQ(IsGroupingEnabled()
  910. ? mojom::MediaSessionInfo::SessionState::kActive
  911. : mojom::MediaSessionInfo::SessionState::kSuspended,
  912. GetState(&media_session_1));
  913. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  914. GetState(&media_session_2));
  915. }
  916. TEST_P(AudioFocusManagerTest, RequestAudioFocus_PreferStop_LossToGain) {
  917. test::MockMediaSession media_session_1;
  918. test::MockMediaSession media_session_2;
  919. media_session_1.SetPreferStop(true);
  920. AudioFocusManager::RequestId request_id_1 =
  921. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  922. EXPECT_EQ(request_id_1, GetAudioFocusedSession());
  923. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  924. GetState(&media_session_1));
  925. AudioFocusManager::RequestId request_id_2 =
  926. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
  927. EXPECT_EQ(request_id_2, GetAudioFocusedSession());
  928. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kInactive),
  929. GetState(&media_session_1));
  930. }
  931. TEST_P(AudioFocusManagerTest,
  932. RequestAudioFocus_PreferStop_LossToGainTransient) {
  933. test::MockMediaSession media_session_1;
  934. test::MockMediaSession media_session_2;
  935. media_session_1.SetPreferStop(true);
  936. AudioFocusManager::RequestId request_id_1 =
  937. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  938. EXPECT_EQ(request_id_1, GetAudioFocusedSession());
  939. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  940. GetState(&media_session_1));
  941. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
  942. EXPECT_EQ(
  943. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  944. GetState(&media_session_1));
  945. }
  946. TEST_P(AudioFocusManagerTest, GainFocusTypeHasEffectEvenIfSuspended) {
  947. test::MockMediaSession media_session_1;
  948. test::MockMediaSession media_session_2;
  949. test::MockMediaSession media_session_3;
  950. AudioFocusManager::RequestId request_id_1 =
  951. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  952. EXPECT_EQ(request_id_1, GetAudioFocusedSession());
  953. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
  954. EXPECT_EQ(
  955. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  956. GetState(&media_session_1));
  957. // When the second session becomes suspended and that event originated from
  958. // the session itself then we should keep the other session suspended.
  959. media_session_2.Suspend(mojom::MediaSession::SuspendType::kUI);
  960. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
  961. GetState(&media_session_2));
  962. {
  963. test::MockMediaSessionMojoObserver observer(media_session_1);
  964. observer.WaitForState(
  965. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
  966. }
  967. // When the second session is resumed then we should still keep the other
  968. // session suspended.
  969. media_session_2.Resume(mojom::MediaSession::SuspendType::kUI);
  970. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  971. GetState(&media_session_2));
  972. {
  973. test::MockMediaSessionMojoObserver observer(media_session_1);
  974. observer.WaitForState(
  975. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
  976. }
  977. // If a new session takes focus then this should suspend all sessions.
  978. RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGainTransient);
  979. {
  980. test::MockMediaSessionMojoObserver observer(media_session_2);
  981. observer.WaitForState(
  982. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
  983. }
  984. {
  985. test::MockMediaSessionMojoObserver observer(media_session_1);
  986. observer.WaitForState(
  987. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
  988. }
  989. // If the second session regains focus then it should suspend all sessions.
  990. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
  991. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  992. GetState(&media_session_2));
  993. {
  994. test::MockMediaSessionMojoObserver observer(media_session_1);
  995. observer.WaitForState(
  996. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
  997. }
  998. {
  999. test::MockMediaSessionMojoObserver observer(media_session_3);
  1000. observer.WaitForState(
  1001. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
  1002. }
  1003. }
  1004. TEST_P(AudioFocusManagerTest, TransientFocusTypeHasNoEffectIfSuspended) {
  1005. test::MockMediaSession media_session_1;
  1006. test::MockMediaSession media_session_2;
  1007. test::MockMediaSession media_session_3;
  1008. AudioFocusManager::RequestId request_id_1 =
  1009. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  1010. EXPECT_EQ(request_id_1, GetAudioFocusedSession());
  1011. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
  1012. EXPECT_EQ(
  1013. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  1014. GetState(&media_session_1));
  1015. // When the transient session becomes suspended and that event originates from
  1016. // the session itself then we should stop pausing the other session.
  1017. media_session_2.Suspend(mojom::MediaSession::SuspendType::kUI);
  1018. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
  1019. GetState(&media_session_2));
  1020. {
  1021. test::MockMediaSessionMojoObserver observer(media_session_1);
  1022. observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
  1023. }
  1024. // When the transient session is resumed then we should pause the other
  1025. // session again.
  1026. media_session_2.Resume(mojom::MediaSession::SuspendType::kUI);
  1027. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1028. GetState(&media_session_2));
  1029. {
  1030. test::MockMediaSessionMojoObserver observer(media_session_1);
  1031. observer.WaitForState(
  1032. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
  1033. }
  1034. // If we have a new session take focus then this should suspend all the other
  1035. // sessions and the transient session should have no effect.
  1036. RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGainTransient);
  1037. {
  1038. test::MockMediaSessionMojoObserver observer(media_session_2);
  1039. observer.WaitForState(
  1040. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
  1041. }
  1042. {
  1043. test::MockMediaSessionMojoObserver observer(media_session_1);
  1044. observer.WaitForState(
  1045. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
  1046. }
  1047. // If the second session regains focus then it should start pausing again.
  1048. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
  1049. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1050. GetState(&media_session_2));
  1051. {
  1052. test::MockMediaSessionMojoObserver observer(media_session_1);
  1053. observer.WaitForState(
  1054. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
  1055. }
  1056. {
  1057. test::MockMediaSessionMojoObserver observer(media_session_3);
  1058. observer.WaitForState(
  1059. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
  1060. }
  1061. }
  1062. TEST_P(AudioFocusManagerTest, TransientDuckFocusTypeHasNoEffectIfSuspended) {
  1063. test::MockMediaSession media_session_1;
  1064. test::MockMediaSession media_session_2;
  1065. test::MockMediaSession media_session_3;
  1066. AudioFocusManager::RequestId request_id_1 =
  1067. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  1068. EXPECT_EQ(request_id_1, GetAudioFocusedSession());
  1069. RequestAudioFocus(&media_session_2,
  1070. mojom::AudioFocusType::kGainTransientMayDuck);
  1071. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  1072. GetState(&media_session_1));
  1073. // When the ducking session becomes suspended and that event originates from
  1074. // the session itself then we should stop ducking.
  1075. media_session_2.Suspend(mojom::MediaSession::SuspendType::kUI);
  1076. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
  1077. GetState(&media_session_2));
  1078. {
  1079. test::MockMediaSessionMojoObserver observer(media_session_1);
  1080. observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
  1081. }
  1082. // When the ducking session is resumed then we should resume ducking.
  1083. media_session_2.Resume(mojom::MediaSession::SuspendType::kUI);
  1084. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1085. GetState(&media_session_2));
  1086. {
  1087. test::MockMediaSessionMojoObserver observer(media_session_1);
  1088. observer.WaitForState(
  1089. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking));
  1090. }
  1091. // If we have a new session take focus then this should suspend all the other
  1092. // sessions and we should not have any ducking from the ducking session (since
  1093. // it is suspended).
  1094. RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGainTransient);
  1095. {
  1096. test::MockMediaSessionMojoObserver observer(media_session_2);
  1097. observer.WaitForState(
  1098. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
  1099. }
  1100. {
  1101. test::MockMediaSessionMojoObserver observer(media_session_1);
  1102. observer.WaitForState(
  1103. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
  1104. }
  1105. // If the ducking session regains focus then it should start ducking again.
  1106. RequestAudioFocus(&media_session_2,
  1107. mojom::AudioFocusType::kGainTransientMayDuck);
  1108. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1109. GetState(&media_session_2));
  1110. {
  1111. test::MockMediaSessionMojoObserver observer(media_session_1);
  1112. observer.WaitForState(
  1113. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking));
  1114. }
  1115. {
  1116. test::MockMediaSessionMojoObserver observer(media_session_3);
  1117. observer.WaitForState(
  1118. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking));
  1119. }
  1120. }
  1121. TEST_P(AudioFocusManagerTest, AmbientFocusHasNoEffect) {
  1122. test::MockMediaSession media_session_1;
  1123. test::MockMediaSession media_session_2;
  1124. AudioFocusManager::RequestId request_id_1 =
  1125. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  1126. EXPECT_EQ(request_id_1, GetAudioFocusedSession());
  1127. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1128. GetState(&media_session_1));
  1129. EXPECT_EQ(0, GetAmbientCount());
  1130. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kAmbient);
  1131. EXPECT_EQ(1, GetAmbientCount());
  1132. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1133. GetState(&media_session_1));
  1134. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1135. GetState(&media_session_2));
  1136. media_session_2.AbandonAudioFocusFromClient();
  1137. EXPECT_EQ(0, GetAmbientCount());
  1138. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1139. GetState(&media_session_1));
  1140. }
  1141. TEST_P(AudioFocusManagerTest, AudioFocusObserver_NotTopMost) {
  1142. test::MockMediaSession media_session_1;
  1143. test::MockMediaSession media_session_2;
  1144. AudioFocusManager::RequestId request_id_1 =
  1145. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  1146. EXPECT_EQ(request_id_1, GetAudioFocusedSession());
  1147. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1148. GetState(&media_session_1));
  1149. RequestAudioFocus(&media_session_2,
  1150. mojom::AudioFocusType::kGainTransientMayDuck);
  1151. EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
  1152. GetState(&media_session_1));
  1153. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1154. GetState(&media_session_2));
  1155. {
  1156. std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
  1157. media_session_1.AbandonAudioFocusFromClient();
  1158. EXPECT_TRUE(observer->focus_lost_session()->session_info.Equals(
  1159. test::GetMediaSessionInfoSync(&media_session_1)));
  1160. }
  1161. }
  1162. TEST_P(AudioFocusManagerTest, SuspendAllSessionOnPowerSuspend) {
  1163. test::MockMediaSession media_session_1;
  1164. test::MockMediaSession media_session_2;
  1165. {
  1166. test::MockMediaSessionMojoObserver observer(media_session_1);
  1167. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  1168. observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
  1169. }
  1170. {
  1171. test::MockMediaSessionMojoObserver observer(media_session_2);
  1172. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
  1173. observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
  1174. }
  1175. test::MockMediaSessionMojoObserver observer_1(media_session_1);
  1176. test::MockMediaSessionMojoObserver observer_2(media_session_2);
  1177. GenerateSuspendEvent();
  1178. observer_1.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
  1179. observer_2.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
  1180. }
  1181. TEST_P(AudioFocusManagerTest, TransientPauseShouldDelayControllerPause) {
  1182. test::MockMediaSession media_session_1;
  1183. test::MockMediaSession media_session_2;
  1184. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  1185. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1186. GetState(&media_session_1));
  1187. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
  1188. EXPECT_EQ(
  1189. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  1190. GetState(&media_session_1));
  1191. mojo::Remote<mojom::MediaController> controller;
  1192. controller_manager()->CreateMediaControllerForSession(
  1193. controller.BindNewPipeAndPassReceiver(), media_session_1.request_id());
  1194. controller_manager().FlushForTesting();
  1195. controller->Suspend();
  1196. controller.FlushForTesting();
  1197. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
  1198. GetState(&media_session_1));
  1199. // When we abandon the transient session then we will apply the last
  1200. // controller action.
  1201. media_session_2.AbandonAudioFocusFromClient();
  1202. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
  1203. GetState(&media_session_1));
  1204. }
  1205. TEST_P(AudioFocusManagerTest, TransientPauseShouldDelayControllerStop) {
  1206. test::MockMediaSession media_session_1;
  1207. test::MockMediaSession media_session_2;
  1208. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  1209. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1210. GetState(&media_session_1));
  1211. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
  1212. EXPECT_EQ(
  1213. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  1214. GetState(&media_session_1));
  1215. mojo::Remote<mojom::MediaController> controller;
  1216. controller_manager()->CreateMediaControllerForSession(
  1217. controller.BindNewPipeAndPassReceiver(), media_session_1.request_id());
  1218. controller_manager().FlushForTesting();
  1219. controller->Stop();
  1220. controller.FlushForTesting();
  1221. // If enforcement is enabled then the session was previously suspended by the
  1222. // transient session and therefore we should be suspended. Otherwise, we
  1223. // should be inactive because the stop command would not have been delayed.
  1224. EXPECT_EQ(IsEnforcementEnabled()
  1225. ? mojom::MediaSessionInfo::SessionState::kSuspended
  1226. : mojom::MediaSessionInfo::SessionState::kInactive,
  1227. GetState(&media_session_1));
  1228. {
  1229. // When we abandon the transient session then we will apply the last
  1230. // controller action.
  1231. test::MockMediaSessionMojoObserver observer(media_session_1);
  1232. media_session_2.AbandonAudioFocusFromClient();
  1233. observer.WaitForState(mojom::MediaSessionInfo::SessionState::kInactive);
  1234. }
  1235. }
  1236. TEST_P(AudioFocusManagerTest, TransientPauseShouldDelayControllerResume) {
  1237. test::MockMediaSession media_session_1;
  1238. test::MockMediaSession media_session_2;
  1239. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  1240. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1241. GetState(&media_session_1));
  1242. mojo::Remote<mojom::MediaController> controller;
  1243. controller_manager()->CreateMediaControllerForSession(
  1244. controller.BindNewPipeAndPassReceiver(), media_session_1.request_id());
  1245. controller_manager().FlushForTesting();
  1246. controller->Suspend();
  1247. controller.FlushForTesting();
  1248. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
  1249. GetState(&media_session_1));
  1250. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
  1251. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
  1252. GetState(&media_session_1));
  1253. controller->Resume();
  1254. controller.FlushForTesting();
  1255. // If enforcement is enabled then the session was previously suspended by the
  1256. // transient session and therefore we should be suspended. Otherwise, we
  1257. // should be active because the resume command would not have been delayed.
  1258. EXPECT_EQ(
  1259. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  1260. GetState(&media_session_1));
  1261. {
  1262. // When we abandon the transient session then we will apply the last
  1263. // controller action.
  1264. test::MockMediaSessionMojoObserver observer(media_session_1);
  1265. media_session_2.AbandonAudioFocusFromClient();
  1266. observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
  1267. }
  1268. }
  1269. TEST_P(AudioFocusManagerTest, TransientPauseShouldDelayLastActionOnly) {
  1270. test::MockMediaSession media_session_1;
  1271. test::MockMediaSession media_session_2;
  1272. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  1273. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
  1274. GetState(&media_session_1));
  1275. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
  1276. EXPECT_EQ(
  1277. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  1278. GetState(&media_session_1));
  1279. mojo::Remote<mojom::MediaController> controller;
  1280. controller_manager()->CreateMediaControllerForSession(
  1281. controller.BindNewPipeAndPassReceiver(), media_session_1.request_id());
  1282. controller_manager().FlushForTesting();
  1283. controller->Resume();
  1284. controller.FlushForTesting();
  1285. // The resume action should be delayed because we were suspended by the
  1286. // transient session.
  1287. EXPECT_EQ(
  1288. GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
  1289. GetState(&media_session_1));
  1290. // Calling suspend while we are still suspended should cancel the delayed
  1291. // resume action so we will never resume.
  1292. controller->Suspend();
  1293. controller.FlushForTesting();
  1294. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
  1295. GetState(&media_session_1));
  1296. // When we abandon the transient session then we will apply the last
  1297. // controller action.
  1298. media_session_2.AbandonAudioFocusFromClient();
  1299. EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
  1300. GetState(&media_session_1));
  1301. }
  1302. TEST_P(AudioFocusManagerTest, RequestIdValidation) {
  1303. test::MockMediaSession media_session_1;
  1304. test::MockMediaSession media_session_2;
  1305. base::UnguessableToken request_id = base::UnguessableToken::Create();
  1306. EXPECT_TRUE(RequestGroupedAudioFocus(request_id, &media_session_1,
  1307. mojom::AudioFocusType::kGain,
  1308. base::UnguessableToken::Create()));
  1309. EXPECT_EQ(request_id, GetAudioFocusedSession());
  1310. // The audio focus request should fail since we have already used that id.
  1311. EXPECT_FALSE(RequestGroupedAudioFocus(request_id, &media_session_2,
  1312. mojom::AudioFocusType::kGain,
  1313. base::UnguessableToken::Create()));
  1314. media_session_1.AbandonAudioFocusFromClient();
  1315. EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusedSession());
  1316. // If we abandon focus then we should be able to use the id now.
  1317. EXPECT_TRUE(RequestGroupedAudioFocus(request_id, &media_session_2,
  1318. mojom::AudioFocusType::kGain,
  1319. base::UnguessableToken::Create()));
  1320. EXPECT_EQ(request_id, GetAudioFocusedSession());
  1321. }
  1322. TEST_P(AudioFocusManagerTest, SourceObservers) {
  1323. // Create two identity observers for two different identities.
  1324. base::UnguessableToken identity_1 = base::UnguessableToken::Create();
  1325. base::UnguessableToken identity_2 = base::UnguessableToken::Create();
  1326. std::unique_ptr<test::TestAudioFocusObserver> observer_1 =
  1327. CreateSourceObserver(identity_1);
  1328. std::unique_ptr<test::TestAudioFocusObserver> observer_2 =
  1329. CreateSourceObserver(identity_2);
  1330. // Request audio focus for the first identity.
  1331. SetSource(identity_1, kExampleSourceName);
  1332. test::MockMediaSession media_session_1;
  1333. base::UnguessableToken request_id_1 =
  1334. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  1335. // The observer for the first identity should see the gained focus, while the
  1336. // observer for the second identity should see nothing.
  1337. EXPECT_EQ(request_id_1, observer_1->focus_gained_session()->request_id);
  1338. EXPECT_TRUE(observer_2->focus_gained_session().is_null());
  1339. // Request audio focus for the second identity.
  1340. SetSource(identity_2, kExampleSourceName);
  1341. test::MockMediaSession media_session_2;
  1342. base::UnguessableToken request_id_2 =
  1343. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
  1344. // The observer for the first identity should still show the first request,
  1345. // while the observer for the second identity should see the new session.
  1346. EXPECT_EQ(request_id_1, observer_1->focus_gained_session()->request_id);
  1347. EXPECT_EQ(request_id_2, observer_2->focus_gained_session()->request_id);
  1348. // Make another request in the second identity.
  1349. test::MockMediaSession media_session_3;
  1350. base::UnguessableToken request_id_3 =
  1351. RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGain);
  1352. // The observer for the first identity should still show the first request,
  1353. // while the observer for the second identity should see the new session.
  1354. EXPECT_EQ(request_id_1, observer_1->focus_gained_session()->request_id);
  1355. EXPECT_EQ(request_id_3, observer_2->focus_gained_session()->request_id);
  1356. // Abandon the topmost session.
  1357. media_session_3.AbandonAudioFocusFromClient();
  1358. FlushForTesting();
  1359. // The observer for the second identity should get the new lost and gained
  1360. // sessions, with no updates to the first observer.
  1361. EXPECT_EQ(request_id_3, observer_2->focus_lost_session()->request_id);
  1362. EXPECT_EQ(request_id_2, observer_2->focus_gained_session()->request_id);
  1363. EXPECT_EQ(request_id_1, observer_1->focus_gained_session()->request_id);
  1364. EXPECT_TRUE(observer_1->focus_lost_session().is_null());
  1365. }
  1366. TEST_P(AudioFocusManagerTest, GetSourceFocusRequests) {
  1367. // Establish identities.
  1368. base::UnguessableToken identity_1 = base::UnguessableToken::Create();
  1369. base::UnguessableToken identity_2 = base::UnguessableToken::Create();
  1370. base::UnguessableToken identity_3 = base::UnguessableToken::Create();
  1371. // Create a focus request for the first identity.
  1372. SetSource(identity_1, kExampleSourceName);
  1373. test::MockMediaSession media_session_1;
  1374. base::UnguessableToken request_id_1 =
  1375. RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
  1376. // Create a focus request for the second identity.
  1377. SetSource(identity_2, kExampleSourceName);
  1378. test::MockMediaSession media_session_2;
  1379. base::UnguessableToken request_id_2 =
  1380. RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
  1381. // Create another focus request for the first identity.
  1382. SetSource(identity_1, kExampleSourceName);
  1383. test::MockMediaSession media_session_3;
  1384. base::UnguessableToken request_id_3 =
  1385. RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGain);
  1386. // Use the GetSourceFocusRequests API to get requests for each identity.
  1387. std::vector<mojom::AudioFocusRequestStatePtr> identity_1_requests =
  1388. GetSourceFocusRequests(identity_1);
  1389. std::vector<mojom::AudioFocusRequestStatePtr> identity_2_requests =
  1390. GetSourceFocusRequests(identity_2);
  1391. std::vector<mojom::AudioFocusRequestStatePtr> identity_3_requests =
  1392. GetSourceFocusRequests(identity_3);
  1393. // Ensure that the API returned the right requests for the first identity.
  1394. EXPECT_EQ(2u, identity_1_requests.size());
  1395. EXPECT_EQ(request_id_1, identity_1_requests[0]->request_id);
  1396. EXPECT_EQ(request_id_3, identity_1_requests[1]->request_id);
  1397. // Ensure that the API returned the right requests for the second identity.
  1398. EXPECT_EQ(1u, identity_2_requests.size());
  1399. EXPECT_EQ(request_id_2, identity_2_requests[0]->request_id);
  1400. // Ensure that the API returned nothing for the unused identity.
  1401. EXPECT_TRUE(identity_3_requests.empty());
  1402. }
  1403. } // namespace media_session