From 1803d1cdb8cf429c3d0a3fdbbecbad25145db8c4 Mon Sep 17 00:00:00 2001 From: bachinger Date: Wed, 23 Nov 2022 01:42:43 +0000 Subject: [PATCH] Migrate BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS to Media3 PiperOrigin-RevId: 490376734 --- .../media3/session/MediaConstants.java | 19 +++++ .../androidx/media3/session/MediaUtils.java | 23 ++++++ .../session/common/MediaBrowserConstants.java | 2 + ...wserCompatWithMediaLibraryServiceTest.java | 28 +++++++ ...wserCompatWithMediaSessionServiceTest.java | 5 +- ...enerWithMediaBrowserServiceCompatTest.java | 45 +++++++++++ .../media3/session/MediaUtilsTest.java | 81 ++++++++++++++++++- .../MockMediaBrowserServiceCompat.java | 15 +++- .../session/MockMediaLibraryService.java | 18 +++++ 9 files changed, 230 insertions(+), 6 deletions(-) diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaConstants.java b/libraries/session/src/main/java/androidx/media3/session/MediaConstants.java index 0ebcd49075..d79385f5e4 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaConstants.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaConstants.java @@ -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. + * + *

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, diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java b/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java index 97d240032c..64a25e0eb9 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java @@ -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; @@ -38,6 +39,7 @@ import static androidx.media3.common.Player.COMMAND_STOP; 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; @@ -996,6 +998,15 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; } 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)) @@ -1015,6 +1026,18 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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); diff --git a/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/MediaBrowserConstants.java b/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/MediaBrowserConstants.java index 65e7847199..6cf1ce19e1 100644 --- a/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/MediaBrowserConstants.java +++ b/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/MediaBrowserConstants.java @@ -25,6 +25,8 @@ import java.util.List; 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; diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaBrowserCompatWithMediaLibraryServiceTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaBrowserCompatWithMediaLibraryServiceTest.java index 4e36a19ece..4e3ae96507 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaBrowserCompatWithMediaLibraryServiceTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaBrowserCompatWithMediaLibraryServiceTest.java @@ -45,6 +45,7 @@ import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXT 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; @@ -615,4 +616,31 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest 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); + } } diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaBrowserCompatWithMediaSessionServiceTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaBrowserCompatWithMediaSessionServiceTest.java index 12caed0f8e..4199b8f610 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaBrowserCompatWithMediaSessionServiceTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaBrowserCompatWithMediaSessionServiceTest.java @@ -82,13 +82,12 @@ public class MediaBrowserCompatWithMediaSessionServiceTest { 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)) diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaBrowserListenerWithMediaBrowserServiceCompatTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaBrowserListenerWithMediaBrowserServiceCompatTest.java index d9f8a0afd0..30bd1c83a2 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaBrowserListenerWithMediaBrowserServiceCompatTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaBrowserListenerWithMediaBrowserServiceCompatTest.java @@ -18,10 +18,13 @@ package androidx.media3.session; 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; @@ -163,6 +166,48 @@ public class MediaBrowserListenerWithMediaBrowserServiceCompatTest { 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 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 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(); diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaUtilsTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaUtilsTest.java index 8ff1473cbc..80dd8073b4 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaUtilsTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaUtilsTest.java @@ -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; @@ -34,6 +38,7 @@ import android.support.v4.media.session.MediaSessionCompat; 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; @@ -271,16 +276,54 @@ public final class MediaUtilsTest { 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 @@ -288,6 +331,7 @@ public final class MediaUtilsTest { 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) @@ -295,11 +339,44 @@ public final class MediaUtilsTest { .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 diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/MockMediaBrowserServiceCompat.java b/libraries/test_session_current/src/main/java/androidx/media3/session/MockMediaBrowserServiceCompat.java index 65ce255a30..19bce9153d 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/MockMediaBrowserServiceCompat.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/MockMediaBrowserServiceCompat.java @@ -22,6 +22,7 @@ import static androidx.media3.session.MediaConstants.EXTRAS_VALUE_COMPLETION_STA 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; @@ -37,6 +38,7 @@ import android.support.v4.media.MediaDescriptionCompat; 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; @@ -303,7 +305,18 @@ public class MockMediaBrowserServiceCompat extends MediaBrowserServiceCompat { 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); } }); diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/MockMediaLibraryService.java b/libraries/test_session_current/src/main/java/androidx/media3/session/MockMediaLibraryService.java index e3023a00a2..d460bee20b 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/MockMediaLibraryService.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/MockMediaLibraryService.java @@ -20,6 +20,7 @@ import static androidx.media3.session.MediaConstants.EXTRAS_KEY_COMPLETION_STATU import static androidx.media3.session.MediaConstants.EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT_COMPAT; import static androidx.media3.session.MediaConstants.EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL_COMPAT; 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.MediaTestUtils.assertLibraryParamsEquals; import static androidx.media3.test.session.common.CommonConstants.SUPPORT_APP_PACKAGE_NAME; import static androidx.media3.test.session.common.MediaBrowserConstants.CUSTOM_ACTION; @@ -39,6 +40,7 @@ import static androidx.media3.test.session.common.MediaBrowserConstants.PARENT_I import static androidx.media3.test.session.common.MediaBrowserConstants.PARENT_ID_LONG_LIST; 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.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_LONG_LIST; @@ -232,6 +234,22 @@ public class MockMediaLibraryService extends MediaLibraryService { .build()) .build(); } + if (params != null) { + boolean browsableRootChildrenOnly = + params.extras.getBoolean( + EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY, /* defaultValue= */ false); + if (browsableRootChildrenOnly) { + rootItem = + new MediaItem.Builder() + .setMediaId(ROOT_ID_SUPPORTS_BROWSABLE_CHILDREN_ONLY) + .setMediaMetadata( + new MediaMetadata.Builder() + .setFolderType(MediaMetadata.FOLDER_TYPE_MIXED) + .setIsPlayable(false) + .build()) + .build(); + } + } return Futures.immediateFuture(LibraryResult.ofItem(rootItem, ROOT_PARAMS)); }