diff options
| author | 2022-05-03 21:27:00 +0000 | |
|---|---|---|
| committer | 2022-05-06 14:04:28 +0000 | |
| commit | 3a5d2ebeb9ced1527db2f1645f306957a58522f7 (patch) | |
| tree | 29d93cadbe079755c73aba89930e2dcbf12eb4c3 | |
| parent | 4c0c32d03c2867b6bbf8a786c61c05a7cbb5c541 (diff) | |
[Media] Add a MediaController.Callback that will disconnect us when
onSessionDestroyed is triggered.
Bug: 225403871
Test: ResumeMediaBrowserTest
Change-Id: I2626a6af7d09f12184b2dda88b28838b51a247c6
3 files changed, 119 insertions, 3 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowser.java b/packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowser.java index 4f598ff797d0..40a5653a15a0 100644 --- a/packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowser.java +++ b/packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowser.java @@ -52,8 +52,10 @@ public class ResumeMediaBrowser { private final MediaBrowserFactory mBrowserFactory; private final ResumeMediaBrowserLogger mLogger; private final ComponentName mComponentName; + private final MediaController.Callback mMediaControllerCallback = new SessionDestroyCallback(); private MediaBrowser mMediaBrowser; + @Nullable private MediaController mMediaController; /** * Initialize a new media browser @@ -90,6 +92,7 @@ public class ResumeMediaBrowser { mComponentName, mConnectionCallback, rootHints); + updateMediaController(); mLogger.logConnection(mComponentName, "findRecentMedia"); mMediaBrowser.connect(); } @@ -154,7 +157,8 @@ public class ResumeMediaBrowser { @Override public void onConnected() { Log.d(TAG, "Service connected for " + mComponentName); - if (mMediaBrowser != null && mMediaBrowser.isConnected()) { + updateMediaController(); + if (isBrowserConnected()) { String root = mMediaBrowser.getRoot(); if (!TextUtils.isEmpty(root)) { if (mCallback != null) { @@ -207,6 +211,7 @@ public class ResumeMediaBrowser { mMediaBrowser.disconnect(); } mMediaBrowser = null; + updateMediaController(); } /** @@ -225,7 +230,8 @@ public class ResumeMediaBrowser { @Override public void onConnected() { Log.d(TAG, "Connected for restart " + mMediaBrowser.isConnected()); - if (mMediaBrowser == null || !mMediaBrowser.isConnected()) { + updateMediaController(); + if (!isBrowserConnected()) { if (mCallback != null) { mCallback.onError(); } @@ -259,6 +265,7 @@ public class ResumeMediaBrowser { disconnect(); } }, rootHints); + updateMediaController(); mLogger.logConnection(mComponentName, "restart"); mMediaBrowser.connect(); } @@ -273,7 +280,7 @@ public class ResumeMediaBrowser { * @return the token, or null if the MediaBrowser is null or disconnected */ public MediaSession.Token getToken() { - if (mMediaBrowser == null || !mMediaBrowser.isConnected()) { + if (!isBrowserConnected()) { return null; } return mMediaBrowser.getSessionToken(); @@ -305,10 +312,39 @@ public class ResumeMediaBrowser { mComponentName, mConnectionCallback, rootHints); + updateMediaController(); mLogger.logConnection(mComponentName, "testConnection"); mMediaBrowser.connect(); } + /** Updates mMediaController based on our current browser values. */ + private void updateMediaController() { + MediaSession.Token controllerToken = + mMediaController != null ? mMediaController.getSessionToken() : null; + MediaSession.Token currentToken = getToken(); + boolean areEqual = (controllerToken == null && currentToken == null) + || (controllerToken != null && controllerToken.equals(currentToken)); + if (areEqual) { + return; + } + + // Whenever the token changes, un-register the callback on the old controller (if we have + // one) and create a new controller with the callback attached. + if (mMediaController != null) { + mMediaController.unregisterCallback(mMediaControllerCallback); + } + if (currentToken != null) { + mMediaController = createMediaController(currentToken); + mMediaController.registerCallback(mMediaControllerCallback); + } else { + mMediaController = null; + } + } + + private boolean isBrowserConnected() { + return mMediaBrowser != null && mMediaBrowser.isConnected(); + } + /** * Interface to handle results from ResumeMediaBrowser */ @@ -335,4 +371,12 @@ public class ResumeMediaBrowser { ResumeMediaBrowser browser) { } } + + private class SessionDestroyCallback extends MediaController.Callback { + @Override + public void onSessionDestroyed() { + mLogger.logSessionDestroyed(isBrowserConnected(), mComponentName); + disconnect(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowserLogger.kt b/packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowserLogger.kt index ccc5edc1123a..41f735486c7e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowserLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowserLogger.kt @@ -48,6 +48,27 @@ class ResumeMediaBrowserLogger @Inject constructor( }, { "Disconnecting browser for component $str1" } ) + + /** + * Logs that we received a [android.media.session.MediaController.Callback.onSessionDestroyed] + * event. + * + * @param isBrowserConnected true if there's a currently connected + * [android.media.browse.MediaBrowser] and false otherwise. + * @param componentName the component name for the [ResumeMediaBrowser] that triggered this log. + */ + fun logSessionDestroyed( + isBrowserConnected: Boolean, + componentName: ComponentName + ) = buffer.log( + TAG, + LogLevel.DEBUG, + { + bool1 = isBrowserConnected + str1 = componentName.toShortString() + }, + { "Session destroyed. Active browser = $bool1. Browser component = $str1." } + ) } private const val TAG = "MediaBrowser" diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/ResumeMediaBrowserTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/ResumeMediaBrowserTest.kt index a07447521ab8..dafaa6b93696 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/ResumeMediaBrowserTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/ResumeMediaBrowserTest.kt @@ -35,6 +35,7 @@ import org.mockito.ArgumentCaptor import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito +import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` as whenever @@ -73,6 +74,7 @@ public class ResumeMediaBrowserTest : SysuiTestCase() { @Captor lateinit var connectionCallback: ArgumentCaptor<MediaBrowser.ConnectionCallback> @Captor lateinit var subscriptionCallback: ArgumentCaptor<MediaBrowser.SubscriptionCallback> + @Captor lateinit var mediaControllerCallback: ArgumentCaptor<MediaController.Callback> @Before fun setUp() { @@ -82,6 +84,7 @@ public class ResumeMediaBrowserTest : SysuiTestCase() { .thenReturn(browser) whenever(mediaController.transportControls).thenReturn(transportControls) + whenever(mediaController.sessionToken).thenReturn(token) resumeBrowser = TestableResumeMediaBrowser( context, @@ -137,6 +140,22 @@ public class ResumeMediaBrowserTest : SysuiTestCase() { } @Test + fun testConnection_thenSessionDestroyed_disconnects() { + // When testConnection is called and we connect successfully + setupBrowserConnection() + resumeBrowser.testConnection() + verify(mediaController).registerCallback(mediaControllerCallback.capture()) + reset(browser) + + // And a sessionDestroyed event is triggered + mediaControllerCallback.value.onSessionDestroyed() + + // Then we disconnect the browser and unregister the callback + verify(browser).disconnect() + verify(mediaController).unregisterCallback(mediaControllerCallback.value) + } + + @Test fun testConnection_calledTwice_oldBrowserDisconnected() { val oldBrowser = mock<MediaBrowser>() whenever(browserFactory.create(any(), any(), any())).thenReturn(oldBrowser) @@ -188,6 +207,22 @@ public class ResumeMediaBrowserTest : SysuiTestCase() { } @Test + fun testFindRecentMedia_thenSessionDestroyed_disconnects() { + // When findRecentMedia is called and we connect successfully + setupBrowserConnection() + resumeBrowser.findRecentMedia() + verify(mediaController).registerCallback(mediaControllerCallback.capture()) + reset(browser) + + // And a sessionDestroyed event is triggered + mediaControllerCallback.value.onSessionDestroyed() + + // Then we disconnect the browser and unregister the callback + verify(browser).disconnect() + verify(mediaController).unregisterCallback(mediaControllerCallback.value) + } + + @Test fun testFindRecentMedia_calledTwice_oldBrowserDisconnected() { val oldBrowser = mock<MediaBrowser>() whenever(browserFactory.create(any(), any(), any())).thenReturn(oldBrowser) @@ -261,6 +296,22 @@ public class ResumeMediaBrowserTest : SysuiTestCase() { } @Test + fun testRestart_thenSessionDestroyed_disconnects() { + // When restart is called and we connect successfully + setupBrowserConnection() + resumeBrowser.restart() + verify(mediaController).registerCallback(mediaControllerCallback.capture()) + reset(browser) + + // And a sessionDestroyed event is triggered + mediaControllerCallback.value.onSessionDestroyed() + + // Then we disconnect the browser and unregister the callback + verify(browser).disconnect() + verify(mediaController).unregisterCallback(mediaControllerCallback.value) + } + + @Test fun testRestart_calledTwice_oldBrowserDisconnected() { val oldBrowser = mock<MediaBrowser>() whenever(browserFactory.create(any(), any(), any())).thenReturn(oldBrowser) |