mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Use connection hints when connecting to MediaBrowserService
Minor improvement to allow an Media3 browser to pass extras when connecting the initial browser in `MediaControllerImplLegacy`. Before this change an empty bundle was sent. After this change the connection hints of the `Media3 browser is used as root hints of the initial browser that connects when the Media3 browser is built in `MediaBrowser.buildAsync`. #cherrypick PiperOrigin-RevId: 684372552
This commit is contained in:
parent
b6d0540059
commit
cbc0ee369f
@ -112,6 +112,10 @@
|
|||||||
* Fix bug where a Media3 controller was sometimes unable to let a session
|
* Fix bug where a Media3 controller was sometimes unable to let a session
|
||||||
app start a foreground service after requesting `play()`.
|
app start a foreground service after requesting `play()`.
|
||||||
* Restrict `CommandButton.Builder.setIconUri` to only accept content Uris.
|
* Restrict `CommandButton.Builder.setIconUri` to only accept content Uris.
|
||||||
|
* Pass connection hints of a Media3 browser to the initial
|
||||||
|
`MediaBrowserCompat` when connecting to a legacy `MediaBrowserCompat`.
|
||||||
|
The service can receive the connection hints passed in as root hints
|
||||||
|
with the first call to `onGetRoot()`.
|
||||||
* UI:
|
* UI:
|
||||||
* Make the stretched/cropped video in
|
* Make the stretched/cropped video in
|
||||||
`PlayerView`-in-Compose-`AndroidView` workaround opt-in, due to issues
|
`PlayerView`-in-Compose-`AndroidView` workaround opt-in, due to issues
|
||||||
|
@ -292,7 +292,7 @@ public final class MediaBrowser extends MediaController {
|
|||||||
if (token.isLegacySession()) {
|
if (token.isLegacySession()) {
|
||||||
impl =
|
impl =
|
||||||
new MediaBrowserImplLegacy(
|
new MediaBrowserImplLegacy(
|
||||||
context, this, token, applicationLooper, checkNotNull(bitmapLoader));
|
context, this, token, connectionHints, applicationLooper, checkNotNull(bitmapLoader));
|
||||||
} else {
|
} else {
|
||||||
impl = new MediaBrowserImplBase(context, this, token, connectionHints, applicationLooper);
|
impl = new MediaBrowserImplBase(context, this, token, connectionHints, applicationLooper);
|
||||||
}
|
}
|
||||||
|
@ -62,9 +62,10 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
|||||||
Context context,
|
Context context,
|
||||||
@UnderInitialization MediaBrowser instance,
|
@UnderInitialization MediaBrowser instance,
|
||||||
SessionToken token,
|
SessionToken token,
|
||||||
|
Bundle connectionHints,
|
||||||
Looper applicationLooper,
|
Looper applicationLooper,
|
||||||
BitmapLoader bitmapLoader) {
|
BitmapLoader bitmapLoader) {
|
||||||
super(context, instance, token, applicationLooper, bitmapLoader);
|
super(context, instance, token, connectionHints, applicationLooper, bitmapLoader);
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
commandButtonsForMediaItems = ImmutableMap.of();
|
commandButtonsForMediaItems = ImmutableMap.of();
|
||||||
}
|
}
|
||||||
|
@ -568,7 +568,7 @@ public class MediaController implements Player {
|
|||||||
@Nullable BitmapLoader bitmapLoader) {
|
@Nullable BitmapLoader bitmapLoader) {
|
||||||
if (token.isLegacySession()) {
|
if (token.isLegacySession()) {
|
||||||
return new MediaControllerImplLegacy(
|
return new MediaControllerImplLegacy(
|
||||||
context, this, token, applicationLooper, checkNotNull(bitmapLoader));
|
context, this, token, connectionHints, applicationLooper, checkNotNull(bitmapLoader));
|
||||||
} else {
|
} else {
|
||||||
return new MediaControllerImplBase(context, this, token, connectionHints, applicationLooper);
|
return new MediaControllerImplBase(context, this, token, connectionHints, applicationLooper);
|
||||||
}
|
}
|
||||||
@ -2073,6 +2073,10 @@ public class MediaController implements Player {
|
|||||||
return impl.getBinder();
|
return impl.getBinder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* package */ Bundle getConnectionHints() {
|
||||||
|
return impl.getConnectionHints();
|
||||||
|
}
|
||||||
|
|
||||||
private void verifyApplicationThread() {
|
private void verifyApplicationThread() {
|
||||||
checkState(Looper.myLooper() == getApplicationLooper(), WRONG_THREAD_ERROR_MESSAGE);
|
checkState(Looper.myLooper() == getApplicationLooper(), WRONG_THREAD_ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
@ -2081,6 +2085,8 @@ public class MediaController implements Player {
|
|||||||
|
|
||||||
void connect(@UnderInitialization MediaControllerImpl this);
|
void connect(@UnderInitialization MediaControllerImpl this);
|
||||||
|
|
||||||
|
Bundle getConnectionHints();
|
||||||
|
|
||||||
void addListener(Player.Listener listener);
|
void addListener(Player.Listener listener);
|
||||||
|
|
||||||
void removeListener(Player.Listener listener);
|
void removeListener(Player.Listener listener);
|
||||||
|
@ -215,6 +215,11 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle getConnectionHints() {
|
||||||
|
return connectionHints;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addListener(Listener listener) {
|
public void addListener(Listener listener) {
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
|
@ -102,6 +102,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
|||||||
private final ControllerCompatCallback controllerCompatCallback;
|
private final ControllerCompatCallback controllerCompatCallback;
|
||||||
private final BitmapLoader bitmapLoader;
|
private final BitmapLoader bitmapLoader;
|
||||||
private final ImmutableList<CommandButton> commandButtonsForMediaItems;
|
private final ImmutableList<CommandButton> commandButtonsForMediaItems;
|
||||||
|
private final Bundle connectionHints;
|
||||||
|
|
||||||
@Nullable private MediaControllerCompat controllerCompat;
|
@Nullable private MediaControllerCompat controllerCompat;
|
||||||
@Nullable private MediaBrowserCompat browserCompat;
|
@Nullable private MediaBrowserCompat browserCompat;
|
||||||
@ -117,6 +118,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
|||||||
Context context,
|
Context context,
|
||||||
@UnderInitialization MediaController instance,
|
@UnderInitialization MediaController instance,
|
||||||
SessionToken token,
|
SessionToken token,
|
||||||
|
Bundle connectionHints,
|
||||||
Looper applicationLooper,
|
Looper applicationLooper,
|
||||||
BitmapLoader bitmapLoader) {
|
BitmapLoader bitmapLoader) {
|
||||||
// Initialize default values.
|
// Initialize default values.
|
||||||
@ -134,6 +136,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
|||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
controllerCompatCallback = new ControllerCompatCallback(applicationLooper);
|
controllerCompatCallback = new ControllerCompatCallback(applicationLooper);
|
||||||
this.token = token;
|
this.token = token;
|
||||||
|
this.connectionHints = connectionHints;
|
||||||
this.bitmapLoader = bitmapLoader;
|
this.bitmapLoader = bitmapLoader;
|
||||||
currentPositionMs = C.TIME_UNSET;
|
currentPositionMs = C.TIME_UNSET;
|
||||||
lastSetPlayWhenReadyCalledTimeMs = C.TIME_UNSET;
|
lastSetPlayWhenReadyCalledTimeMs = C.TIME_UNSET;
|
||||||
@ -154,6 +157,11 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle getConnectionHints() {
|
||||||
|
return connectionHints;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addListener(Listener listener) {
|
public void addListener(Listener listener) {
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
@ -1410,7 +1418,10 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
|||||||
// Create it on the application looper to respect that.
|
// Create it on the application looper to respect that.
|
||||||
browserCompat =
|
browserCompat =
|
||||||
new MediaBrowserCompat(
|
new MediaBrowserCompat(
|
||||||
context, token.getComponentName(), new ConnectionCallback(), null);
|
context,
|
||||||
|
token.getComponentName(),
|
||||||
|
new ConnectionCallback(),
|
||||||
|
instance.getConnectionHints());
|
||||||
browserCompat.connect();
|
browserCompat.connect();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import static androidx.media3.session.LibraryResult.RESULT_SUCCESS;
|
|||||||
import static androidx.media3.session.MediaConstants.EXTRAS_KEY_COMPLETION_STATUS;
|
import static androidx.media3.session.MediaConstants.EXTRAS_KEY_COMPLETION_STATUS;
|
||||||
import static androidx.media3.session.MediaConstants.EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED;
|
import static androidx.media3.session.MediaConstants.EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED;
|
||||||
import static androidx.media3.session.MediaConstants.EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY;
|
import static androidx.media3.session.MediaConstants.EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY;
|
||||||
|
import static androidx.media3.session.MockMediaBrowserServiceCompat.EXTRAS_KEY_SEND_ROOT_HINTS_AS_SESSION_EXTRAS;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.MOCK_MEDIA_BROWSER_SERVICE_COMPAT;
|
import static androidx.media3.test.session.common.CommonConstants.MOCK_MEDIA_BROWSER_SERVICE_COMPAT;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.PARENT_ID;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.PARENT_ID;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS_KEY;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS_KEY;
|
||||||
@ -136,6 +137,33 @@ public class MediaBrowserListenerWithMediaBrowserServiceCompatTest {
|
|||||||
assertThat(thrown).hasCauseThat().isInstanceOf(SecurityException.class);
|
assertThat(thrown).hasCauseThat().isInstanceOf(SecurityException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void connect_useConnectionHints_connectionHintsPassedToLegacyServerOnGetRootAsRootHints()
|
||||||
|
throws Exception {
|
||||||
|
Bundle connectionHints = new Bundle();
|
||||||
|
connectionHints.putBoolean(EXTRAS_KEY_SEND_ROOT_HINTS_AS_SESSION_EXTRAS, true);
|
||||||
|
CountDownLatch latch = new CountDownLatch(/* count= */ 1);
|
||||||
|
AtomicReference<Bundle> extrasRef = new AtomicReference<>();
|
||||||
|
createBrowser(
|
||||||
|
connectionHints,
|
||||||
|
/* maxCommandsForMediaItems= */ 0,
|
||||||
|
/* listener= */ new MediaBrowser.Listener() {
|
||||||
|
@Override
|
||||||
|
public void onExtrasChanged(MediaController controller, Bundle extras) {
|
||||||
|
extrasRef.set(extras);
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||||
|
assertThat(
|
||||||
|
extrasRef
|
||||||
|
.get()
|
||||||
|
.getBoolean(
|
||||||
|
EXTRAS_KEY_SEND_ROOT_HINTS_AS_SESSION_EXTRAS, /* defaultValue= */ false))
|
||||||
|
.isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getLibraryRoot_browseActionsAvailable() throws Exception {
|
public void getLibraryRoot_browseActionsAvailable() throws Exception {
|
||||||
remoteService.setProxyForTest(TEST_MEDIA_ITEMS_WITH_BROWSE_ACTIONS);
|
remoteService.setProxyForTest(TEST_MEDIA_ITEMS_WITH_BROWSE_ACTIONS);
|
||||||
|
@ -40,7 +40,9 @@ import static java.lang.Math.min;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.Looper;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.support.v4.media.MediaBrowserCompat;
|
import android.support.v4.media.MediaBrowserCompat;
|
||||||
import android.support.v4.media.MediaBrowserCompat.MediaItem;
|
import android.support.v4.media.MediaBrowserCompat.MediaItem;
|
||||||
@ -68,6 +70,13 @@ public class MockMediaBrowserServiceCompat extends MediaBrowserServiceCompat {
|
|||||||
*/
|
*/
|
||||||
public static final ImmutableList<MediaItem> MEDIA_ITEMS = createMediaItems();
|
public static final ImmutableList<MediaItem> MEDIA_ITEMS = createMediaItems();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key in the browser root hints to request a confirmation of the call to {@link
|
||||||
|
* #onGetRoot(String, int, Bundle)}.
|
||||||
|
*/
|
||||||
|
public static final String EXTRAS_KEY_SEND_ROOT_HINTS_AS_SESSION_EXTRAS =
|
||||||
|
"confirm_on_get_root_with_custom_action";
|
||||||
|
|
||||||
private static final String TAG = "MockMBSCompat";
|
private static final String TAG = "MockMBSCompat";
|
||||||
private static final Object lock = new Object();
|
private static final Object lock = new Object();
|
||||||
|
|
||||||
@ -166,12 +175,18 @@ public class MockMediaBrowserServiceCompat extends MediaBrowserServiceCompat {
|
|||||||
// Test only -- reject any other request.
|
// Test only -- reject any other request.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (rootHints.getBoolean(EXTRAS_KEY_SEND_ROOT_HINTS_AS_SESSION_EXTRAS, false)) {
|
||||||
|
// Send delayed because the Media3 browser is in the process of connecting at this point and
|
||||||
|
// won't receive listener callbacks before being connected.
|
||||||
|
new Handler(Looper.myLooper())
|
||||||
|
.postDelayed(() -> sessionCompat.setExtras(rootHints), /* delayMillis= */ 100L);
|
||||||
|
}
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
if (isProxyOverridesMethod("onGetRoot")) {
|
if (isProxyOverridesMethod("onGetRoot")) {
|
||||||
return serviceProxy.onGetRoot(clientPackageName, clientUid, rootHints);
|
return serviceProxy.onGetRoot(clientPackageName, clientUid, rootHints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new BrowserRoot("stub", null);
|
return new BrowserRoot("stub", /* extras= */ rootHints);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user