Commit 1c815873 by bachinger Committed by microkatz

Use MediaBrowserCompat.rootHints as connections hints

In Media3 there is the useful concept of connection hints that a
client can set when building the session and that are sent to the
service and passed to the `Callback.onConnect()` method when the
browser connects.

These connection hints are then included in the `ControllerInfo`
object that later will be passed to every callback method and the
implementor can then take decisions specific to these connection
hints.

These connection hints are not available in media1. However, when
an app creates a `MediaBrowserCompat` object, the constructor takes
a rootHint object that is sent to
`MediaBrowserServiceCompat.onGetRoot()`.

This change uses the browser rootHints as the connection hints when
creating the `ControllerInfo` for legacy browsers and makes them
available to the `MediaLibrarySession.Callback` domain methods in
the same way as connection hints of a Media3 browser.

PiperOrigin-RevId: 484220748
(cherry picked from commit 21022c77)
parent 1607e3da
......@@ -317,14 +317,14 @@ import java.util.concurrent.atomic.AtomicReference;
}
@Override
public ControllerInfo createControllerInfo(RemoteUserInfo remoteUserInfo) {
public ControllerInfo createControllerInfo(RemoteUserInfo remoteUserInfo, Bundle rootHints) {
return new ControllerInfo(
remoteUserInfo,
ControllerInfo.LEGACY_CONTROLLER_VERSION,
ControllerInfo.LEGACY_CONTROLLER_INTERFACE_VERSION,
getMediaSessionManager().isTrustedForMediaControl(remoteUserInfo),
new BrowserLegacyCb(remoteUserInfo),
/* connectionHints= */ Bundle.EMPTY);
/* connectionHints= */ rootHints);
}
public ControllerCb getBrowserLegacyCbForBroadcast() {
......
......@@ -61,7 +61,8 @@ import java.util.concurrent.atomic.AtomicReference;
public BrowserRoot onGetRoot(
String clientPackageName, int clientUid, @Nullable Bundle rootHints) {
RemoteUserInfo info = getCurrentBrowserInfo();
MediaSession.ControllerInfo controller = createControllerInfo(info);
MediaSession.ControllerInfo controller =
createControllerInfo(info, rootHints != null ? rootHints : Bundle.EMPTY);
AtomicReference<MediaSession.ConnectionResult> resultReference = new AtomicReference<>();
ConditionVariable haveResult = new ConditionVariable();
......@@ -92,14 +93,14 @@ import java.util.concurrent.atomic.AtomicReference;
result.sendResult(/* result= */ null);
}
public ControllerInfo createControllerInfo(RemoteUserInfo info) {
public ControllerInfo createControllerInfo(RemoteUserInfo info, Bundle rootHints) {
return new ControllerInfo(
info,
ControllerInfo.LEGACY_CONTROLLER_VERSION,
ControllerInfo.LEGACY_CONTROLLER_INTERFACE_VERSION,
manager.isTrustedForMediaControl(info),
/* cb= */ null,
/* connectionHints= */ Bundle.EMPTY);
/* connectionHints= */ rootHints);
}
public final MediaSessionManager getMediaSessionManager() {
......
......@@ -23,6 +23,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
import android.content.ComponentName;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.PlaybackStateCompat;
......@@ -63,16 +64,10 @@ public class MediaBrowserCompatWithMediaSessionServiceTest {
@Nullable PlaybackStateCompat lastReportedPlaybackStateCompat;
@Before
public void setUp() throws Exception {
public void setUp() {
context = ApplicationProvider.getApplicationContext();
handler = threadTestRule.getHandler();
connectionCallback = new TestConnectionCallback();
handler.postAndSync(
() -> {
// Make browser's internal handler to be initialized with test thread.
browserCompat =
new MediaBrowserCompat(context, getServiceComponent(), connectionCallback, null);
});
}
@After
......@@ -87,15 +82,22 @@ public class MediaBrowserCompatWithMediaSessionServiceTest {
return MOCK_MEDIA3_SESSION_SERVICE;
}
void connectAndWait() throws InterruptedException {
void connectAndWait(Bundle connectionHints) throws Exception {
handler.postAndSync(
() -> {
// Make browser's internal handler to be initialized with test thread.
browserCompat =
new MediaBrowserCompat(
context, getServiceComponent(), connectionCallback, connectionHints);
});
browserCompat.connect();
assertThat(connectionCallback.connectedLatch.await(SERVICE_CONNECTION_TIMEOUT_MS, MILLISECONDS))
.isTrue();
}
@Test
public void connect() throws InterruptedException {
connectAndWait();
public void connect() throws Exception {
connectAndWait(/* connectionHints= */ Bundle.EMPTY);
assertThat(connectionCallback.failedLatch.getCount()).isNotEqualTo(0);
}
......@@ -109,7 +111,7 @@ public class MediaBrowserCompatWithMediaSessionServiceTest {
@Test
public void getSessionToken() throws Exception {
connectAndWait();
connectAndWait(/* connectionHints= */ Bundle.EMPTY);
MediaControllerCompat controller =
new MediaControllerCompat(context, browserCompat.getSessionToken());
assertThat(controller.getPackageName())
......
......@@ -82,6 +82,9 @@ public class MockMediaLibraryService extends MediaLibraryService {
/** ID of the session that this service will create. */
public static final String ID = "TestLibrary";
public static final String CONNECTION_HINTS_CUSTOM_LIBRARY_ROOT =
"CONNECTION_HINTS_CUSTOM_LIBRARY_ROOT";
public static final MediaItem ROOT_ITEM =
new MediaItem.Builder()
.setMediaId(ROOT_ID)
......@@ -192,7 +195,24 @@ public class MockMediaLibraryService extends MediaLibraryService {
public ListenableFuture<LibraryResult<MediaItem>> onGetLibraryRoot(
MediaLibrarySession session, ControllerInfo browser, @Nullable LibraryParams params) {
assertLibraryParams(params);
return Futures.immediateFuture(LibraryResult.ofItem(ROOT_ITEM, ROOT_PARAMS));
MediaItem rootItem = ROOT_ITEM;
// Use connection hints to select the library root.
String customLibraryRoot =
browser
.getConnectionHints()
.getString(CONNECTION_HINTS_CUSTOM_LIBRARY_ROOT, /* defaultValue= */ null);
if (customLibraryRoot != null) {
rootItem =
new MediaItem.Builder()
.setMediaId(customLibraryRoot)
.setMediaMetadata(
new MediaMetadata.Builder()
.setFolderType(MediaMetadata.FOLDER_TYPE_ALBUMS)
.setIsPlayable(false)
.build())
.build();
}
return Futures.immediateFuture(LibraryResult.ofItem(rootItem, ROOT_PARAMS));
}
@Override
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment