Skip to content

Commit

Permalink
Migrate BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS to Media3
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 490376734
  • Loading branch information
marcbaechinger authored and icbaker committed Nov 24, 2022
1 parent 8ce1213 commit 1803d1c
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -389,12 +389,31 @@ public final class MediaConstants {
*
* @see MediaLibrarySession.Callback#onGetLibraryRoot(MediaLibrarySession,
* MediaSession.ControllerInfo, LibraryParams)
* @see MediaBrowser#getLibraryRoot(LibraryParams)
* @see LibraryParams#extras
*/
@UnstableApi
public static final String EXTRAS_KEY_ROOT_CHILDREN_LIMIT =
androidx.media.utils.MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT;

/**
* {@link Bundle} key used in {@link LibraryParams#extras} passed to {@link
* MediaLibrarySession.Callback#onGetLibraryRoot(MediaLibrarySession, MediaSession.ControllerInfo,
* LibraryParams)} to indicate whether only browsable media items are supported as children of the
* root node by the {@link MediaBrowser}. If true, root children that are not browsable may be
* omitted or made less discoverable.
*
* <p>TYPE: boolean.
*
* @see MediaLibrarySession.Callback#onGetLibraryRoot(MediaLibrarySession,
* MediaSession.ControllerInfo, LibraryParams)
* @see MediaBrowser#getLibraryRoot(LibraryParams)
* @see LibraryParams#extras
*/
@UnstableApi
public static final String EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY =
"androidx.media3.session.LibraryParams.Extras.KEY_ROOT_CHILDREN_BROWSABLE_ONLY";

/**
* {@link Bundle} key used in {@link LibraryParams#extras} passed by the {@link MediaBrowser} as
* root hints to {@link MediaLibrarySession.Callback#onGetLibraryRoot(MediaLibrarySession,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package androidx.media3.session;

import static android.support.v4.media.session.MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS;
import static androidx.media.utils.MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS;
import static androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME;
import static androidx.media3.common.Player.COMMAND_CHANGE_MEDIA_ITEMS;
import static androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM;
Expand All @@ -38,6 +39,7 @@
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Util.castNonNull;
import static androidx.media3.common.util.Util.constrainValue;
import static androidx.media3.session.MediaConstants.EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY;
import static java.lang.Math.max;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

Expand Down Expand Up @@ -996,6 +998,15 @@ public static LibraryParams convertToLibraryParams(
}
try {
legacyBundle.setClassLoader(context.getClassLoader());
int supportedChildrenFlags =
legacyBundle.getInt(
BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS, /* defaultValue= */ -1);
if (supportedChildrenFlags >= 0) {
legacyBundle.remove(BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS);
legacyBundle.putBoolean(
EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY,
supportedChildrenFlags == MediaBrowserCompat.MediaItem.FLAG_BROWSABLE);
}
return new LibraryParams.Builder()
.setExtras(legacyBundle)
.setRecent(legacyBundle.getBoolean(BrowserRoot.EXTRA_RECENT))
Expand All @@ -1015,6 +1026,18 @@ public static Bundle convertToRootHints(@Nullable LibraryParams params) {
return null;
}
Bundle rootHints = new Bundle(params.extras);
if (params.extras.containsKey(EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY)) {
boolean browsableChildrenSupported =
params.extras.getBoolean(
EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY, /* defaultValue= */ false);
rootHints.remove(EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY);
rootHints.putInt(
BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS,
browsableChildrenSupported
? MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
: MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
| MediaBrowserCompat.MediaItem.FLAG_PLAYABLE);
}
rootHints.putBoolean(BrowserRoot.EXTRA_RECENT, params.isRecent);
rootHints.putBoolean(BrowserRoot.EXTRA_OFFLINE, params.isOffline);
rootHints.putBoolean(BrowserRoot.EXTRA_SUGGESTED, params.isSuggested);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
public class MediaBrowserConstants {

public static final String ROOT_ID = "rootId";
public static final String ROOT_ID_SUPPORTS_BROWSABLE_CHILDREN_ONLY =
"root_id_supports_browsable_children_only";
public static final Bundle ROOT_EXTRAS = new Bundle();
public static final String ROOT_EXTRAS_KEY = "root_extras_key";
public static final int ROOT_EXTRAS_VALUE = 4321;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS_KEY;
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS_VALUE;
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_ID;
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_ID_SUPPORTS_BROWSABLE_CHILDREN_ONLY;
import static androidx.media3.test.session.common.MediaBrowserConstants.SEARCH_QUERY;
import static androidx.media3.test.session.common.MediaBrowserConstants.SEARCH_QUERY_EMPTY_RESULT;
import static androidx.media3.test.session.common.MediaBrowserConstants.SEARCH_QUERY_ERROR;
Expand Down Expand Up @@ -615,4 +616,31 @@ public void rootBrowserHints_searchNotSupported_reportsSearchNotSupported() thro

assertThat(isSearchSupported).isFalse();
}

@Test
public void rootBrowserHints_legacyBrowsableFlagSet_receivesRootWithBrowsableChildrenOnly()
throws Exception {
Bundle rootHints = new Bundle();
rootHints.putInt(
androidx.media.utils.MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS,
MediaItem.FLAG_BROWSABLE);
connectAndWait(rootHints);

String root = browserCompat.getRoot();

assertThat(root).isEqualTo(ROOT_ID_SUPPORTS_BROWSABLE_CHILDREN_ONLY);
}

@Test
public void rootBrowserHints_legacyPlayableFlagSet_receivesDefaultRoot() throws Exception {
Bundle connectionHints = new Bundle();
connectionHints.putInt(
androidx.media.utils.MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS,
MediaItem.FLAG_BROWSABLE | MediaItem.FLAG_PLAYABLE);
connectAndWait(connectionHints);

String root = browserCompat.getRoot();

assertThat(root).isEqualTo(ROOT_ID);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,12 @@ ComponentName getServiceComponent() {
return MOCK_MEDIA3_SESSION_SERVICE;
}

void connectAndWait(Bundle connectionHints) throws Exception {
void connectAndWait(Bundle rootHints) throws Exception {
handler.postAndSync(
() -> {
// Make browser's internal handler to be initialized with test thread.
browserCompat =
new MediaBrowserCompat(
context, getServiceComponent(), connectionCallback, connectionHints);
new MediaBrowserCompat(context, getServiceComponent(), connectionCallback, rootHints);
});
browserCompat.connect();
assertThat(connectionCallback.connectedLatch.await(SERVICE_CONNECTION_TIMEOUT_MS, MILLISECONDS))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@
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_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED;
import static androidx.media3.session.MediaConstants.EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY;
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.ROOT_EXTRAS_KEY;
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS_VALUE;
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_ID;
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_ID_SUPPORTS_BROWSABLE_CHILDREN_ONLY;
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_CONNECT_REJECTED;
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_GET_CHILDREN;
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_GET_LIBRARY_ROOT;
Expand Down Expand Up @@ -163,6 +166,48 @@ public void getLibraryRoot_correctExtraKeyAndValue() throws Exception {
assertThat(extras.getInt(ROOT_EXTRAS_KEY, ROOT_EXTRAS_VALUE + 1)).isEqualTo(ROOT_EXTRAS_VALUE);
}

@Test
public void getLibraryRoot_browsableRootChildrenOnly_receivesRootWithBrowsableChildrenOnly()
throws Exception {
remoteService.setProxyForTest(TEST_GET_LIBRARY_ROOT);
MediaBrowser browser = createBrowser(/* listener= */ null);

LibraryResult<MediaItem> resultForLibraryRoot =
threadTestRule
.getHandler()
.postAndSync(
() -> {
Bundle extras = new Bundle();
extras.putBoolean(EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY, true);
return browser.getLibraryRoot(
new LibraryParams.Builder().setExtras(extras).build());
})
.get(TIMEOUT_MS, MILLISECONDS);

assertThat(resultForLibraryRoot.value.mediaId)
.isEqualTo(ROOT_ID_SUPPORTS_BROWSABLE_CHILDREN_ONLY);
}

@Test
public void getLibraryRoot_browsableRootChildrenOnlyFalse_receivesDefaultRoot() throws Exception {
remoteService.setProxyForTest(TEST_GET_LIBRARY_ROOT);
MediaBrowser browser = createBrowser(/* listener= */ null);

LibraryResult<MediaItem> resultForLibraryRoot =
threadTestRule
.getHandler()
.postAndSync(
() -> {
Bundle extras = new Bundle();
extras.putBoolean(EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY, false);
return browser.getLibraryRoot(
new LibraryParams.Builder().setExtras(extras).build());
})
.get(TIMEOUT_MS, MILLISECONDS);

assertThat(resultForLibraryRoot.value.mediaId).isEqualTo(ROOT_ID);
}

@Test
public void getChildren_correctMetadataExtras() throws Exception {
LibraryParams params = MediaTestUtils.createLibraryParams();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@
*/
package androidx.media3.session;

import static android.support.v4.media.MediaBrowserCompat.MediaItem.FLAG_BROWSABLE;
import static android.support.v4.media.MediaBrowserCompat.MediaItem.FLAG_PLAYABLE;
import static android.support.v4.media.MediaMetadataCompat.METADATA_KEY_DURATION;
import static android.support.v4.media.session.MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS;
import static androidx.media.utils.MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS;
import static androidx.media3.session.MediaConstants.EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY;
import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.SECONDS;

Expand All @@ -34,6 +38,7 @@
import android.support.v4.media.session.PlaybackStateCompat;
import androidx.annotation.Nullable;
import androidx.media.AudioAttributesCompat;
import androidx.media.utils.MediaConstants;
import androidx.media3.common.AudioAttributes;
import androidx.media3.common.C;
import androidx.media3.common.HeartRating;
Expand Down Expand Up @@ -271,35 +276,107 @@ public void convertToLibraryParams() {
assertThat(MediaUtils.convertToLibraryParams(context, null)).isNull();
Bundle rootHints = new Bundle();
rootHints.putString("key", "value");
rootHints.putInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS, FLAG_BROWSABLE);
rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_OFFLINE, true);
rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_SUGGESTED, true);

MediaLibraryService.LibraryParams params =
MediaUtils.convertToLibraryParams(context, rootHints);

assertThat(params.extras.getString("key")).isEqualTo("value");
assertThat(params.extras.getBoolean(EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY)).isTrue();
assertThat(params.extras.containsKey(BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS))
.isFalse();
assertThat(params.isOffline).isTrue();
assertThat(params.isRecent).isTrue();
assertThat(params.isSuggested).isTrue();
assertThat(params.extras.getString("key")).isEqualTo("value");
}

@Test
public void convertToLibraryParams_rootHintsBrowsableNoFlagSet_browsableOnlyFalse() {
Bundle rootHints = new Bundle();
rootHints.putInt(MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS, 0);

MediaLibraryService.LibraryParams params =
MediaUtils.convertToLibraryParams(context, rootHints);

assertThat(params.extras.getBoolean(EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY)).isFalse();
}

@Test
public void convertToLibraryParams_rootHintsPlayableFlagSet_browsableOnlyFalse() {
Bundle rootHints = new Bundle();
rootHints.putInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS,
FLAG_PLAYABLE | FLAG_BROWSABLE);

MediaLibraryService.LibraryParams params =
MediaUtils.convertToLibraryParams(context, rootHints);

assertThat(params.extras.getBoolean(EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY)).isFalse();
}

