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 MediaBrowserFactory mBrowserFactory;
|
||||||
private final ResumeMediaBrowserLogger mLogger;
|
private final ResumeMediaBrowserLogger mLogger;
|
||||||
private final ComponentName mComponentName;
|
private final ComponentName mComponentName;
|
||||||
|
private final MediaController.Callback mMediaControllerCallback = new SessionDestroyCallback();
|
||||||
|
|
||||||
private MediaBrowser mMediaBrowser;
|
private MediaBrowser mMediaBrowser;
|
||||||
|
@Nullable private MediaController mMediaController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a new media browser
|
* Initialize a new media browser
|
||||||
@@ -90,6 +92,7 @@ public class ResumeMediaBrowser {
|
|||||||
mComponentName,
|
mComponentName,
|
||||||
mConnectionCallback,
|
mConnectionCallback,
|
||||||
rootHints);
|
rootHints);
|
||||||
|
updateMediaController();
|
||||||
mLogger.logConnection(mComponentName, "findRecentMedia");
|
mLogger.logConnection(mComponentName, "findRecentMedia");
|
||||||
mMediaBrowser.connect();
|
mMediaBrowser.connect();
|
||||||
}
|
}
|
||||||
@@ -154,7 +157,8 @@ public class ResumeMediaBrowser {
|
|||||||
@Override
|
@Override
|
||||||
public void onConnected() {
|
public void onConnected() {
|
||||||
Log.d(TAG, "Service connected for " + mComponentName);
|
Log.d(TAG, "Service connected for " + mComponentName);
|
||||||
if (mMediaBrowser != null && mMediaBrowser.isConnected()) {
|
updateMediaController();
|
||||||
|
if (isBrowserConnected()) {
|
||||||
String root = mMediaBrowser.getRoot();
|
String root = mMediaBrowser.getRoot();
|
||||||
if (!TextUtils.isEmpty(root)) {
|
if (!TextUtils.isEmpty(root)) {
|
||||||
if (mCallback != null) {
|
if (mCallback != null) {
|
||||||
@@ -207,6 +211,7 @@ public class ResumeMediaBrowser {
|
|||||||
mMediaBrowser.disconnect();
|
mMediaBrowser.disconnect();
|
||||||
}
|
}
|
||||||
mMediaBrowser = null;
|
mMediaBrowser = null;
|
||||||
|
updateMediaController();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -225,7 +230,8 @@ public class ResumeMediaBrowser {
|
|||||||
@Override
|
@Override
|
||||||
public void onConnected() {
|
public void onConnected() {
|
||||||
Log.d(TAG, "Connected for restart " + mMediaBrowser.isConnected());
|
Log.d(TAG, "Connected for restart " + mMediaBrowser.isConnected());
|
||||||
if (mMediaBrowser == null || !mMediaBrowser.isConnected()) {
|
updateMediaController();
|
||||||
|
if (!isBrowserConnected()) {
|
||||||
if (mCallback != null) {
|
if (mCallback != null) {
|
||||||
mCallback.onError();
|
mCallback.onError();
|
||||||
}
|
}
|
||||||
@@ -259,6 +265,7 @@ public class ResumeMediaBrowser {
|
|||||||
disconnect();
|
disconnect();
|
||||||
}
|
}
|
||||||
}, rootHints);
|
}, rootHints);
|
||||||
|
updateMediaController();
|
||||||
mLogger.logConnection(mComponentName, "restart");
|
mLogger.logConnection(mComponentName, "restart");
|
||||||
mMediaBrowser.connect();
|
mMediaBrowser.connect();
|
||||||
}
|
}
|
||||||
@@ -273,7 +280,7 @@ public class ResumeMediaBrowser {
|
|||||||
* @return the token, or null if the MediaBrowser is null or disconnected
|
* @return the token, or null if the MediaBrowser is null or disconnected
|
||||||
*/
|
*/
|
||||||
public MediaSession.Token getToken() {
|
public MediaSession.Token getToken() {
|
||||||
if (mMediaBrowser == null || !mMediaBrowser.isConnected()) {
|
if (!isBrowserConnected()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return mMediaBrowser.getSessionToken();
|
return mMediaBrowser.getSessionToken();
|
||||||
@@ -305,10 +312,39 @@ public class ResumeMediaBrowser {
|
|||||||
mComponentName,
|
mComponentName,
|
||||||
mConnectionCallback,
|
mConnectionCallback,
|
||||||
rootHints);
|
rootHints);
|
||||||
|
updateMediaController();
|
||||||
mLogger.logConnection(mComponentName, "testConnection");
|
mLogger.logConnection(mComponentName, "testConnection");
|
||||||
mMediaBrowser.connect();
|
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
|
* Interface to handle results from ResumeMediaBrowser
|
||||||
*/
|
*/
|
||||||
@@ -335,4 +371,12 @@ public class ResumeMediaBrowser {
|
|||||||
ResumeMediaBrowser browser) {
|
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" }
|
{ "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"
|
private const val TAG = "MediaBrowser"
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.mockito.ArgumentCaptor
|
|||||||
import org.mockito.Captor
|
import org.mockito.Captor
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito
|
import org.mockito.Mockito
|
||||||
|
import org.mockito.Mockito.reset
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
import org.mockito.Mockito.`when` as whenever
|
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 connectionCallback: ArgumentCaptor<MediaBrowser.ConnectionCallback>
|
||||||
@Captor lateinit var subscriptionCallback: ArgumentCaptor<MediaBrowser.SubscriptionCallback>
|
@Captor lateinit var subscriptionCallback: ArgumentCaptor<MediaBrowser.SubscriptionCallback>
|
||||||
|
@Captor lateinit var mediaControllerCallback: ArgumentCaptor<MediaController.Callback>
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
@@ -82,6 +84,7 @@ public class ResumeMediaBrowserTest : SysuiTestCase() {
|
|||||||
.thenReturn(browser)
|
.thenReturn(browser)
|
||||||
|
|
||||||
whenever(mediaController.transportControls).thenReturn(transportControls)
|
whenever(mediaController.transportControls).thenReturn(transportControls)
|
||||||
|
whenever(mediaController.sessionToken).thenReturn(token)
|
||||||
|
|
||||||
resumeBrowser = TestableResumeMediaBrowser(
|
resumeBrowser = TestableResumeMediaBrowser(
|
||||||
context,
|
context,
|
||||||
@@ -136,6 +139,22 @@ public class ResumeMediaBrowserTest : SysuiTestCase() {
|
|||||||
verify(callback).addTrack(eq(description), eq(component), eq(resumeBrowser))
|
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
|
@Test
|
||||||
fun testConnection_calledTwice_oldBrowserDisconnected() {
|
fun testConnection_calledTwice_oldBrowserDisconnected() {
|
||||||
val oldBrowser = mock<MediaBrowser>()
|
val oldBrowser = mock<MediaBrowser>()
|
||||||
@@ -187,6 +206,22 @@ public class ResumeMediaBrowserTest : SysuiTestCase() {
|
|||||||
verify(callback).onConnected()
|
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
|
@Test
|
||||||
fun testFindRecentMedia_calledTwice_oldBrowserDisconnected() {
|
fun testFindRecentMedia_calledTwice_oldBrowserDisconnected() {
|
||||||
val oldBrowser = mock<MediaBrowser>()
|
val oldBrowser = mock<MediaBrowser>()
|
||||||
@@ -260,6 +295,22 @@ public class ResumeMediaBrowserTest : SysuiTestCase() {
|
|||||||
verify(transportControls).play()
|
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
|
@Test
|
||||||
fun testRestart_calledTwice_oldBrowserDisconnected() {
|
fun testRestart_calledTwice_oldBrowserDisconnected() {
|
||||||
val oldBrowser = mock<MediaBrowser>()
|
val oldBrowser = mock<MediaBrowser>()
|
||||||
|
|||||||
Reference in New Issue
Block a user