Enable cast via MediaSession2/MediaController2
Bug: 77659082
Test: ./gradlew :media:check :media:connectedCheck
Change-Id: Ia74e92b9dcab26f26b7e6e0bfef5718205bf3b78
diff --git a/media/src/androidTest/java/androidx/media/MediaController2Test.java b/media/src/androidTest/java/androidx/media/MediaController2Test.java
index 4cb51d3..a9be286 100644
--- a/media/src/androidTest/java/androidx/media/MediaController2Test.java
+++ b/media/src/androidTest/java/androidx/media/MediaController2Test.java
@@ -1092,6 +1092,62 @@
}
@Test
+ public void testSubscribeRouteInfo() throws InterruptedException {
+ prepareLooper();
+ final TestSessionCallback callback = new TestSessionCallback() {
+ @Override
+ public void onSubscribeRoutesInfo(@NonNull MediaSession2 session,
+ @NonNull ControllerInfo controller) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ mLatch.countDown();
+ }
+
+ @Override
+ public void onUnsubscribeRoutesInfo(@NonNull MediaSession2 session,
+ @NonNull ControllerInfo controller) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ mLatch.countDown();
+ }
+ };
+ mSession.close();
+ mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback).setId(TAG).build();
+ final MediaController2 controller = createController(mSession.getToken());
+
+ callback.resetLatchCount(1);
+ controller.subscribeRoutesInfo();
+ assertTrue(callback.mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ callback.resetLatchCount(1);
+ controller.unsubscribeRoutesInfo();
+ assertTrue(callback.mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testSelectRouteInfo() throws InterruptedException {
+ prepareLooper();
+ final Bundle testRoute = new Bundle();
+ testRoute.putString("id", "testRoute");
+ final TestSessionCallback callback = new TestSessionCallback() {
+ @Override
+ public void onSelectRoute(@NonNull MediaSession2 session,
+ @NonNull ControllerInfo controller, @NonNull Bundle route) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertTrue(TestUtils.equals(route, testRoute));
+ mLatch.countDown();
+ }
+ };
+ mSession.close();
+ mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback).setId(TAG).build();
+ final MediaController2 controller = createController(mSession.getToken());
+
+ callback.resetLatchCount(1);
+ controller.selectRoute(testRoute);
+ assertTrue(callback.mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
public void testClose_beforeConnected() throws InterruptedException {
prepareLooper();
MediaController2 controller =
@@ -1222,4 +1278,12 @@
mLatch.countDown();
}
}
+
+ class TestSessionCallback extends SessionCallback {
+ CountDownLatch mLatch;
+
+ void resetLatchCount(int count) {
+ mLatch = new CountDownLatch(count);
+ }
+ }
}
diff --git a/media/src/androidTest/java/androidx/media/MediaSession2Test.java b/media/src/androidTest/java/androidx/media/MediaSession2Test.java
index 77dbf43..39764c6 100644
--- a/media/src/androidTest/java/androidx/media/MediaSession2Test.java
+++ b/media/src/androidTest/java/androidx/media/MediaSession2Test.java
@@ -38,6 +38,7 @@
import android.support.test.runner.AndroidJUnit4;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.media.MediaController2.ControllerCallback;
import androidx.media.MediaController2.PlaybackInfo;
import androidx.media.MediaSession2.CommandButton;
@@ -827,6 +828,24 @@
assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
}
+ @Test
+ public void testNotifyRoutesInfoChanged() throws InterruptedException {
+ prepareLooper();
+ final CountDownLatch latch = new CountDownLatch(1);
+ final ControllerCallback callback = new ControllerCallback() {
+ @Override
+ public void onRoutesInfoChanged(@NonNull MediaController2 controller,
+ @Nullable List<Bundle> routes) {
+ assertNull(routes);
+ latch.countDown();
+ }
+ };
+ final MediaController2 controller = createController(mSession.getToken(), true, callback);
+ ControllerInfo controllerInfo = getTestControllerInfo();
+ mSession.notifyRoutesInfoChanged(controllerInfo, null);
+ assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ }
+
private ControllerInfo getTestControllerInfo() {
List<ControllerInfo> controllers = mSession.getConnectedControllers();
assertNotNull(controllers);
diff --git a/media/src/androidTest/java/androidx/media/MediaSession2TestBase.java b/media/src/androidTest/java/androidx/media/MediaSession2TestBase.java
index bc9a31d..745ef3a 100644
--- a/media/src/androidTest/java/androidx/media/MediaSession2TestBase.java
+++ b/media/src/androidTest/java/androidx/media/MediaSession2TestBase.java
@@ -339,6 +339,12 @@
mOnCustomCommandRunnable = runnable;
}
}
+
+ @Override
+ public void onRoutesInfoChanged(@NonNull MediaController2 controller,
+ @Nullable List<Bundle> routes) {
+ mCallbackProxy.onRoutesInfoChanged(controller, routes);
+ }
}
public class TestMediaController extends MediaController2 implements TestControllerInterface {
diff --git a/media/src/main/java/androidx/media/MediaConstants2.java b/media/src/main/java/androidx/media/MediaConstants2.java
index b5af0a9..652776b 100644
--- a/media/src/main/java/androidx/media/MediaConstants2.java
+++ b/media/src/main/java/androidx/media/MediaConstants2.java
@@ -24,8 +24,9 @@
// Event string used by IMediaControllerCallback.onEvent()
static final String SESSION_EVENT_ON_PLAYER_STATE_CHANGED =
"androidx.media.session.event.ON_PLAYER_STATE_CHANGED";
- static final String SESSION_EVENT_ON_ERROR =
- "androidx.media.session.event.ON_ERROR";
+ static final String SESSION_EVENT_ON_ERROR = "androidx.media.session.event.ON_ERROR";
+ static final String SESSION_EVENT_ON_ROUTES_INFO_CHANGED =
+ "androidx.media.session.event.ON_ROUTES_INFO_CHANGED";
static final String SESSION_EVENT_ON_REPEAT_MODE_CHANGED =
"androidx.media.session.event.ON_REPEAT_MODE_CHANGED";
static final String SESSION_EVENT_ON_SHUFFLE_MODE_CHANGED =
@@ -76,6 +77,7 @@
static final String ARGUMENT_ARGUMENTS = "androidx.media.argument.ARGUMENTS";
static final String ARGUMENT_RESULT_RECEIVER = "androidx.media.argument.RESULT_RECEIVER";
static final String ARGUMENT_COMMAND_BUTTONS = "androidx.media.argument.COMMAND_BUTTONS";
+ static final String ARGUMENT_ROUTE_BUNDLE = "androidx.media.argument.ROUTE_BUNDLE";
static final String ARGUMENT_ICONTROLLER_CALLBACK =
"androidx.media.argument.ICONTROLLER_CALLBACK";
diff --git a/media/src/main/java/androidx/media/MediaController2.java b/media/src/main/java/androidx/media/MediaController2.java
index f62616c..9822712 100644
--- a/media/src/main/java/androidx/media/MediaController2.java
+++ b/media/src/main/java/androidx/media/MediaController2.java
@@ -40,6 +40,7 @@
import static androidx.media.MediaConstants2.ARGUMENT_RATING;
import static androidx.media.MediaConstants2.ARGUMENT_REPEAT_MODE;
import static androidx.media.MediaConstants2.ARGUMENT_RESULT_RECEIVER;
+import static androidx.media.MediaConstants2.ARGUMENT_ROUTE_BUNDLE;
import static androidx.media.MediaConstants2.ARGUMENT_SEEK_POSITION;
import static androidx.media.MediaConstants2.ARGUMENT_SHUFFLE_MODE;
import static androidx.media.MediaConstants2.ARGUMENT_UID;
@@ -59,6 +60,7 @@
import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYLIST_CHANGED;
import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYLIST_METADATA_CHANGED;
import static androidx.media.MediaConstants2.SESSION_EVENT_ON_REPEAT_MODE_CHANGED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ROUTES_INFO_CHANGED;
import static androidx.media.MediaConstants2.SESSION_EVENT_ON_SHUFFLE_MODE_CHANGED;
import static androidx.media.MediaConstants2.SESSION_EVENT_SEND_CUSTOM_COMMAND;
import static androidx.media.MediaConstants2.SESSION_EVENT_SET_CUSTOM_LAYOUT;
@@ -87,7 +89,10 @@
import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH;
import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_URI;
import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_REWIND;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_SELECT_ROUTE;
import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_SET_RATING;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_SUBSCRIBE_ROUTES_INFO;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_UNSUBSCRIBE_ROUTES_INFO;
import static androidx.media.SessionCommand2.COMMAND_CODE_VOLUME_ADJUST_VOLUME;
import static androidx.media.SessionCommand2.COMMAND_CODE_VOLUME_SET_VOLUME;
@@ -331,6 +336,17 @@
*/
public void onRepeatModeChanged(@NonNull MediaController2 controller,
@MediaPlaylistAgent.RepeatMode int repeatMode) { }
+
+ /**
+ * Called when a property of the indicated media route has changed.
+ *
+ * @param controller the controller for this event
+ * @param routes The list of Bundle from MediaRouteDescriptor.asBundle().
+ * See MediaRouteDescriptor.fromBundle(Bundle bundle) to get
+ * MediaRouteDescriptor object from the {@code routes}
+ */
+ public void onRoutesInfoChanged(@NonNull MediaController2 controller,
+ @Nullable List<Bundle> routes) { }
}
/**
@@ -526,6 +542,12 @@
mCallback.onError(MediaController2.this, errorCode, errorExtras);
break;
}
+ case SESSION_EVENT_ON_ROUTES_INFO_CHANGED: {
+ List<Bundle> routes = MediaUtils2.toBundleList(
+ extras.getParcelableArray(ARGUMENT_ROUTE_BUNDLE));
+ mCallback.onRoutesInfoChanged(MediaController2.this, routes);
+ break;
+ }
case SESSION_EVENT_ON_PLAYLIST_CHANGED: {
MediaMetadata2 playlistMetadata = MediaMetadata2.fromBundle(
extras.getBundle(ARGUMENT_PLAYLIST_METADATA));
@@ -1436,6 +1458,38 @@
sendCommand(COMMAND_CODE_PLAYLIST_SET_SHUFFLE_MODE, args);
}
+ /**
+ * Queries for information about the routes currently known.
+ */
+ public void subscribeRoutesInfo() {
+ sendCommand(COMMAND_CODE_SESSION_SUBSCRIBE_ROUTES_INFO);
+ }
+
+ /**
+ * Unsubscribes for changes to the routes.
+ * <p>
+ * The {@link ControllerCallback#onRoutesInfoChanged callback} will no longer be invoked for
+ * the routes once this method returns.
+ * </p>
+ */
+ public void unsubscribeRoutesInfo() {
+ sendCommand(COMMAND_CODE_SESSION_UNSUBSCRIBE_ROUTES_INFO);
+ }
+
+ /**
+ * Selects the specified route.
+ *
+ * @param route The route to select.
+ */
+ public void selectRoute(@NonNull Bundle route) {
+ if (route == null) {
+ throw new IllegalArgumentException("route shouldn't be null");
+ }
+ Bundle args = new Bundle();
+ args.putBundle(ARGUMENT_ROUTE_BUNDLE, route);
+ sendCommand(COMMAND_CODE_SESSION_SELECT_ROUTE, args);
+ }
+
// Should be used without a lock to prevent potential deadlock.
void onConnectedNotLocked(Bundle data) {
// TODO: Getting mPlaybackInfo via MediaControllerCompat.Callback.onAudioInfoChanged()
diff --git a/media/src/main/java/androidx/media/MediaSession2.java b/media/src/main/java/androidx/media/MediaSession2.java
index e11af45..0093991 100644
--- a/media/src/main/java/androidx/media/MediaSession2.java
+++ b/media/src/main/java/androidx/media/MediaSession2.java
@@ -431,6 +431,37 @@
public void onRewind(@NonNull MediaSession2 session, ControllerInfo controller) { }
/**
+ * Called when a controller called {@link MediaController2#subscribeRoutesInfo()}
+ * Session app should notify the routes information by calling
+ * {@link MediaSession2#notifyRoutesInfoChanged(ControllerInfo, List<Bundle>)}.
+ *
+ * @param session the session for this event
+ * @param controller controller information
+ * @see SessionCommand2#COMMAND_CODE_SESSION_SUBSCRIBE_ROUTES_INFO
+ */
+ public void onSubscribeRoutesInfo(@NonNull MediaSession2 session,
+ @NonNull ControllerInfo controller) { }
+
+ /**
+ * Called when a controller called {@link MediaController2#unsubscribeRoutesInfo()}
+ *
+ * @param session the session for this event
+ * @param controller controller information
+ * @see SessionCommand2#COMMAND_CODE_SESSION_UNSUBSCRIBE_ROUTES_INFO
+ */
+ public void onUnsubscribeRoutesInfo(@NonNull MediaSession2 session,
+ @NonNull ControllerInfo controller) { }
+
+ /**
+ * Called when a controller called {@link MediaController2#selectRoute(Bundle)}.
+ * @param session the session for this event
+ * @param controller controller information
+ * @param route The route bundle which may be from MediaRouteDescritor.asBundle().
+ * @see SessionCommand2#COMMAND_CODE_SESSION_SELECT_ROUTE
+ */
+ public void onSelectRoute(@NonNull MediaSession2 session,
+ @NonNull ControllerInfo controller, @NonNull Bundle route) { }
+ /**
* Called when the player's current playing item is changed
* <p>
* When it's called, you should invalidate previous playback information and wait for later
@@ -1044,6 +1075,8 @@
abstract void sendCustomCommand(@NonNull ControllerInfo controller,
@NonNull SessionCommand2 command, @Nullable Bundle args,
@Nullable ResultReceiver receiver);
+ abstract void notifyRoutesInfoChanged(@NonNull ControllerInfo controller,
+ @Nullable List<Bundle> routes);
// Internally used methods
abstract void setInstance(MediaSession2 session);
@@ -1293,6 +1326,18 @@
}
/**
+ * Notify routes information to a connected controller
+ *
+ * @param controller controller information
+ * @param routes The routes information. Each bundle should be from
+ * MediaRouteDescritor.asBundle().
+ */
+ public void notifyRoutesInfoChanged(@NonNull ControllerInfo controller,
+ @Nullable List<Bundle> routes) {
+ mImpl.notifyRoutesInfoChanged(controller, routes);
+ }
+
+ /**
* Gets the current player state.
*
* @return the current player state
diff --git a/media/src/main/java/androidx/media/MediaSession2ImplBase.java b/media/src/main/java/androidx/media/MediaSession2ImplBase.java
index b5a3350..eb23de3 100644
--- a/media/src/main/java/androidx/media/MediaSession2ImplBase.java
+++ b/media/src/main/java/androidx/media/MediaSession2ImplBase.java
@@ -240,7 +240,7 @@
if (layout == null) {
throw new IllegalArgumentException("layout shouldn't be null");
}
- mSession2Stub.notifyCustomLayoutNotLocked(controller, layout);
+ mSession2Stub.notifyCustomLayout(controller, layout);
}
@Override
@@ -357,6 +357,12 @@
}
@Override
+ public void notifyRoutesInfoChanged(@NonNull ControllerInfo controller,
+ @Nullable List<Bundle> routes) {
+ mSession2Stub.notifyRoutesInfoChanged(controller, routes);
+ }
+
+ @Override
public @MediaPlayerBase.PlayerState int getPlayerState() {
MediaPlayerBase player;
synchronized (mLock) {
@@ -721,7 +727,7 @@
@Override
PlaybackStateCompat getPlaybackStateCompat() {
synchronized (mLock) {
- int state = MediaUtils2.toPlaybackStateCompatState(getPlayerState(),
+ int state = MediaUtils2.createPlaybackStateCompatState(getPlayerState(),
getBufferingState());
// TODO: Consider following missing stuff
// - setCustomAction(): Fill custom layout
diff --git a/media/src/main/java/androidx/media/MediaSession2StubImplBase.java b/media/src/main/java/androidx/media/MediaSession2StubImplBase.java
index 6e0d375..b203255 100644
--- a/media/src/main/java/androidx/media/MediaSession2StubImplBase.java
+++ b/media/src/main/java/androidx/media/MediaSession2StubImplBase.java
@@ -37,6 +37,7 @@
import static androidx.media.MediaConstants2.ARGUMENT_RATING;
import static androidx.media.MediaConstants2.ARGUMENT_REPEAT_MODE;
import static androidx.media.MediaConstants2.ARGUMENT_RESULT_RECEIVER;
+import static androidx.media.MediaConstants2.ARGUMENT_ROUTE_BUNDLE;
import static androidx.media.MediaConstants2.ARGUMENT_SEEK_POSITION;
import static androidx.media.MediaConstants2.ARGUMENT_SHUFFLE_MODE;
import static androidx.media.MediaConstants2.ARGUMENT_UID;
@@ -56,6 +57,7 @@
import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYLIST_CHANGED;
import static androidx.media.MediaConstants2.SESSION_EVENT_ON_PLAYLIST_METADATA_CHANGED;
import static androidx.media.MediaConstants2.SESSION_EVENT_ON_REPEAT_MODE_CHANGED;
+import static androidx.media.MediaConstants2.SESSION_EVENT_ON_ROUTES_INFO_CHANGED;
import static androidx.media.MediaConstants2.SESSION_EVENT_ON_SHUFFLE_MODE_CHANGED;
import static androidx.media.MediaConstants2.SESSION_EVENT_SEND_CUSTOM_COMMAND;
import static androidx.media.MediaConstants2.SESSION_EVENT_SET_CUSTOM_LAYOUT;
@@ -82,7 +84,10 @@
import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH;
import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_URI;
import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_REWIND;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_SELECT_ROUTE;
import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_SET_RATING;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_SUBSCRIBE_ROUTES_INFO;
+import static androidx.media.SessionCommand2.COMMAND_CODE_SESSION_UNSUBSCRIBE_ROUTES_INFO;
import static androidx.media.SessionCommand2.COMMAND_CODE_VOLUME_ADJUST_VOLUME;
import static androidx.media.SessionCommand2.COMMAND_CODE_VOLUME_SET_VOLUME;
@@ -103,6 +108,7 @@
import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.media.MediaSession2.CommandButton;
import androidx.media.MediaSession2.ControllerInfo;
@@ -119,6 +125,7 @@
private static final SparseArray<SessionCommand2> sCommandsForOnCommandRequest =
new SparseArray<>();
+
static {
SessionCommandGroup2 group = new SessionCommandGroup2();
group.addAllPlaybackCommands();
@@ -391,6 +398,21 @@
mSession.getInstance(), controller, mediaId, rating);
break;
}
+ case COMMAND_CODE_SESSION_SUBSCRIBE_ROUTES_INFO: {
+ mSession.getCallback().onSubscribeRoutesInfo(
+ mSession.getInstance(), controller);
+ break;
+ }
+ case COMMAND_CODE_SESSION_UNSUBSCRIBE_ROUTES_INFO: {
+ mSession.getCallback().onUnsubscribeRoutesInfo(
+ mSession.getInstance(), controller);
+ break;
+ }
+ case COMMAND_CODE_SESSION_SELECT_ROUTE: {
+ Bundle route = extras.getBundle(ARGUMENT_ROUTE_BUNDLE);
+ mSession.getCallback().onSelectRoute(
+ mSession.getInstance(), controller, route);
+ }
}
}
});
@@ -428,7 +450,7 @@
return controllers;
}
- void notifyCustomLayoutNotLocked(ControllerInfo controller, final List<CommandButton> layout) {
+ void notifyCustomLayout(ControllerInfo controller, final List<CommandButton> layout) {
notifyInternal(controller, new Session2Runnable() {
@Override
public void run(ControllerInfo controller) throws RemoteException {
@@ -516,6 +538,22 @@
});
}
+ void notifyRoutesInfoChanged(@NonNull final ControllerInfo controller,
+ @Nullable final List<Bundle> routes) {
+ notifyInternal(controller, new Session2Runnable() {
+ @Override
+ public void run(ControllerInfo controller) throws RemoteException {
+ Bundle bundle = null;
+ if (routes != null) {
+ bundle = new Bundle();
+ bundle.putParcelableArray(ARGUMENT_ROUTE_BUNDLE, routes.toArray(new Bundle[0]));
+ }
+ controller.getControllerBinder().onEvent(
+ SESSION_EVENT_ON_ROUTES_INFO_CHANGED, bundle);
+ }
+ });
+ }
+
void notifyPlaylistChanged(final List<MediaItem2> playlist,
final MediaMetadata2 metadata) {
notifyAll(SessionCommand2.COMMAND_CODE_PLAYLIST_GET_LIST, new Session2Runnable() {
diff --git a/media/src/main/java/androidx/media/MediaUtils2.java b/media/src/main/java/androidx/media/MediaUtils2.java
index b784599..1707f9c 100644
--- a/media/src/main/java/androidx/media/MediaUtils2.java
+++ b/media/src/main/java/androidx/media/MediaUtils2.java
@@ -371,7 +371,18 @@
.build();
}
- static int toPlaybackStateCompatState(int playerState, int bufferingState) {
+ static List<Bundle> toBundleList(Parcelable[] array) {
+ if (array == null) {
+ return null;
+ }
+ List<Bundle> bundleList = new ArrayList<>();
+ for (Parcelable p : array) {
+ bundleList.add((Bundle) p);
+ }
+ return bundleList;
+ }
+
+ static int createPlaybackStateCompatState(int playerState, int bufferingState) {
switch (playerState) {
case MediaPlayerBase.PLAYER_STATE_PLAYING:
switch (bufferingState) {
diff --git a/media/src/main/java/androidx/media/SessionCommand2.java b/media/src/main/java/androidx/media/SessionCommand2.java
index 32a9154..a07799b 100644
--- a/media/src/main/java/androidx/media/SessionCommand2.java
+++ b/media/src/main/java/androidx/media/SessionCommand2.java
@@ -265,6 +265,22 @@
public static final int COMMAND_CODE_SESSION_SET_RATING = 28;
/**
+ * Command code for {@link MediaController2#subscribeRoutesInfo()}
+ */
+ public static final int COMMAND_CODE_SESSION_SUBSCRIBE_ROUTES_INFO = 36;
+
+ /**
+ * Command code for {@link MediaController2#unsubscribeRoutesInfo()}
+ */
+ public static final int COMMAND_CODE_SESSION_UNSUBSCRIBE_ROUTES_INFO = 37;
+
+ /**
+ * Command code for {@link MediaController2#selectRoute(Bundle)}}
+ */
+ public static final int COMMAND_CODE_SESSION_SELECT_ROUTE = 38;
+
+
+ /**
* Command code for {@link MediaBrowser2#getChildren(String, int, int, Bundle)}.
*/
public static final int COMMAND_CODE_LIBRARY_GET_CHILDREN = 29;