@Test
public void convertToLibraryParams_rootHintsBrowsableAbsentKey_browsableOnlyFalse() {
MediaLibraryService.LibraryParams params =
MediaUtils.convertToLibraryParams(context, /* legacyBundle= */ Bundle.EMPTY);

assertThat(params.extras.getBoolean(EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY)).isFalse();
}

@Test
public void convertToRootHints() {
assertThat(MediaUtils.convertToRootHints(null)).isNull();
Bundle extras = new Bundle();
extras.putString("key", "value");
extras.putBoolean(EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY, true);
MediaLibraryService.LibraryParams param =
new MediaLibraryService.LibraryParams.Builder()
.setOffline(true)
.setRecent(true)
.setSuggested(true)
.setExtras(extras)
.build();

Bundle rootHints = MediaUtils.convertToRootHints(param);

assertThat(
rootHints.getInt(
BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS, /* defaultValue= */ 0))
.isEqualTo(FLAG_BROWSABLE);
assertThat(rootHints.getString("key")).isEqualTo("value");
assertThat(rootHints.get(EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY)).isNull();
assertThat(rootHints.getBoolean(MediaBrowserService.BrowserRoot.EXTRA_OFFLINE)).isTrue();
assertThat(rootHints.getBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT)).isTrue();
assertThat(rootHints.getBoolean(MediaBrowserService.BrowserRoot.EXTRA_SUGGESTED)).isTrue();
assertThat(rootHints.getString("key")).isEqualTo("value");
}

