Merge "[Media] Add a MediaController.Callback that will disconnect us when onSessionDestroyed is triggered." into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
254bb54736
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
@@ -136,6 +139,22 @@ public class ResumeMediaBrowserTest : SysuiTestCase() {
|
||||
verify(callback).addTrack(eq(description), eq(component), eq(resumeBrowser))
|
||||
}
|
||||
|
||||
@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>()
|
||||
@@ -187,6 +206,22 @@ public class ResumeMediaBrowserTest : SysuiTestCase() {
|
||||
verify(callback).onConnected()
|
||||
}
|
||||
|
||||
@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>()
|
||||
@@ -260,6 +295,22 @@ public class ResumeMediaBrowserTest : SysuiTestCase() {
|
||||
verify(transportControls).play()
|
||||
}
|
||||
|
||||
@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>()
|
||||
|
||||
Reference in New Issue
Block a user