summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt13
-rw-r--r--media/java/android/media/IMediaRoute2Provider.aidl3
-rw-r--r--media/java/android/media/IMediaRouterService.aidl7
-rw-r--r--media/java/android/media/MediaRoute2ProviderService.java28
-rw-r--r--media/java/android/media/MediaRouter2.java77
-rw-r--r--media/java/android/media/MediaRouter2Manager.java100
-rw-r--r--media/java/android/media/RoutingSessionInfo.java94
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java118
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java23
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2Provider.java3
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java40
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java84
-rw-r--r--services/core/java/com/android/server/media/MediaRouterService.java22
-rw-r--r--services/core/java/com/android/server/media/SystemMediaRoute2Provider.java25
14 files changed, 560 insertions, 77 deletions
diff --git a/api/current.txt b/api/current.txt
index 475506a317bc..26f6951672ac 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -26816,7 +26816,8 @@ package android.media {
method public void onDiscoveryPreferenceChanged(@NonNull android.media.RouteDiscoveryPreference);
method public abstract void onReleaseSession(@NonNull String);
method public abstract void onSelectRoute(@NonNull String, @NonNull String);
- method public abstract void onSetVolume(@NonNull String, int);
+ method public abstract void onSetRouteVolume(@NonNull String, int);
+ method public abstract void onSetSessionVolume(@NonNull String, int);
method public abstract void onTransferToRoute(@NonNull String, @NonNull String);
field public static final long REQUEST_ID_UNKNOWN = 0L; // 0x0L
field public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService";
@@ -26977,9 +26978,13 @@ package android.media {
method @NonNull public java.util.List<android.media.MediaRoute2Info> getSelectableRoutes();
method @NonNull public java.util.List<android.media.MediaRoute2Info> getSelectedRoutes();
method @NonNull public java.util.List<android.media.MediaRoute2Info> getTransferrableRoutes();
+ method public int getVolume();
+ method public int getVolumeHandling();
+ method public int getVolumeMax();
method public boolean isReleased();
method public void release();
method public void selectRoute(@NonNull android.media.MediaRoute2Info);
+ method public void setVolume(int);
method public void transferToRoute(@NonNull android.media.MediaRoute2Info);
}
@@ -27374,6 +27379,9 @@ package android.media {
method @NonNull public java.util.List<java.lang.String> getSelectableRoutes();
method @NonNull public java.util.List<java.lang.String> getSelectedRoutes();
method @NonNull public java.util.List<java.lang.String> getTransferrableRoutes();
+ method public int getVolume();
+ method public int getVolumeHandling();
+ method public int getVolumeMax();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.media.RoutingSessionInfo> CREATOR;
}
@@ -27395,6 +27403,9 @@ package android.media {
method @NonNull public android.media.RoutingSessionInfo.Builder removeSelectedRoute(@NonNull String);
method @NonNull public android.media.RoutingSessionInfo.Builder removeTransferrableRoute(@NonNull String);
method @NonNull public android.media.RoutingSessionInfo.Builder setControlHints(@Nullable android.os.Bundle);
+ method @NonNull public android.media.RoutingSessionInfo.Builder setVolume(int);
+ method @NonNull public android.media.RoutingSessionInfo.Builder setVolumeHandling(int);
+ method @NonNull public android.media.RoutingSessionInfo.Builder setVolumeMax(int);
}
public final class Session2Command implements android.os.Parcelable {
diff --git a/media/java/android/media/IMediaRoute2Provider.aidl b/media/java/android/media/IMediaRoute2Provider.aidl
index 9131f3bc960d..0c645641ee37 100644
--- a/media/java/android/media/IMediaRoute2Provider.aidl
+++ b/media/java/android/media/IMediaRoute2Provider.aidl
@@ -36,5 +36,6 @@ oneway interface IMediaRoute2Provider {
void transferToRoute(String sessionId, String routeId);
void notifyControlRequestSent(String id, in Intent request);
- void requestSetVolume(String id, int volume);
+ void setRouteVolume(String routeId, int volume);
+ void setSessionVolume(String sessionId, int volume);
}
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 6fef46889742..f919dce17b2f 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -51,7 +51,8 @@ interface IMediaRouterService {
void unregisterClient2(IMediaRouter2Client client);
void sendControlRequest(IMediaRouter2Client client, in MediaRoute2Info route,
in Intent request);
- void requestSetVolume2(IMediaRouter2Client client, in MediaRoute2Info route, int volume);
+ void setRouteVolume2(IMediaRouter2Client client, in MediaRoute2Info route, int volume);
+ void setSessionVolume2(IMediaRouter2Client client, String sessionId, int volume);
void requestCreateSession(IMediaRouter2Client client, in MediaRoute2Info route, int requestId,
in @nullable Bundle sessionHints);
@@ -67,8 +68,10 @@ interface IMediaRouterService {
void requestCreateClientSession(IMediaRouter2Manager manager, String packageName,
in @nullable MediaRoute2Info route, int requestId);
- void requestSetVolume2Manager(IMediaRouter2Manager manager,
+ void setRouteVolume2Manager(IMediaRouter2Manager manager,
in MediaRoute2Info route, int volume);
+ void setSessionVolume2Manager(IMediaRouter2Manager manager,
+ String sessionId, int volume);
List<RoutingSessionInfo> getActiveSessions(IMediaRouter2Manager manager);
void selectClientRoute(IMediaRouter2Manager manager,
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 20a59bba54c6..aac195dc76d5 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -122,16 +122,25 @@ public abstract class MediaRoute2ProviderService extends Service {
* @hide
*/
//TODO: Discuss what to use for request (e.g., Intent? Request class?)
- public abstract void onControlRequest(@NonNull String routeId, @NonNull Intent request);
+ public void onControlRequest(@NonNull String routeId, @NonNull Intent request) {}
/**
- * Called when requestSetVolume is called on a route of the provider.
+ * Called when a volume setting is requested on a route of the provider
*
* @param routeId the id of the route
* @param volume the target volume
* @see MediaRoute2Info#getVolumeMax()
*/
- public abstract void onSetVolume(@NonNull String routeId, int volume);
+ public abstract void onSetRouteVolume(@NonNull String routeId, int volume);
+
+ /**
+ * Called when {@link MediaRouter2.RoutingController#setVolume(int)} is called on
+ * a routing session of the provider
+ *
+ * @param sessionId the id of the routing session
+ * @param volume the target volume
+ */
+ public abstract void onSetSessionVolume(@NonNull String sessionId, int volume);
/**
* Gets information of the session with the given id.
@@ -513,12 +522,21 @@ public abstract class MediaRoute2ProviderService extends Service {
}
@Override
- public void requestSetVolume(String routeId, int volume) {
+ public void setRouteVolume(String routeId, int volume) {
if (!checkCallerisSystem()) {
return;
}
- mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetVolume,
+ mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetRouteVolume,
MediaRoute2ProviderService.this, routeId, volume));
}
+
+ @Override
+ public void setSessionVolume(String sessionId, int volume) {
+ if (!checkCallerisSystem()) {
+ return;
+ }
+ mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetSessionVolume,
+ MediaRoute2ProviderService.this, sessionId, volume));
+ }
}
}
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 64186106d2c8..0e6ade539e35 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -446,7 +446,7 @@ public class MediaRouter2 {
* @param volume The new volume value between 0 and {@link MediaRoute2Info#getVolumeMax}.
* @hide
*/
- public void requestSetVolume(@NonNull MediaRoute2Info route, int volume) {
+ public void setRouteVolume(@NonNull MediaRoute2Info route, int volume) {
Objects.requireNonNull(route, "route must not be null");
Client2 client;
@@ -455,7 +455,7 @@ public class MediaRouter2 {
}
if (client != null) {
try {
- mMediaRouterService.requestSetVolume2(client, route, volume);
+ mMediaRouterService.setRouteVolume2(client, route, volume);
} catch (RemoteException ex) {
Log.e(TAG, "Unable to send control request.", ex);
}
@@ -885,6 +885,43 @@ public class MediaRouter2 {
}
/**
+ * Gets information about how volume is handled on the session.
+ *
+ * @return {@link MediaRoute2Info#PLAYBACK_VOLUME_FIXED} or
+ * {@link MediaRoute2Info#PLAYBACK_VOLUME_VARIABLE}
+ */
+ @MediaRoute2Info.PlaybackVolume
+ public int getVolumeHandling() {
+ synchronized (mControllerLock) {
+ return mSessionInfo.getVolumeHandling();
+ }
+ }
+
+ /**
+ * Gets the maximum volume of the session.
+ */
+ public int getVolumeMax() {
+ synchronized (mControllerLock) {
+ return mSessionInfo.getVolumeMax();
+ }
+ }
+
+ /**
+ * Gets the current volume of the session.
+ * <p>
+ * When it's available, it represents the volume of routing session, which is a group
+ * of selected routes. To get the volume of a route,
+ * use {@link MediaRoute2Info#getVolume()}.
+ * </p>
+ * @see MediaRoute2Info#getVolume()
+ */
+ public int getVolume() {
+ synchronized (mControllerLock) {
+ return mSessionInfo.getVolume();
+ }
+ }
+
+ /**
* Returns true if this controller is released, false otherwise.
* If it is released, then all other getters from this instance may return invalid values.
* Also, any operations to this instance will be ignored once released.
@@ -1040,6 +1077,42 @@ public class MediaRouter2 {
}
/**
+ * Requests a volume change for the remote session asynchronously.
+ *
+ * @param volume The new volume value between 0 and {@link RoutingController#getVolumeMax}
+ * (inclusive).
+ * @see #getVolume()
+ */
+ public void setVolume(int volume) {
+ if (getVolumeHandling() == MediaRoute2Info.PLAYBACK_VOLUME_FIXED) {
+ Log.w(TAG, "setVolume: the routing session has fixed volume. Ignoring.");
+ return;
+ }
+ if (volume < 0 || volume > getVolumeMax()) {
+ Log.w(TAG, "setVolume: the target volume is out of range. Ignoring");
+ return;
+ }
+
+ synchronized (mControllerLock) {
+ if (mIsReleased) {
+ Log.w(TAG, "setVolume is called on released controller. Ignoring.");
+ return;
+ }
+ }
+ Client2 client;
+ synchronized (sRouterLock) {
+ client = mClient;
+ }
+ if (client != null) {
+ try {
+ mMediaRouterService.setSessionVolume2(client, getId(), volume);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "setVolume: Failed to deliver request.", ex);
+ }
+ }
+ }
+
+ /**
* Release this controller and corresponding session.
* Any operations on this controller after calling this method will be ignored.
* The devices that are playing media will stop playing it.
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 2c1fdab9da01..5ce291c06ade 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -22,6 +22,8 @@ import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.media.session.MediaController;
+import android.media.session.MediaSessionManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
@@ -53,6 +55,8 @@ public class MediaRouter2Manager {
@GuardedBy("sLock")
private static MediaRouter2Manager sInstance;
+ private final MediaSessionManager mMediaSessionManager;
+
final String mPackageName;
private Context mContext;
@@ -89,6 +93,8 @@ public class MediaRouter2Manager {
mContext = context.getApplicationContext();
mMediaRouterService = IMediaRouterService.Stub.asInterface(
ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE));
+ mMediaSessionManager = (MediaSessionManager) context
+ .getSystemService(Context.MEDIA_SESSION_SERVICE);
mPackageName = mContext.getPackageName();
mHandler = new Handler(context.getMainLooper());
}
@@ -150,6 +156,23 @@ public class MediaRouter2Manager {
}
}
+ /**
+ * Gets a {@link android.media.session.MediaController} associated with the
+ * given routing session.
+ * If there is no matching media session, {@code null} is returned.
+ */
+ @Nullable
+ public MediaController getMediaControllerForRoutingSession(
+ @NonNull RoutingSessionInfo sessionInfo) {
+ for (MediaController controller : mMediaSessionManager.getActiveSessions(null)) {
+ String volumeControlId = controller.getPlaybackInfo().getVolumeControlId();
+ if (TextUtils.equals(sessionInfo.getId(), volumeControlId)) {
+ return controller;
+ }
+ }
+ return null;
+ }
+
//TODO: Use cache not to create array. For now, it's unclear when to purge the cache.
//Do this when we finalize how to set control categories.
/**
@@ -178,24 +201,24 @@ public class MediaRouter2Manager {
}
/**
- * Gets routing controllers of an application with the given package name.
+ * Gets routing sessions of an application with the given package name.
* The first element of the returned list is the system routing controller.
*
* @see MediaRouter2#getSystemController()
*/
@NonNull
- public List<RoutingController> getRoutingControllers(@NonNull String packageName) {
+ public List<RoutingSessionInfo> getRoutingSessions(@NonNull String packageName) {
Objects.requireNonNull(packageName, "packageName must not be null");
- List<RoutingController> controllers = new ArrayList<>();
+ List<RoutingSessionInfo> sessions = new ArrayList<>();
for (RoutingSessionInfo sessionInfo : getActiveSessions()) {
if (sessionInfo.isSystemSession()
|| TextUtils.equals(sessionInfo.getClientPackageName(), packageName)) {
- controllers.add(new RoutingController(sessionInfo));
+ sessions.add(sessionInfo);
}
}
- return controllers;
+ return sessions;
}
/**
@@ -250,13 +273,12 @@ public class MediaRouter2Manager {
boolean transferred = false;
//TODO: instead of release all controllers, add an API to specify controllers that
// should be released (or is the system controller).
- for (RoutingController controller : getRoutingControllers(packageName)) {
- if (!transferred && controller.getSessionInfo().getTransferrableRoutes()
- .contains(route.getId())) {
- controller.transferToRoute(route);
+ for (RoutingSessionInfo sessionInfo : getRoutingSessions(packageName)) {
+ if (!transferred && sessionInfo.getTransferrableRoutes().contains(route.getId())) {
+ new RoutingController(sessionInfo).transferToRoute(route);
transferred = true;
- } else if (!controller.getSessionInfo().isSystemSession()) {
- controller.release();
+ } else if (!sessionInfo.isSystemSession()) {
+ new RoutingController(sessionInfo).release();
}
}
@@ -282,22 +304,72 @@ public class MediaRouter2Manager {
/**
* Requests a volume change for a route asynchronously.
+ */
+ //TODO: remove this.
+ public void requestSetVolume(MediaRoute2Info route, int volume) {
+ setRouteVolume(route, volume);
+ }
+
+ /**
+ * Requests a volume change for a route asynchronously.
* <p>
* It may have no effect if the route is currently not selected.
* </p>
*
- * @param volume The new volume value between 0 and {@link MediaRoute2Info#getVolumeMax}.
+ * @param volume The new volume value between 0 and {@link MediaRoute2Info#getVolumeMax}
+ * (inclusive).
*/
- public void requestSetVolume(@NonNull MediaRoute2Info route, int volume) {
+ public void setRouteVolume(@NonNull MediaRoute2Info route, int volume) {
Objects.requireNonNull(route, "route must not be null");
+ if (route.getVolumeHandling() == MediaRoute2Info.PLAYBACK_VOLUME_FIXED) {
+ Log.w(TAG, "setRouteVolume: the route has fixed volume. Ignoring.");
+ return;
+ }
+ if (volume < 0 || volume > route.getVolumeMax()) {
+ Log.w(TAG, "setRouteVolume: the target volume is out of range. Ignoring");
+ return;
+ }
+
+ Client client;
+ synchronized (sLock) {
+ client = mClient;
+ }
+ if (client != null) {
+ try {
+ mMediaRouterService.setRouteVolume2Manager(client, route, volume);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to send control request.", ex);
+ }
+ }
+ }
+
+ /**
+ * Requests a volume change for a routing session asynchronously.
+ *
+ * @param volume The new volume value between 0 and {@link RoutingSessionInfo#getVolumeMax}
+ * (inclusive).
+ */
+ public void setSessionVolume(@NonNull RoutingSessionInfo sessionInfo, int volume) {
+ Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+
+ if (sessionInfo.getVolumeHandling() == MediaRoute2Info.PLAYBACK_VOLUME_FIXED) {
+ Log.w(TAG, "setSessionVolume: the route has fixed volume. Ignoring.");
+ return;
+ }
+ if (volume < 0 || volume > sessionInfo.getVolumeMax()) {
+ Log.w(TAG, "setSessionVolume: the target volume is out of range. Ignoring");
+ return;
+ }
+
Client client;
synchronized (sLock) {
client = mClient;
}
if (client != null) {
try {
- mMediaRouterService.requestSetVolume2Manager(client, route, volume);
+ mMediaRouterService.setSessionVolume2Manager(
+ client, sessionInfo.getId(), volume);
} catch (RemoteException ex) {
Log.e(TAG, "Unable to send control request.", ex);
}
diff --git a/media/java/android/media/RoutingSessionInfo.java b/media/java/android/media/RoutingSessionInfo.java
index 5383ea219c57..0d4e666de51b 100644
--- a/media/java/android/media/RoutingSessionInfo.java
+++ b/media/java/android/media/RoutingSessionInfo.java
@@ -56,6 +56,11 @@ public final class RoutingSessionInfo implements Parcelable {
final List<String> mSelectableRoutes;
final List<String> mDeselectableRoutes;
final List<String> mTransferrableRoutes;
+
+ final int mVolumeHandling;
+ final int mVolumeMax;
+ final int mVolume;
+
@Nullable
final Bundle mControlHints;
final boolean mIsSystemSession;
@@ -77,6 +82,10 @@ public final class RoutingSessionInfo implements Parcelable {
mTransferrableRoutes = Collections.unmodifiableList(
convertToUniqueRouteIds(builder.mTransferrableRoutes));
+ mVolumeHandling = builder.mVolumeHandling;
+ mVolumeMax = builder.mVolumeMax;
+ mVolume = builder.mVolume;
+
mControlHints = builder.mControlHints;
mIsSystemSession = builder.mIsSystemSession;
}
@@ -93,6 +102,10 @@ public final class RoutingSessionInfo implements Parcelable {
mDeselectableRoutes = ensureList(src.createStringArrayList());
mTransferrableRoutes = ensureList(src.createStringArrayList());
+ mVolumeHandling = src.readInt();
+ mVolumeMax = src.readInt();
+ mVolume = src.readInt();
+
mControlHints = src.readBundle();
mIsSystemSession = src.readBoolean();
}
@@ -188,6 +201,36 @@ public final class RoutingSessionInfo implements Parcelable {
}
/**
+ * Gets information about how volume is handled on the session.
+ *
+ * @return {@link MediaRoute2Info#PLAYBACK_VOLUME_FIXED} or
+ * {@link MediaRoute2Info#PLAYBACK_VOLUME_VARIABLE}.
+ */
+ @MediaRoute2Info.PlaybackVolume
+ public int getVolumeHandling() {
+ return mVolumeHandling;
+ }
+
+ /**
+ * Gets the maximum volume of the session.
+ */
+ public int getVolumeMax() {
+ return mVolumeMax;
+ }
+
+ /**
+ * Gets the current volume of the session.
+ * <p>
+ * When it's available, it represents the volume of routing session, which is a group
+ * of selected routes. To get the volume of each route, use {@link MediaRoute2Info#getVolume()}.
+ * </p>
+ * @see MediaRoute2Info#getVolume()
+ */
+ public int getVolume() {
+ return mVolume;
+ }
+
+ /**
* Gets the control hints
*/
@Nullable
@@ -218,6 +261,9 @@ public final class RoutingSessionInfo implements Parcelable {
dest.writeStringList(mSelectableRoutes);
dest.writeStringList(mDeselectableRoutes);
dest.writeStringList(mTransferrableRoutes);
+ dest.writeInt(mVolumeHandling);
+ dest.writeInt(mVolumeMax);
+ dest.writeInt(mVolume);
dest.writeBundle(mControlHints);
dest.writeBoolean(mIsSystemSession);
}
@@ -238,13 +284,17 @@ public final class RoutingSessionInfo implements Parcelable {
&& Objects.equals(mSelectedRoutes, other.mSelectedRoutes)
&& Objects.equals(mSelectableRoutes, other.mSelectableRoutes)
&& Objects.equals(mDeselectableRoutes, other.mDeselectableRoutes)
- && Objects.equals(mTransferrableRoutes, other.mTransferrableRoutes);
+ && Objects.equals(mTransferrableRoutes, other.mTransferrableRoutes)
+ && (mVolumeHandling == other.mVolumeHandling)
+ && (mVolumeMax == other.mVolumeMax)
+ && (mVolume == other.mVolume);
}
@Override
public int hashCode() {
return Objects.hash(mId, mClientPackageName, mProviderId,
- mSelectedRoutes, mSelectableRoutes, mDeselectableRoutes, mTransferrableRoutes);
+ mSelectedRoutes, mSelectableRoutes, mDeselectableRoutes, mTransferrableRoutes,
+ mVolumeMax, mVolumeHandling, mVolume);
}
@Override
@@ -264,6 +314,9 @@ public final class RoutingSessionInfo implements Parcelable {
.append(", transferrableRoutes={")
.append(String.join(",", mTransferrableRoutes))
.append("}")
+ .append(", volumeHandling=").append(getVolumeHandling())
+ .append(", volumeMax=").append(getVolumeMax())
+ .append(", volume=").append(getVolume())
.append(" }");
return result.toString();
}
@@ -298,6 +351,9 @@ public final class RoutingSessionInfo implements Parcelable {
final List<String> mSelectableRoutes;
final List<String> mDeselectableRoutes;
final List<String> mTransferrableRoutes;
+ int mVolumeHandling = MediaRoute2Info.PLAYBACK_VOLUME_FIXED;
+ int mVolumeMax;
+ int mVolume;
Bundle mControlHints;
boolean mIsSystemSession;
@@ -346,6 +402,10 @@ public final class RoutingSessionInfo implements Parcelable {
mDeselectableRoutes = new ArrayList<>(sessionInfo.mDeselectableRoutes);
mTransferrableRoutes = new ArrayList<>(sessionInfo.mTransferrableRoutes);
+ mVolumeHandling = sessionInfo.mVolumeHandling;
+ mVolumeMax = sessionInfo.mVolumeMax;
+ mVolume = sessionInfo.mVolume;
+
mControlHints = sessionInfo.mControlHints;
mIsSystemSession = sessionInfo.mIsSystemSession;
}
@@ -497,6 +557,36 @@ public final class RoutingSessionInfo implements Parcelable {
}
/**
+ * Sets the session's volume handling.
+ * {@link MediaRoute2Info#PLAYBACK_VOLUME_FIXED} or
+ * {@link MediaRoute2Info#PLAYBACK_VOLUME_VARIABLE}.
+ */
+ @NonNull
+ public RoutingSessionInfo.Builder setVolumeHandling(
+ @MediaRoute2Info.PlaybackVolume int volumeHandling) {
+ mVolumeHandling = volumeHandling;
+ return this;
+ }
+
+ /**
+ * Sets the session's maximum volume, or 0 if unknown.
+ */
+ @NonNull
+ public RoutingSessionInfo.Builder setVolumeMax(int volumeMax) {
+ mVolumeMax = volumeMax;
+ return this;
+ }
+
+ /**
+ * Sets the session's current volume, or 0 if unknown.
+ */
+ @NonNull
+ public RoutingSessionInfo.Builder setVolume(int volume) {
+ mVolume = volume;
+ return this;
+ }
+
+ /**
* Sets control hints.
*/
@NonNull
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index f10e5ebb5d3e..3ffb9514a98b 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -44,6 +44,7 @@ import android.media.MediaRouter2;
import android.media.MediaRouter2.RouteCallback;
import android.media.MediaRouter2.RoutingControllerCallback;
import android.media.MediaRouter2Manager;
+import android.media.MediaRouter2Utils;
import android.media.RouteDiscoveryPreference;
import android.media.RoutingSessionInfo;
import android.support.test.InstrumentationRegistry;
@@ -57,6 +58,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -225,22 +227,22 @@ public class MediaRouterManagerTest {
}
});
- assertEquals(1, mManager.getRoutingControllers(mPackageName).size());
+ assertEquals(1, mManager.getRoutingSessions(mPackageName).size());
mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1));
latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
- List<MediaRouter2Manager.RoutingController> controllers =
- mManager.getRoutingControllers(mPackageName);
+ List<RoutingSessionInfo> sessions = mManager.getRoutingSessions(mPackageName);
- assertEquals(2, controllers.size());
+ assertEquals(2, sessions.size());
- MediaRouter2Manager.RoutingController routingController = controllers.get(1);
+ MediaRouter2Manager.RoutingController routingController =
+ mManager.getControllerForSession(sessions.get(1));
awaitOnRouteChangedManager(
() -> routingController.release(),
ROUTE_ID1,
route -> TextUtils.equals(route.getClientPackageName(), null));
- assertEquals(1, mManager.getRoutingControllers(mPackageName).size());
+ assertEquals(1, mManager.getRoutingSessions(mPackageName).size());
}
/**
@@ -266,11 +268,11 @@ public class MediaRouterManagerTest {
route -> TextUtils.equals(route.getClientPackageName(), mPackageName));
assertTrue(onSessionCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- List<MediaRouter2Manager.RoutingController> controllers =
- mManager.getRoutingControllers(mPackageName);
+ List<RoutingSessionInfo> sessions = mManager.getRoutingSessions(mPackageName);
- assertEquals(2, controllers.size());
- MediaRouter2Manager.RoutingController routingController = controllers.get(1);
+ assertEquals(2, sessions.size());
+ MediaRouter2Manager.RoutingController routingController =
+ mManager.getControllerForSession(sessions.get(1));
awaitOnRouteChangedManager(
() -> mManager.selectRoute(mPackageName, routes.get(ROUTE_ID5_TO_TRANSFER_TO)),
@@ -284,7 +286,33 @@ public class MediaRouterManagerTest {
}
@Test
- public void testControlVolumeWithManager() throws Exception {
+ public void testSetSystemRouteVolume() throws Exception {
+ // ensure client
+ addManagerCallback(new MediaRouter2Manager.Callback());
+ String selectedSystemRouteId =
+ MediaRouter2Utils.getOriginalId(
+ mManager.getActiveSessions().get(0).getSelectedRoutes().get(0));
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(Collections.emptyList());
+ MediaRoute2Info volRoute = routes.get(selectedSystemRouteId);
+ assertNotNull(volRoute);
+
+ int originalVolume = volRoute.getVolume();
+ int targetVolume = originalVolume == volRoute.getVolumeMax()
+ ? originalVolume - 1 : originalVolume + 1;
+
+ awaitOnRouteChangedManager(
+ () -> mManager.setRouteVolume(volRoute, targetVolume),
+ selectedSystemRouteId,
+ (route -> route.getVolume() == targetVolume));
+
+ awaitOnRouteChangedManager(
+ () -> mManager.setRouteVolume(volRoute, originalVolume),
+ selectedSystemRouteId,
+ (route -> route.getVolume() == originalVolume));
+ }
+
+ @Test
+ public void testSetRouteVolume() throws Exception {
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
@@ -293,17 +321,81 @@ public class MediaRouterManagerTest {
? originalVolume - 1 : originalVolume + 1;
awaitOnRouteChangedManager(
- () -> mManager.requestSetVolume(volRoute, targetVolume),
+ () -> mManager.setRouteVolume(volRoute, targetVolume),
ROUTE_ID_VARIABLE_VOLUME,
(route -> route.getVolume() == targetVolume));
awaitOnRouteChangedManager(
- () -> mManager.requestSetVolume(volRoute, originalVolume),
+ () -> mManager.setRouteVolume(volRoute, originalVolume),
ROUTE_ID_VARIABLE_VOLUME,
(route -> route.getVolume() == originalVolume));
}
@Test
+ public void testSetSessionVolume() throws Exception {
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
+ addRouterCallback(new RouteCallback());
+
+ CountDownLatch onSessionCreatedLatch = new CountDownLatch(1);
+ CountDownLatch volumeChangedLatch = new CountDownLatch(2);
+
+ // create a controller
+ addManagerCallback(new MediaRouter2Manager.Callback() {
+ @Override
+ public void onSessionCreated(MediaRouter2Manager.RoutingController controller) {
+ assertNotNull(controller);
+ onSessionCreatedLatch.countDown();
+ }
+ });
+
+ mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1));
+ assertTrue(onSessionCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ List<RoutingSessionInfo> sessions = mManager.getRoutingSessions(mPackageName);
+ assertEquals(2, sessions.size());
+
+ // test setSessionVolume
+ RoutingSessionInfo sessionInfo = sessions.get(1);
+ int currentVolume = sessionInfo.getVolume();
+ int targetVolume = (currentVolume == 0) ? 1 : (currentVolume - 1);
+
+ RoutingControllerCallback routingControllerCallback = new RoutingControllerCallback() {
+ @Override
+ public void onControllerUpdated(MediaRouter2.RoutingController controller) {
+ if (!TextUtils.equals(sessionInfo.getId(), controller.getId())) {
+ return;
+ }
+ if (controller.getVolume() == targetVolume) {
+ volumeChangedLatch.countDown();
+ }
+ }
+ };
+ mRouter2.registerControllerCallback(mExecutor, routingControllerCallback);
+
+ addManagerCallback(new MediaRouter2Manager.Callback() {
+ @Override
+ public void onSessionsUpdated() {
+ List<RoutingSessionInfo> sessions = mManager.getRoutingSessions(mPackageName);
+ if (sessions.size() != 2) {
+ return;
+ }
+
+ if (sessions.get(1).getVolume() == targetVolume) {
+ volumeChangedLatch.countDown();
+ }
+ }
+ });
+
+ mManager.setSessionVolume(sessionInfo, targetVolume);
+
+ try {
+ assertTrue(volumeChangedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } finally {
+ mRouter2.unregisterControllerCallback(routingControllerCallback);
+ }
+ }
+
+ @Test
public void testVolumeHandling() throws Exception {
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java
index 1a866cafff90..267927ff4a6e 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java
@@ -18,6 +18,7 @@ package com.android.mediaroutertest;
import static android.media.MediaRoute2Info.DEVICE_TYPE_REMOTE_SPEAKER;
import static android.media.MediaRoute2Info.DEVICE_TYPE_REMOTE_TV;
+import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
import android.annotation.Nullable;
import android.content.Intent;
@@ -51,6 +52,8 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
public static final String ROUTE_NAME_SPECIAL_FEATURE = "Special Feature Route";
public static final int VOLUME_MAX = 100;
+ public static final int SESSION_VOLUME_MAX = 50;
+ public static final int SESSION_VOLUME_INITIAL = 20;
public static final String ROUTE_ID_FIXED_VOLUME = "route_fixed_volume";
public static final String ROUTE_NAME_FIXED_VOLUME = "Fixed Volume Route";
public static final String ROUTE_ID_VARIABLE_VOLUME = "route_variable_volume";
@@ -141,12 +144,12 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
}
@Override
- public void onSetVolume(String routeId, int volume) {
+ public void onSetRouteVolume(String routeId, int volume) {
MediaRoute2Info route = mRoutes.get(routeId);
if (route == null) {
return;
}
- volume = Math.min(volume, Math.max(0, route.getVolumeMax()));
+ volume = Math.max(0, Math.min(volume, route.getVolumeMax()));
mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
.setVolume(volume)
.build());
@@ -154,6 +157,19 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
}
@Override
+ public void onSetSessionVolume(String sessionId, int volume) {
+ RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
+ if (sessionInfo == null) {
+ return;
+ }
+ volume = Math.max(0, Math.min(volume, sessionInfo.getVolumeMax()));
+ RoutingSessionInfo newSessionInfo = new RoutingSessionInfo.Builder(sessionInfo)
+ .setVolume(volume)
+ .build();
+ notifySessionUpdated(newSessionInfo);
+ }
+
+ @Override
public void onCreateSession(String packageName, String routeId, long requestId,
@Nullable Bundle sessionHints) {
MediaRoute2Info route = mRoutes.get(routeId);
@@ -176,6 +192,9 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
.addSelectedRoute(routeId)
.addSelectableRoute(ROUTE_ID4_TO_SELECT_AND_DESELECT)
.addTransferrableRoute(ROUTE_ID5_TO_TRANSFER_TO)
+ .setVolumeHandling(PLAYBACK_VOLUME_VARIABLE)
+ .setVolumeMax(SESSION_VOLUME_MAX)
+ .setVolume(SESSION_VOLUME_INITIAL)
// Set control hints with given sessionHints
.setControlHints(sessionHints)
.build();
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index 83588846ade8..3de5cf1ceaff 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -62,7 +62,8 @@ abstract class MediaRoute2Provider {
public abstract void transferToRoute(String sessionId, String routeId);
public abstract void sendControlRequest(String routeId, Intent request);
- public abstract void requestSetVolume(String routeId, int volume);
+ public abstract void setRouteVolume(String routeId, int volume);
+ public abstract void setSessionVolume(String sessionId, int volume);
@NonNull
public String getUniqueId() {
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index dd536ecd19fa..c1ea697d8a2d 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -131,9 +131,17 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
}
@Override
- public void requestSetVolume(String routeId, int volume) {
+ public void setRouteVolume(String routeId, int volume) {
if (mConnectionReady) {
- mActiveConnection.requestSetVolume(routeId, volume);
+ mActiveConnection.setRouteVolume(routeId, volume);
+ updateBinding();
+ }
+ }
+
+ @Override
+ public void setSessionVolume(String sessionId, int volume) {
+ if (mConnectionReady) {
+ mActiveConnection.setSessionVolume(sessionId, volume);
updateBinding();
}
}
@@ -456,7 +464,7 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
try {
mProvider.requestCreateSession(packageName, routeId, requestId, sessionHints);
} catch (RemoteException ex) {
- Slog.e(TAG, "Failed to deliver request to create a session.", ex);
+ Slog.e(TAG, "requestCreateSession: Failed to deliver request.");
}
}
@@ -464,7 +472,7 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
try {
mProvider.releaseSession(sessionId);
} catch (RemoteException ex) {
- Slog.e(TAG, "Failed to deliver request to release a session.", ex);
+ Slog.e(TAG, "releaseSession: Failed to deliver request.");
}
}
@@ -472,7 +480,7 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
try {
mProvider.updateDiscoveryPreference(discoveryPreference);
} catch (RemoteException ex) {
- Slog.e(TAG, "updateDiscoveryPreference(): Failed to deliver request.");
+ Slog.e(TAG, "updateDiscoveryPreference: Failed to deliver request.");
}
}
@@ -480,7 +488,7 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
try {
mProvider.selectRoute(sessionId, routeId);
} catch (RemoteException ex) {
- Slog.e(TAG, "Failed to deliver request to select a route for a session.", ex);
+ Slog.e(TAG, "selectRoute: Failed to deliver request.", ex);
}
}
@@ -488,7 +496,7 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
try {
mProvider.deselectRoute(sessionId, routeId);
} catch (RemoteException ex) {
- Slog.e(TAG, "Failed to deliver request to deselect a route from a session.", ex);
+ Slog.e(TAG, "deselectRoute: Failed to deliver request.", ex);
}
}
@@ -496,7 +504,7 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
try {
mProvider.transferToRoute(sessionId, routeId);
} catch (RemoteException ex) {
- Slog.e(TAG, "Failed to deliver request to transfer a session to a route.", ex);
+ Slog.e(TAG, "transferToRoute: Failed to deliver request.", ex);
}
}
@@ -504,15 +512,23 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
try {
mProvider.notifyControlRequestSent(routeId, request);
} catch (RemoteException ex) {
- Slog.e(TAG, "Failed to deliver request to send control request.", ex);
+ Slog.e(TAG, "sendControlRequest: Failed to deliver request.", ex);
+ }
+ }
+
+ public void setRouteVolume(String routeId, int volume) {
+ try {
+ mProvider.setRouteVolume(routeId, volume);
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "setRouteVolume: Failed to deliver request.", ex);
}
}
- public void requestSetVolume(String routeId, int volume) {
+ public void setSessionVolume(String sessionId, int volume) {
try {
- mProvider.requestSetVolume(routeId, volume);
+ mProvider.setSessionVolume(sessionId, volume);
} catch (RemoteException ex) {
- Slog.e(TAG, "Failed to deliver request to request set volume.", ex);
+ Slog.e(TAG, "setSessionVolume: Failed to deliver request.", ex);
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index b1133223e59a..2096531e7611 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -320,14 +320,29 @@ class MediaRouter2ServiceImpl {
}
}
- public void requestSetVolume2(IMediaRouter2Client client, MediaRoute2Info route, int volume) {
+ public void setRouteVolume2(IMediaRouter2Client client,
+ MediaRoute2Info route, int volume) {
Objects.requireNonNull(client, "client must not be null");
Objects.requireNonNull(route, "route must not be null");
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- requestSetVolumeLocked(client, route, volume);
+ setRouteVolumeLocked(client, route, volume);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public void setSessionVolume2(IMediaRouter2Client client, String sessionId, int volume) {
+ Objects.requireNonNull(client, "client must not be null");
+ Objects.requireNonNull(sessionId, "sessionId must not be null");
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ setSessionVolumeLocked(client, sessionId, volume);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -346,7 +361,7 @@ class MediaRouter2ServiceImpl {
}
}
- public void requestSetVolume2Manager(IMediaRouter2Manager manager,
+ public void setRouteVolume2Manager(IMediaRouter2Manager manager,
MediaRoute2Info route, int volume) {
Objects.requireNonNull(manager, "manager must not be null");
Objects.requireNonNull(route, "route must not be null");
@@ -354,7 +369,22 @@ class MediaRouter2ServiceImpl {
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- requestSetVolumeLocked(manager, route, volume);
+ setRouteVolumeLocked(manager, route, volume);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public void setSessionVolume2Manager(IMediaRouter2Manager manager,
+ String sessionId, int volume) {
+ Objects.requireNonNull(manager, "manager must not be null");
+ Objects.requireNonNull(sessionId, "sessionId must not be null");
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ setSessionVolumeLocked(manager, sessionId, volume);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -587,18 +617,30 @@ class MediaRouter2ServiceImpl {
}
}
- private void requestSetVolumeLocked(IMediaRouter2Client client, MediaRoute2Info route,
+ private void setRouteVolumeLocked(IMediaRouter2Client client, MediaRoute2Info route,
int volume) {
final IBinder binder = client.asBinder();
Client2Record clientRecord = mAllClientRecords.get(binder);
if (clientRecord != null) {
clientRecord.mUserRecord.mHandler.sendMessage(
- obtainMessage(UserHandler::requestSetVolume,
+ obtainMessage(UserHandler::setRouteVolume,
clientRecord.mUserRecord.mHandler, route, volume));
}
}
+ private void setSessionVolumeLocked(IMediaRouter2Client client, String sessionId,
+ int volume) {
+ final IBinder binder = client.asBinder();
+ Client2Record clientRecord = mAllClientRecords.get(binder);
+
+ if (clientRecord != null) {
+ clientRecord.mUserRecord.mHandler.sendMessage(
+ obtainMessage(UserHandler::setSessionVolume,
+ clientRecord.mUserRecord.mHandler, sessionId, volume));
+ }
+ }
+
private void registerManagerLocked(IMediaRouter2Manager manager,
int uid, int pid, String packageName, int userId, boolean trusted) {
final IBinder binder = manager.asBinder();
@@ -660,18 +702,30 @@ class MediaRouter2ServiceImpl {
}
}
- private void requestSetVolumeLocked(IMediaRouter2Manager manager, MediaRoute2Info route,
+ private void setRouteVolumeLocked(IMediaRouter2Manager manager, MediaRoute2Info route,
int volume) {
final IBinder binder = manager.asBinder();
ManagerRecord managerRecord = mAllManagerRecords.get(binder);
if (managerRecord != null) {
managerRecord.mUserRecord.mHandler.sendMessage(
- obtainMessage(UserHandler::requestSetVolume,
+ obtainMessage(UserHandler::setRouteVolume,
managerRecord.mUserRecord.mHandler, route, volume));
}
}
+ private void setSessionVolumeLocked(IMediaRouter2Manager manager, String sessionId,
+ int volume) {
+ final IBinder binder = manager.asBinder();
+ ManagerRecord managerRecord = mAllManagerRecords.get(binder);
+
+ if (managerRecord != null) {
+ managerRecord.mUserRecord.mHandler.sendMessage(
+ obtainMessage(UserHandler::setSessionVolume,
+ managerRecord.mUserRecord.mHandler, sessionId, volume));
+ }
+ }
+
private List<RoutingSessionInfo> getActiveSessionsLocked(IMediaRouter2Manager manager) {
final IBinder binder = manager.asBinder();
ManagerRecord managerRecord = mAllManagerRecords.get(binder);
@@ -1399,11 +1453,21 @@ class MediaRouter2ServiceImpl {
}
}
- private void requestSetVolume(MediaRoute2Info route, int volume) {
+ private void setRouteVolume(MediaRoute2Info route, int volume) {
final MediaRoute2Provider provider = findProvider(route.getProviderId());
if (provider != null) {
- provider.requestSetVolume(route.getOriginalId(), volume);
+ provider.setRouteVolume(route.getOriginalId(), volume);
+ }
+ }
+
+ private void setSessionVolume(String sessionId, int volume) {
+ final MediaRoute2Provider provider = findProvider(getProviderId(sessionId));
+ if (provider == null) {
+ Slog.w(TAG, "setSessionVolume: couldn't find provider for session "
+ + "id=" + sessionId);
+ return;
}
+ provider.setSessionVolume(getOriginalId(sessionId), volume);
}
private List<IMediaRouter2Client> getClients() {
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 57f0328f1c00..b38e47a1c25e 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -533,15 +533,29 @@ public final class MediaRouterService extends IMediaRouterService.Stub
// Binder call
@Override
- public void requestSetVolume2(IMediaRouter2Client client, MediaRoute2Info route, int volume) {
- mService2.requestSetVolume2(client, route, volume);
+ public void setRouteVolume2(IMediaRouter2Client client,
+ MediaRoute2Info route, int volume) {
+ mService2.setRouteVolume2(client, route, volume);
+ }
+
+ // Binder call
+ @Override
+ public void setSessionVolume2(IMediaRouter2Client client, String sessionId, int volume) {
+ mService2.setSessionVolume2(client, sessionId, volume);
}
// Binder call
@Override
- public void requestSetVolume2Manager(IMediaRouter2Manager manager,
+ public void setRouteVolume2Manager(IMediaRouter2Manager manager,
MediaRoute2Info route, int volume) {
- mService2.requestSetVolume2Manager(manager, route, volume);
+ mService2.setRouteVolume2Manager(manager, route, volume);
+ }
+
+ // Binder call
+ @Override
+ public void setSessionVolume2Manager(IMediaRouter2Manager manager,
+ String sessionId, int volume) {
+ mService2.setSessionVolume2Manager(manager, sessionId, volume);
}
// Binder call
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index b5dcea8bb51e..18383c431479 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -42,6 +42,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import java.util.Collections;
import java.util.List;
@@ -67,6 +68,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
SystemMediaRoute2Provider.class.getPackageName$(),
SystemMediaRoute2Provider.class.getName());
+ @GuardedBy("mLock")
+ private String mSelectedRouteId;
MediaRoute2Info mDefaultRoute;
@NonNull List<MediaRoute2Info> mBluetoothRoutes = Collections.EMPTY_LIST;
final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
@@ -153,9 +156,17 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
public void sendControlRequest(@NonNull String routeId, @NonNull Intent request) {
}
- //TODO: implement method
@Override
- public void requestSetVolume(String routeId, int volume) {
+ public void setRouteVolume(String routeId, int volume) {
+ if (!TextUtils.equals(routeId, mSelectedRouteId)) {
+ return;
+ }
+ mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
+ }
+
+ @Override
+ public void setSessionVolume(String sessionId, int volume) {
+ // Do nothing since we don't support grouping volume yet.
}
private void initializeDefaultRoute() {
@@ -241,18 +252,16 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
SYSTEM_SESSION_ID, "" /* clientPackageName */)
.setSystemSession(true);
String activeBtDeviceAddress = mBtRouteProvider.getActiveDeviceAddress();
+ mSelectedRouteId = TextUtils.isEmpty(activeBtDeviceAddress) ? mDefaultRoute.getId()
+ : activeBtDeviceAddress;
+ builder.addSelectedRoute(mSelectedRouteId);
if (!TextUtils.isEmpty(activeBtDeviceAddress)) {
- // Bluetooth route. Set the route ID with the device's address.
- builder.addSelectedRoute(activeBtDeviceAddress);
builder.addTransferrableRoute(mDefaultRoute.getId());
- } else {
- // Default device
- builder.addSelectedRoute(mDefaultRoute.getId());
}
for (MediaRoute2Info route : mBluetoothRoutes) {
- if (!TextUtils.equals(activeBtDeviceAddress, route.getId())) {
+ if (!TextUtils.equals(mSelectedRouteId, route.getId())) {
builder.addTransferrableRoute(route.getId());
}
}