@Test
public void convertToRootHints_browsableOnlyFalse_correctLegacyBrowsableFlags() {
Bundle extras = new Bundle();
extras.putBoolean(EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY, false);
MediaLibraryService.LibraryParams param =
new MediaLibraryService.LibraryParams.Builder().setExtras(extras).build();

Bundle rootHints = MediaUtils.convertToRootHints(param);

assertThat(
rootHints.getInt(
BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS, /* defaultValue= */ -1))
.isEqualTo(FLAG_BROWSABLE | FLAG_PLAYABLE);
assertThat(rootHints.get(EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY)).isNull();
}

@Test
public void convertToRootHints_browsableAbsentKey_noLegacyKeyAdded() {
MediaLibraryService.LibraryParams param =
new MediaLibraryService.LibraryParams.Builder().build();

Bundle rootHints = MediaUtils.convertToRootHints(param);

assertThat(rootHints.get(BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS)).isNull();
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import static androidx.media3.test.session.common.CommonConstants.SUPPORT_APP_PACKAGE_NAME;
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS;
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_ID;
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_ID_SUPPORTS_BROWSABLE_CHILDREN_ONLY;
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_CONNECT_REJECTED;
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_GET_CHILDREN;
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_GET_LIBRARY_ROOT;
Expand All @@ -37,6 +38,7 @@
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.MediaSessionCompat.Callback;
import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable;
import androidx.media.MediaBrowserServiceCompat;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.test.session.common.IRemoteMediaBrowserServiceCompat;
Expand Down Expand Up @@ -303,7 +305,18 @@ private void setProxyForTestGetLibraryRoot_correctExtraKeyAndValue() {
new MockMediaBrowserServiceCompat.Proxy() {
@Override
public BrowserRoot onGetRoot(
String clientPackageName, int clientUid, Bundle rootHints) {
String clientPackageName, int clientUid, @Nullable Bundle rootHints) {
if (rootHints != null) {
// On API levels lower than 21 root hints are null.
int supportedRootChildrenFlags =
rootHints.getInt(
androidx.media.utils.MediaConstants
.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS,
/* defaultValue= */ 0);
if ((supportedRootChildrenFlags == MediaItem.FLAG_BROWSABLE)) {
return new BrowserRoot(ROOT_ID_SUPPORTS_BROWSABLE_CHILDREN_ONLY, ROOT_EXTRAS);
}
}
return new BrowserRoot(ROOT_ID, ROOT_EXTRAS);
}
});
Expand Down
Loading

0 comments on commit 1803d1c

Please sign in to comment.