diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java index fb95e98ebf477..72162c44ec292 100644 --- a/media/java/android/media/MediaRoute2ProviderService.java +++ b/media/java/android/media/MediaRoute2ProviderService.java @@ -519,6 +519,7 @@ public abstract class MediaRoute2ProviderService extends Service { requestCreateSession)); } + //TODO: Ignore requests with unknown session ID. @Override public void selectRoute(long requestId, String sessionId, String routeId) { if (!checkCallerisSystem()) { diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index 2c65cc4440a44..7d14ef5542cc7 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -604,7 +604,8 @@ public final class MediaRouter2 { RoutingController oldController = getCurrentController(); if (!oldController.releaseInternal( - /* shouldReleaseSession= */ true, /* shouldNotifyStop= */ false)) { + /* shouldReleaseSession= */ matchingRequest != null, + /* shouldNotifyStop= */ false)) { // Could not release the controller since it was just released by other thread. oldController = getSystemController(); } diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java index 3b570b60ff24d..5d61dd06c7920 100644 --- a/media/java/android/media/MediaRouter2Manager.java +++ b/media/java/android/media/MediaRouter2Manager.java @@ -314,7 +314,6 @@ public final class MediaRouter2Manager { //TODO: Ignore unknown route. if (sessionInfo.getTransferableRoutes().contains(route.getId())) { - //TODO: callbacks must be called after this. transferToRoute(sessionInfo, route); return; } @@ -340,7 +339,6 @@ public final class MediaRouter2Manager { } catch (RemoteException ex) { Log.e(TAG, "Unable to select media route", ex); } - releaseSession(sessionInfo); } } @@ -489,6 +487,7 @@ public final class MediaRouter2Manager { notifyTransferFailed(matchingRequest.mOldSessionInfo, requestedRoute); return; } + releaseSession(matchingRequest.mOldSessionInfo); notifyTransferred(matchingRequest.mOldSessionInfo, sessionInfo); } diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index d8bf9edee2b7a..5e865e7cb7153 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -1574,8 +1574,15 @@ class MediaRouter2ServiceImpl { } // Succeeded - notifySessionCreatedToRouter(matchingRequest.mRouterRecord, - toOriginalRequestId(uniqueRequestId), sessionInfo); + if (sessionInfo.isSystemSession() + && !matchingRequest.mRouterRecord.mHasModifyAudioRoutingPermission) { + notifySessionCreatedToRouter(matchingRequest.mRouterRecord, + toOriginalRequestId(uniqueRequestId), + mSystemProvider.getDefaultSessionInfo()); + } else { + notifySessionCreatedToRouter(matchingRequest.mRouterRecord, + toOriginalRequestId(uniqueRequestId), sessionInfo); + } mSessionToRouterMap.put(sessionInfo.getId(), routerRecord); } diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java index 41d7fff52a911..b585b49928cd4 100644 --- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java @@ -36,6 +36,7 @@ import android.media.IAudioRoutesObserver; import android.media.IAudioService; import android.media.MediaRoute2Info; import android.media.MediaRoute2ProviderInfo; +import android.media.MediaRoute2ProviderService; import android.media.RouteDiscoveryPreference; import android.media.RoutingSessionInfo; import android.os.Bundle; @@ -47,6 +48,7 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.R; +import com.android.internal.annotations.GuardedBy; import java.util.Objects; @@ -80,6 +82,10 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { RoutingSessionInfo mDefaultSessionInfo; final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo(); + private final Object mRequestLock = new Object(); + @GuardedBy("mRequestLock") + private volatile SessionCreationRequest mPendingSessionCreationRequest; + final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() { @Override public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) { @@ -135,10 +141,27 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { @Override public void requestCreateSession(long requestId, String packageName, String routeId, Bundle sessionHints) { + // Assume a router without MODIFY_AUDIO_ROUTING permission can't request with + // a route ID different from the default route ID. The service should've filtered. + if (TextUtils.equals(routeId, DEFAULT_ROUTE_ID)) { + mCallback.onSessionCreated(this, requestId, mDefaultSessionInfo); + return; + } + if (TextUtils.equals(routeId, mSelectedRouteId)) { + mCallback.onSessionCreated(this, requestId, mSessionInfos.get(0)); + return; + } + + synchronized (mRequestLock) { + // Handle the previous request as a failure if exists. + if (mPendingSessionCreationRequest != null) { + mCallback.onRequestFailed(this, mPendingSessionCreationRequest.mRequestId, + MediaRoute2ProviderService.REASON_UNKNOWN_ERROR); + } + mPendingSessionCreationRequest = new SessionCreationRequest(requestId, routeId); + } transferToRoute(requestId, SYSTEM_SESSION_ID, routeId); - mCallback.onSessionCreated(this, requestId, mSessionInfos.get(0)); - //TODO: We should call after the session info is changed. } @Override @@ -280,6 +303,24 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } RoutingSessionInfo newSessionInfo = builder.setProviderId(mUniqueId).build(); + + if (mPendingSessionCreationRequest != null) { + SessionCreationRequest sessionCreationRequest; + synchronized (mRequestLock) { + sessionCreationRequest = mPendingSessionCreationRequest; + mPendingSessionCreationRequest = null; + } + if (sessionCreationRequest != null) { + if (TextUtils.equals(mSelectedRouteId, sessionCreationRequest.mRouteId)) { + mCallback.onSessionCreated(this, + sessionCreationRequest.mRequestId, newSessionInfo); + } else { + mCallback.onRequestFailed(this, sessionCreationRequest.mRequestId, + MediaRoute2ProviderService.REASON_UNKNOWN_ERROR); + } + } + } + if (Objects.equals(oldSessionInfo, newSessionInfo)) { return false; } else { @@ -310,6 +351,16 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { mCallback.onSessionUpdated(this, sessionInfo); } + private static class SessionCreationRequest { + final long mRequestId; + final String mRouteId; + + SessionCreationRequest(long requestId, String routeId) { + this.mRequestId = requestId; + this.mRouteId = routeId; + } + } + private class VolumeChangeReceiver extends BroadcastReceiver { // This will be called in the main thread. @Override