Loading media/java/android/media/MediaRouter2Manager.java +80 −2 Original line number Diff line number Diff line Loading @@ -170,8 +170,7 @@ public final class MediaRouter2Manager { public MediaController getMediaControllerForRoutingSession( @NonNull RoutingSessionInfo sessionInfo) { for (MediaController controller : mMediaSessionManager.getActiveSessions(null)) { String volumeControlId = controller.getPlaybackInfo().getVolumeControlId(); if (TextUtils.equals(sessionInfo.getId(), volumeControlId)) { if (areSessionsMatched(controller, sessionInfo)) { return controller; } } Loading Loading @@ -205,6 +204,37 @@ public final class MediaRouter2Manager { return routes; } /** * Gets available routes for the given routing session. * The returned routes can be passed to * {@link #transfer(RoutingSessionInfo, MediaRoute2Info)} for transferring the routing session. * * @param sessionInfo the routing session that would be transferred */ @NonNull public List<MediaRoute2Info> getAvailableRoutesForRoutingSession( @NonNull RoutingSessionInfo sessionInfo) { Objects.requireNonNull(sessionInfo, "sessionInfo must not be null"); List<MediaRoute2Info> routes = new ArrayList<>(); String packageName = sessionInfo.getClientPackageName(); List<String> preferredFeatures = mPreferredFeaturesMap.get(packageName); if (preferredFeatures == null) { preferredFeatures = Collections.emptyList(); } synchronized (mRoutesLock) { for (MediaRoute2Info route : mRoutes.values()) { if (route.isSystemRoute() || route.hasAnyFeatures(preferredFeatures) || sessionInfo.getSelectedRoutes().contains(route.getId()) || sessionInfo.getTransferableRoutes().contains(route.getId())) { routes.add(route); } } } return routes; } /** * Gets the system routing session associated with no specific application. */ Loading @@ -218,6 +248,33 @@ public final class MediaRouter2Manager { throw new IllegalStateException("No system routing session"); } /** * Gets the routing session of a media session. * If the session is using {#link PlaybackInfo#PLAYBACK_TYPE_LOCAL local playback}, * the system routing session is returned. * If the session is using {#link PlaybackInfo#PLAYBACK_TYPE_REMOTE remote playback}, * it returns the corresponding routing session or {@code null} if it's unavailable. */ @Nullable public RoutingSessionInfo getRoutingSessionForMediaController(MediaController mediaController) { MediaController.PlaybackInfo playbackInfo = mediaController.getPlaybackInfo(); if (playbackInfo == null) { return null; } if (playbackInfo.getPlaybackType() == MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL) { return new RoutingSessionInfo.Builder(getSystemRoutingSession()) .setClientPackageName(mediaController.getPackageName()) .build(); } for (RoutingSessionInfo sessionInfo : getActiveSessions()) { if (!sessionInfo.isSystemSession() && areSessionsMatched(mediaController, sessionInfo)) { return sessionInfo; } } return null; } /** * Gets routing sessions of an application with the given package name. * The first element of the returned list is the system routing session. Loading Loading @@ -762,6 +819,27 @@ public final class MediaRouter2Manager { } } private boolean areSessionsMatched(MediaController mediaController, RoutingSessionInfo sessionInfo) { MediaController.PlaybackInfo playbackInfo = mediaController.getPlaybackInfo(); if (playbackInfo == null) { return false; } String volumeControlId = playbackInfo.getVolumeControlId(); if (volumeControlId == null) { return false; } if (TextUtils.equals(volumeControlId, sessionInfo.getId())) { return true; } // Workaround for provider not being able to know the unique session ID. return TextUtils.equals(volumeControlId, sessionInfo.getOriginalId()) && TextUtils.equals(mediaController.getPackageName(), sessionInfo.getOwnerPackageName()); } private List<MediaRoute2Info> getRoutesWithIds(List<String> routeIds) { synchronized (sLock) { return routeIds.stream().map(mRoutes::get) Loading media/java/android/media/RoutingSessionInfo.java +27 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ public final class RoutingSessionInfo implements Parcelable { final String mId; final CharSequence mName; final String mOwnerPackageName; final String mClientPackageName; @Nullable final String mProviderId; Loading @@ -71,6 +72,7 @@ public final class RoutingSessionInfo implements Parcelable { mId = builder.mId; mName = builder.mName; mOwnerPackageName = builder.mOwnerPackageName; mClientPackageName = builder.mClientPackageName; mProviderId = builder.mProviderId; Loading @@ -96,6 +98,7 @@ public final class RoutingSessionInfo implements Parcelable { mId = ensureString(src.readString()); mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(src); mOwnerPackageName = src.readString(); mClientPackageName = ensureString(src.readString()); mProviderId = src.readString(); Loading Loading @@ -158,6 +161,15 @@ public final class RoutingSessionInfo implements Parcelable { return mId; } /** * Gets the package name of the session owner. * @hide */ @Nullable public String getOwnerPackageName() { return mOwnerPackageName; } /** * Gets the client package name of the session */ Loading Loading @@ -263,6 +275,7 @@ public final class RoutingSessionInfo implements Parcelable { public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(mId); dest.writeCharSequence(mName); dest.writeString(mOwnerPackageName); dest.writeString(mClientPackageName); dest.writeString(mProviderId); dest.writeStringList(mSelectedRoutes); Loading @@ -288,6 +301,7 @@ public final class RoutingSessionInfo implements Parcelable { RoutingSessionInfo other = (RoutingSessionInfo) obj; return Objects.equals(mId, other.mId) && Objects.equals(mName, other.mName) && Objects.equals(mOwnerPackageName, other.mOwnerPackageName) && Objects.equals(mClientPackageName, other.mClientPackageName) && Objects.equals(mProviderId, other.mProviderId) && Objects.equals(mSelectedRoutes, other.mSelectedRoutes) Loading @@ -301,7 +315,7 @@ public final class RoutingSessionInfo implements Parcelable { @Override public int hashCode() { return Objects.hash(mId, mName, mClientPackageName, mProviderId, return Objects.hash(mId, mName, mOwnerPackageName, mClientPackageName, mProviderId, mSelectedRoutes, mSelectableRoutes, mDeselectableRoutes, mTransferableRoutes, mVolumeMax, mVolumeHandling, mVolume); } Loading Loading @@ -356,6 +370,7 @@ public final class RoutingSessionInfo implements Parcelable { // TODO: Reorder these (important ones first) final String mId; CharSequence mName; String mOwnerPackageName; String mClientPackageName; String mProviderId; final List<String> mSelectedRoutes; Loading Loading @@ -439,6 +454,17 @@ public final class RoutingSessionInfo implements Parcelable { return this; } /** * Sets the package name of the session owner. It is expected to be called by the system. * * @hide */ @NonNull public Builder setOwnerPackageName(@Nullable String packageName) { mOwnerPackageName = packageName; return this; } /** * Sets the client package name of the session. * Loading services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java +10 −9 Original line number Diff line number Diff line Loading @@ -315,9 +315,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider return; } sessionInfo = new RoutingSessionInfo.Builder(sessionInfo) .setProviderId(getUniqueId()) .build(); sessionInfo = updateSessionInfo(sessionInfo); boolean duplicateSessionAlreadyExists = false; synchronized (mLock) { Loading Loading @@ -348,9 +346,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider return; } sessionInfo = new RoutingSessionInfo.Builder(sessionInfo) .setProviderId(getUniqueId()) .build(); sessionInfo = updateSessionInfo(sessionInfo); boolean found = false; synchronized (mLock) { Loading Loading @@ -380,9 +376,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider return; } sessionInfo = new RoutingSessionInfo.Builder(sessionInfo) .setProviderId(getUniqueId()) .build(); sessionInfo = updateSessionInfo(sessionInfo); boolean found = false; synchronized (mLock) { Loading @@ -403,6 +397,13 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider mCallback.onSessionReleased(this, sessionInfo); } private RoutingSessionInfo updateSessionInfo(RoutingSessionInfo sessionInfo) { return new RoutingSessionInfo.Builder(sessionInfo) .setOwnerPackageName(mComponentName.getPackageName()) .setProviderId(getUniqueId()) .build(); } private void onRequestFailed(Connection connection, long requestId, int reason) { if (mActiveConnection != connection) { return; Loading Loading
media/java/android/media/MediaRouter2Manager.java +80 −2 Original line number Diff line number Diff line Loading @@ -170,8 +170,7 @@ public final class MediaRouter2Manager { public MediaController getMediaControllerForRoutingSession( @NonNull RoutingSessionInfo sessionInfo) { for (MediaController controller : mMediaSessionManager.getActiveSessions(null)) { String volumeControlId = controller.getPlaybackInfo().getVolumeControlId(); if (TextUtils.equals(sessionInfo.getId(), volumeControlId)) { if (areSessionsMatched(controller, sessionInfo)) { return controller; } } Loading Loading @@ -205,6 +204,37 @@ public final class MediaRouter2Manager { return routes; } /** * Gets available routes for the given routing session. * The returned routes can be passed to * {@link #transfer(RoutingSessionInfo, MediaRoute2Info)} for transferring the routing session. * * @param sessionInfo the routing session that would be transferred */ @NonNull public List<MediaRoute2Info> getAvailableRoutesForRoutingSession( @NonNull RoutingSessionInfo sessionInfo) { Objects.requireNonNull(sessionInfo, "sessionInfo must not be null"); List<MediaRoute2Info> routes = new ArrayList<>(); String packageName = sessionInfo.getClientPackageName(); List<String> preferredFeatures = mPreferredFeaturesMap.get(packageName); if (preferredFeatures == null) { preferredFeatures = Collections.emptyList(); } synchronized (mRoutesLock) { for (MediaRoute2Info route : mRoutes.values()) { if (route.isSystemRoute() || route.hasAnyFeatures(preferredFeatures) || sessionInfo.getSelectedRoutes().contains(route.getId()) || sessionInfo.getTransferableRoutes().contains(route.getId())) { routes.add(route); } } } return routes; } /** * Gets the system routing session associated with no specific application. */ Loading @@ -218,6 +248,33 @@ public final class MediaRouter2Manager { throw new IllegalStateException("No system routing session"); } /** * Gets the routing session of a media session. * If the session is using {#link PlaybackInfo#PLAYBACK_TYPE_LOCAL local playback}, * the system routing session is returned. * If the session is using {#link PlaybackInfo#PLAYBACK_TYPE_REMOTE remote playback}, * it returns the corresponding routing session or {@code null} if it's unavailable. */ @Nullable public RoutingSessionInfo getRoutingSessionForMediaController(MediaController mediaController) { MediaController.PlaybackInfo playbackInfo = mediaController.getPlaybackInfo(); if (playbackInfo == null) { return null; } if (playbackInfo.getPlaybackType() == MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL) { return new RoutingSessionInfo.Builder(getSystemRoutingSession()) .setClientPackageName(mediaController.getPackageName()) .build(); } for (RoutingSessionInfo sessionInfo : getActiveSessions()) { if (!sessionInfo.isSystemSession() && areSessionsMatched(mediaController, sessionInfo)) { return sessionInfo; } } return null; } /** * Gets routing sessions of an application with the given package name. * The first element of the returned list is the system routing session. Loading Loading @@ -762,6 +819,27 @@ public final class MediaRouter2Manager { } } private boolean areSessionsMatched(MediaController mediaController, RoutingSessionInfo sessionInfo) { MediaController.PlaybackInfo playbackInfo = mediaController.getPlaybackInfo(); if (playbackInfo == null) { return false; } String volumeControlId = playbackInfo.getVolumeControlId(); if (volumeControlId == null) { return false; } if (TextUtils.equals(volumeControlId, sessionInfo.getId())) { return true; } // Workaround for provider not being able to know the unique session ID. return TextUtils.equals(volumeControlId, sessionInfo.getOriginalId()) && TextUtils.equals(mediaController.getPackageName(), sessionInfo.getOwnerPackageName()); } private List<MediaRoute2Info> getRoutesWithIds(List<String> routeIds) { synchronized (sLock) { return routeIds.stream().map(mRoutes::get) Loading
media/java/android/media/RoutingSessionInfo.java +27 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ public final class RoutingSessionInfo implements Parcelable { final String mId; final CharSequence mName; final String mOwnerPackageName; final String mClientPackageName; @Nullable final String mProviderId; Loading @@ -71,6 +72,7 @@ public final class RoutingSessionInfo implements Parcelable { mId = builder.mId; mName = builder.mName; mOwnerPackageName = builder.mOwnerPackageName; mClientPackageName = builder.mClientPackageName; mProviderId = builder.mProviderId; Loading @@ -96,6 +98,7 @@ public final class RoutingSessionInfo implements Parcelable { mId = ensureString(src.readString()); mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(src); mOwnerPackageName = src.readString(); mClientPackageName = ensureString(src.readString()); mProviderId = src.readString(); Loading Loading @@ -158,6 +161,15 @@ public final class RoutingSessionInfo implements Parcelable { return mId; } /** * Gets the package name of the session owner. * @hide */ @Nullable public String getOwnerPackageName() { return mOwnerPackageName; } /** * Gets the client package name of the session */ Loading Loading @@ -263,6 +275,7 @@ public final class RoutingSessionInfo implements Parcelable { public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(mId); dest.writeCharSequence(mName); dest.writeString(mOwnerPackageName); dest.writeString(mClientPackageName); dest.writeString(mProviderId); dest.writeStringList(mSelectedRoutes); Loading @@ -288,6 +301,7 @@ public final class RoutingSessionInfo implements Parcelable { RoutingSessionInfo other = (RoutingSessionInfo) obj; return Objects.equals(mId, other.mId) && Objects.equals(mName, other.mName) && Objects.equals(mOwnerPackageName, other.mOwnerPackageName) && Objects.equals(mClientPackageName, other.mClientPackageName) && Objects.equals(mProviderId, other.mProviderId) && Objects.equals(mSelectedRoutes, other.mSelectedRoutes) Loading @@ -301,7 +315,7 @@ public final class RoutingSessionInfo implements Parcelable { @Override public int hashCode() { return Objects.hash(mId, mName, mClientPackageName, mProviderId, return Objects.hash(mId, mName, mOwnerPackageName, mClientPackageName, mProviderId, mSelectedRoutes, mSelectableRoutes, mDeselectableRoutes, mTransferableRoutes, mVolumeMax, mVolumeHandling, mVolume); } Loading Loading @@ -356,6 +370,7 @@ public final class RoutingSessionInfo implements Parcelable { // TODO: Reorder these (important ones first) final String mId; CharSequence mName; String mOwnerPackageName; String mClientPackageName; String mProviderId; final List<String> mSelectedRoutes; Loading Loading @@ -439,6 +454,17 @@ public final class RoutingSessionInfo implements Parcelable { return this; } /** * Sets the package name of the session owner. It is expected to be called by the system. * * @hide */ @NonNull public Builder setOwnerPackageName(@Nullable String packageName) { mOwnerPackageName = packageName; return this; } /** * Sets the client package name of the session. * Loading
services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java +10 −9 Original line number Diff line number Diff line Loading @@ -315,9 +315,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider return; } sessionInfo = new RoutingSessionInfo.Builder(sessionInfo) .setProviderId(getUniqueId()) .build(); sessionInfo = updateSessionInfo(sessionInfo); boolean duplicateSessionAlreadyExists = false; synchronized (mLock) { Loading Loading @@ -348,9 +346,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider return; } sessionInfo = new RoutingSessionInfo.Builder(sessionInfo) .setProviderId(getUniqueId()) .build(); sessionInfo = updateSessionInfo(sessionInfo); boolean found = false; synchronized (mLock) { Loading Loading @@ -380,9 +376,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider return; } sessionInfo = new RoutingSessionInfo.Builder(sessionInfo) .setProviderId(getUniqueId()) .build(); sessionInfo = updateSessionInfo(sessionInfo); boolean found = false; synchronized (mLock) { Loading @@ -403,6 +397,13 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider mCallback.onSessionReleased(this, sessionInfo); } private RoutingSessionInfo updateSessionInfo(RoutingSessionInfo sessionInfo) { return new RoutingSessionInfo.Builder(sessionInfo) .setOwnerPackageName(mComponentName.getPackageName()) .setProviderId(getUniqueId()) .build(); } private void onRequestFailed(Connection connection, long requestId, int reason) { if (mActiveConnection != connection) { return; Loading