Loading media/java/android/media/MediaRoute2Info.java +42 −3 Original line number Diff line number Diff line Loading @@ -648,6 +648,7 @@ public final class MediaRoute2Info implements Parcelable { private final boolean mAlsoAllowPrivilegedPackages; private final List<Set<String>> mRequiredPermissions; @SuitabilityStatus private final int mSuitabilityStatus; private Set<String> mTemporaryVisibilityPackages; MediaRoute2Info(@NonNull Builder builder) { mId = builder.mId; Loading @@ -673,6 +674,7 @@ public final class MediaRoute2Info implements Parcelable { mAlsoAllowPrivilegedPackages = builder.mAlsoAllowPrivilegedPackages; mSuitabilityStatus = builder.mSuitabilityStatus; mRequiredPermissions = List.copyOf(builder.mRequiredPermissions); mTemporaryVisibilityPackages = builder.mTemporaryVisibilityPackages; } MediaRoute2Info(@NonNull Parcel in) { Loading Loading @@ -705,6 +707,7 @@ public final class MediaRoute2Info implements Parcelable { } mRequiredPermissions = List.copyOf(requiredPermissions); // Use copyOf to make it immutable. mSuitabilityStatus = in.readInt(); mTemporaryVisibilityPackages = Set.of(); } /** Loading Loading @@ -962,6 +965,15 @@ public final class MediaRoute2Info implements Parcelable { return true; } /** * Returns whether this route can be seen by any router (i.e. has no visibility or permissions * restrictions). * @hide */ public boolean isPublic() { return !mIsVisibilityRestricted && mRequiredPermissions.isEmpty(); } /** * Returns whether this route is visible to the package with the given name. * Loading @@ -970,7 +982,8 @@ public final class MediaRoute2Info implements Parcelable { public boolean isVisibleTo(@NonNull String packageName) { return !mIsVisibilityRestricted || TextUtils.equals(getProviderPackageName(), packageName) || mAllowedPackages.contains(packageName); || mAllowedPackages.contains(packageName) || mTemporaryVisibilityPackages.contains(packageName); } /** Loading @@ -980,7 +993,8 @@ public final class MediaRoute2Info implements Parcelable { // TODO(b/426044649) - see the comment above on the mAlsoAllowPrivilegedPackages member // variable when removing the enableRouteVisibilityControlApi flag. return isVisibleTo(packageName) || (Flags.enableRouteVisibilityControlApi() && callerIsPrivileged && mAlsoAllowPrivilegedPackages); && callerIsPrivileged && mAlsoAllowPrivilegedPackages) || mTemporaryVisibilityPackages.contains(packageName); } /** Loading @@ -993,6 +1007,16 @@ public final class MediaRoute2Info implements Parcelable { return mRequiredPermissions; } /** * Returns a set of packages that should be allowed to see this route regardless of other * visibility or permissions-based restrictions. * * @hide */ public Set<String> getTemporaryVisibilityPackages() { return mTemporaryVisibilityPackages; } /** * Returns whether this route's type can only be published by the system route provider. * Loading Loading @@ -1104,7 +1128,8 @@ public final class MediaRoute2Info implements Parcelable { && Objects.equals(mAllowedPackages, other.mAllowedPackages) && mAlsoAllowPrivilegedPackages == other.mAlsoAllowPrivilegedPackages && Objects.equals(mRequiredPermissions, other.mRequiredPermissions) && mSuitabilityStatus == other.mSuitabilityStatus; && mSuitabilityStatus == other.mSuitabilityStatus && Objects.equals(mTemporaryVisibilityPackages, other.mTemporaryVisibilityPackages); } @Override Loading Loading @@ -1370,6 +1395,7 @@ public final class MediaRoute2Info implements Parcelable { // VISIBILITY_RESTRICTED_TO_ALLOWLIST_AND_PRIVILEGED private boolean mAlsoAllowPrivilegedPackages; private List<Set<String>> mRequiredPermissions; private Set<String> mTemporaryVisibilityPackages; @SuitabilityStatus private int mSuitabilityStatus; /** Loading @@ -1396,6 +1422,7 @@ public final class MediaRoute2Info implements Parcelable { mAllowedPackages = Set.of(); mSuitabilityStatus = SUITABILITY_STATUS_SUITABLE_FOR_DEFAULT_TRANSFER; mRequiredPermissions = List.of(); mTemporaryVisibilityPackages = Set.of(); } /** Loading Loading @@ -1447,6 +1474,7 @@ public final class MediaRoute2Info implements Parcelable { mAlsoAllowPrivilegedPackages = routeInfo.mAlsoAllowPrivilegedPackages; mSuitabilityStatus = routeInfo.mSuitabilityStatus; mRequiredPermissions = routeInfo.mRequiredPermissions; mTemporaryVisibilityPackages = routeInfo.mTemporaryVisibilityPackages; } /** Loading Loading @@ -1759,6 +1787,17 @@ public final class MediaRoute2Info implements Parcelable { return this; } /** * Sets a list of package names that will be temporarily given access to this route, even * if those apps otherwise would not have access due to visibility or permissions. * * @hide */ public Builder setTemporaryAllowedPackages(@NonNull Set<String> packageNames) { mTemporaryVisibilityPackages = Set.copyOf(packageNames); return this; } /** * Sets route suitability status. * Loading media/java/android/media/MediaRoute2ProviderInfo.java +6 −1 Original line number Diff line number Diff line Loading @@ -144,10 +144,15 @@ public final class MediaRoute2ProviderInfo implements Parcelable { } public Builder(@NonNull MediaRoute2ProviderInfo descriptor) { this(descriptor, descriptor.mRoutes); } public Builder(@NonNull MediaRoute2ProviderInfo descriptor, ArrayMap<String, MediaRoute2Info> routes) { Objects.requireNonNull(descriptor, "descriptor must not be null"); mUniqueId = descriptor.mUniqueId; mRoutes = new ArrayMap<>(descriptor.mRoutes); mRoutes = new ArrayMap<>(routes); } /** Loading media/java/android/media/MediaRouter2.java +32 −10 Original line number Diff line number Diff line Loading @@ -980,6 +980,18 @@ public final class MediaRouter2 { } mDiscoveryPreference = newDiscoveryPreference; updateFilteredRoutesLocked(); if (Flags.enableRouteVisibilityControlCompatFixes()) { mHandler.sendMessage( obtainMessage( MediaRouter2::dispatchFilteredRoutesUpdatedOnHandler, this, mFilteredRoutes)); mHandler.sendMessage( obtainMessage( MediaRouter2::dispatchControllerUpdatedIfNeededOnHandler, this, new HashMap<>(mRoutes))); } return true; } Loading Loading @@ -1426,6 +1438,10 @@ public final class MediaRouter2 { mRoutes.put(route.getId(), route); } updateFilteredRoutesLocked(); if (Flags.enableRouteVisibilityControlCompatFixes()) { dispatchFilteredRoutesUpdatedOnHandler(mFilteredRoutes); dispatchControllerUpdatedIfNeededOnHandler(mRoutes); } } } Loading @@ -1435,6 +1451,7 @@ public final class MediaRouter2 { mFilteredRoutes = Collections.unmodifiableList( filterRoutesWithCompositePreferenceLocked(List.copyOf(mRoutes.values()))); if (!Flags.enableRouteVisibilityControlCompatFixes()) { mHandler.sendMessage( obtainMessage( MediaRouter2::dispatchFilteredRoutesUpdatedOnHandler, Loading @@ -1446,6 +1463,7 @@ public final class MediaRouter2 { this, new HashMap<>(mRoutes))); } } /** * Creates a controller and calls the {@link TransferCallback#onTransfer}. If the controller Loading Loading @@ -3886,6 +3904,10 @@ public final class MediaRouter2 { updateFilteredRoutesLocked(); } notifyPreferredFeaturesChanged(preference.getPreferredFeatures()); if (Flags.enableRouteVisibilityControlCompatFixes()) { dispatchFilteredRoutesUpdatedOnHandler(mFilteredRoutes); dispatchControllerUpdatedIfNeededOnHandler(mRoutes); } } private void onRouteListingPreferenceChangedOnHandler( Loading services/core/java/com/android/server/media/MediaRoute2Provider.java +82 −0 Original line number Diff line number Diff line Loading @@ -28,11 +28,15 @@ import android.media.RouteDiscoveryPreference; import android.media.RoutingSessionInfo; import android.os.Bundle; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; import com.android.media.flags.Flags; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; Loading Loading @@ -112,6 +116,17 @@ abstract class MediaRoute2Provider { void setProviderState(MediaRoute2ProviderInfo providerInfo) { if (providerInfo == null) { mProviderInfo = null; return; } List<MediaRoute2Info> possiblyUpdatedRoutes = null; if (Flags.enableRouteVisibilityControlCompatFixes()) { possiblyUpdatedRoutes = getVisibilityUpdatedRoutesIfNeeded(providerInfo.getRoutes(), getSessionInfos()); } if (possiblyUpdatedRoutes != null) { setProviderStateWithUpdatedRoutes(providerInfo, possiblyUpdatedRoutes); } else { mProviderInfo = new MediaRoute2ProviderInfo.Builder(providerInfo) .setUniqueId(mComponentName.getPackageName(), mUniqueId) Loading @@ -120,6 +135,15 @@ abstract class MediaRoute2Provider { } } private void setProviderStateWithUpdatedRoutes(@NonNull MediaRoute2ProviderInfo providerInfo, @NonNull List<MediaRoute2Info> updatedRoutes) { mProviderInfo = new MediaRoute2ProviderInfo.Builder(providerInfo, new ArrayMap<>()) .addRoutes(updatedRoutes) .setUniqueId(mComponentName.getPackageName(), mUniqueId) .setSystemRouteProvider(mIsSystemRouteProvider) .build(); } protected boolean haveCallback() { return mCallback != null; } Loading @@ -132,6 +156,7 @@ abstract class MediaRoute2Provider { protected void notifySessionCreated(long requestId, @Nullable RoutingSessionInfo sessionInfo) { if (mCallback != null) { maybeUpdateProviderStateForRouteVisibility(); mCallback.onSessionCreated(this, requestId, sessionInfo); } } Loading @@ -142,6 +167,7 @@ abstract class MediaRoute2Provider { Set<String> packageNamesWithRoutingSessionOverrides, boolean shouldShowVolumeSystemUi) { if (mCallback != null) { maybeUpdateProviderStateForRouteVisibility(); mCallback.onSessionUpdated(this, sessionInfo, packageNamesWithRoutingSessionOverrides, shouldShowVolumeSystemUi); } Loading @@ -150,6 +176,7 @@ abstract class MediaRoute2Provider { protected void notifySessionReleased(@NonNull RoutingSessionInfo sessionInfo) { if (mCallback != null) { mCallback.onSessionReleased(this, sessionInfo); maybeUpdateProviderStateForRouteVisibility(); } } Loading Loading @@ -312,4 +339,59 @@ abstract class MediaRoute2Provider { .anyMatch(mTargetOriginalRouteId::equals); } } private void maybeUpdateProviderStateForRouteVisibility() { if (!Flags.enableRouteVisibilityControlCompatFixes()) { return; } List<MediaRoute2Info> possiblyUpdatedRoutes = getVisibilityUpdatedRoutesIfNeeded(mProviderInfo.getRoutes(), mSessionInfos); if (possiblyUpdatedRoutes != null) { setProviderStateWithUpdatedRoutes(mProviderInfo, possiblyUpdatedRoutes); notifyProviderStateChanged(); } } /** * Returns a copy of routes with any missing visibility added, or null if the existing * visibility is sufficient. * * <p>We consider visibility to be missing when a route is not visible to a given app, but a * routing session exists where that app is the {@link #getClientPackageName client} and that * route is selected. * * <p>In summary, this method ensures that all routes which are selected by an app are visible * to that app. */ @Nullable private List<MediaRoute2Info> getVisibilityUpdatedRoutesIfNeeded( Collection<MediaRoute2Info> routes, List<RoutingSessionInfo> sessions) { ArrayMap<String, Set<String>> selectedRouteToClient = new ArrayMap<>(); for (RoutingSessionInfo session : sessions) { session.getSelectedRoutes().forEach(routeId -> { Set<String> clients = selectedRouteToClient.computeIfAbsent(routeId, k -> new ArraySet<>()); clients.add(session.getClientPackageName()); }); } boolean updatedSomeRoute = false; ArrayList<MediaRoute2Info> updatedRoutes = new ArrayList<>(); for (MediaRoute2Info route : routes) { String fullId = MediaRouter2Utils.toUniqueId(mUniqueId, route.getOriginalId()); MediaRoute2Info routeToAdd = route; if (!route.isPublic()) { Set<String> clients = selectedRouteToClient.getOrDefault(fullId, Set.of()); if (!clients.equals(route.getTemporaryVisibilityPackages())) { routeToAdd = new MediaRoute2Info.Builder(route) .setTemporaryAllowedPackages(clients) .build(); updatedSomeRoute = true; } } updatedRoutes.add(routeToAdd); } return updatedSomeRoute ? updatedRoutes : null; } } services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +4 −0 Original line number Diff line number Diff line Loading @@ -2852,6 +2852,10 @@ class MediaRouter2ServiceImpl { if (!Flags.enableRouteVisibilityControlApi()) { return true; } if (Flags.enableRouteVisibilityControlCompatFixes() && route.getTemporaryVisibilityPackages().contains(mPackageName)) { return true; } List<Set<String>> permissionSets = route.getRequiredPermissions(); if (permissionSets.isEmpty()) { return true; Loading Loading
media/java/android/media/MediaRoute2Info.java +42 −3 Original line number Diff line number Diff line Loading @@ -648,6 +648,7 @@ public final class MediaRoute2Info implements Parcelable { private final boolean mAlsoAllowPrivilegedPackages; private final List<Set<String>> mRequiredPermissions; @SuitabilityStatus private final int mSuitabilityStatus; private Set<String> mTemporaryVisibilityPackages; MediaRoute2Info(@NonNull Builder builder) { mId = builder.mId; Loading @@ -673,6 +674,7 @@ public final class MediaRoute2Info implements Parcelable { mAlsoAllowPrivilegedPackages = builder.mAlsoAllowPrivilegedPackages; mSuitabilityStatus = builder.mSuitabilityStatus; mRequiredPermissions = List.copyOf(builder.mRequiredPermissions); mTemporaryVisibilityPackages = builder.mTemporaryVisibilityPackages; } MediaRoute2Info(@NonNull Parcel in) { Loading Loading @@ -705,6 +707,7 @@ public final class MediaRoute2Info implements Parcelable { } mRequiredPermissions = List.copyOf(requiredPermissions); // Use copyOf to make it immutable. mSuitabilityStatus = in.readInt(); mTemporaryVisibilityPackages = Set.of(); } /** Loading Loading @@ -962,6 +965,15 @@ public final class MediaRoute2Info implements Parcelable { return true; } /** * Returns whether this route can be seen by any router (i.e. has no visibility or permissions * restrictions). * @hide */ public boolean isPublic() { return !mIsVisibilityRestricted && mRequiredPermissions.isEmpty(); } /** * Returns whether this route is visible to the package with the given name. * Loading @@ -970,7 +982,8 @@ public final class MediaRoute2Info implements Parcelable { public boolean isVisibleTo(@NonNull String packageName) { return !mIsVisibilityRestricted || TextUtils.equals(getProviderPackageName(), packageName) || mAllowedPackages.contains(packageName); || mAllowedPackages.contains(packageName) || mTemporaryVisibilityPackages.contains(packageName); } /** Loading @@ -980,7 +993,8 @@ public final class MediaRoute2Info implements Parcelable { // TODO(b/426044649) - see the comment above on the mAlsoAllowPrivilegedPackages member // variable when removing the enableRouteVisibilityControlApi flag. return isVisibleTo(packageName) || (Flags.enableRouteVisibilityControlApi() && callerIsPrivileged && mAlsoAllowPrivilegedPackages); && callerIsPrivileged && mAlsoAllowPrivilegedPackages) || mTemporaryVisibilityPackages.contains(packageName); } /** Loading @@ -993,6 +1007,16 @@ public final class MediaRoute2Info implements Parcelable { return mRequiredPermissions; } /** * Returns a set of packages that should be allowed to see this route regardless of other * visibility or permissions-based restrictions. * * @hide */ public Set<String> getTemporaryVisibilityPackages() { return mTemporaryVisibilityPackages; } /** * Returns whether this route's type can only be published by the system route provider. * Loading Loading @@ -1104,7 +1128,8 @@ public final class MediaRoute2Info implements Parcelable { && Objects.equals(mAllowedPackages, other.mAllowedPackages) && mAlsoAllowPrivilegedPackages == other.mAlsoAllowPrivilegedPackages && Objects.equals(mRequiredPermissions, other.mRequiredPermissions) && mSuitabilityStatus == other.mSuitabilityStatus; && mSuitabilityStatus == other.mSuitabilityStatus && Objects.equals(mTemporaryVisibilityPackages, other.mTemporaryVisibilityPackages); } @Override Loading Loading @@ -1370,6 +1395,7 @@ public final class MediaRoute2Info implements Parcelable { // VISIBILITY_RESTRICTED_TO_ALLOWLIST_AND_PRIVILEGED private boolean mAlsoAllowPrivilegedPackages; private List<Set<String>> mRequiredPermissions; private Set<String> mTemporaryVisibilityPackages; @SuitabilityStatus private int mSuitabilityStatus; /** Loading @@ -1396,6 +1422,7 @@ public final class MediaRoute2Info implements Parcelable { mAllowedPackages = Set.of(); mSuitabilityStatus = SUITABILITY_STATUS_SUITABLE_FOR_DEFAULT_TRANSFER; mRequiredPermissions = List.of(); mTemporaryVisibilityPackages = Set.of(); } /** Loading Loading @@ -1447,6 +1474,7 @@ public final class MediaRoute2Info implements Parcelable { mAlsoAllowPrivilegedPackages = routeInfo.mAlsoAllowPrivilegedPackages; mSuitabilityStatus = routeInfo.mSuitabilityStatus; mRequiredPermissions = routeInfo.mRequiredPermissions; mTemporaryVisibilityPackages = routeInfo.mTemporaryVisibilityPackages; } /** Loading Loading @@ -1759,6 +1787,17 @@ public final class MediaRoute2Info implements Parcelable { return this; } /** * Sets a list of package names that will be temporarily given access to this route, even * if those apps otherwise would not have access due to visibility or permissions. * * @hide */ public Builder setTemporaryAllowedPackages(@NonNull Set<String> packageNames) { mTemporaryVisibilityPackages = Set.copyOf(packageNames); return this; } /** * Sets route suitability status. * Loading
media/java/android/media/MediaRoute2ProviderInfo.java +6 −1 Original line number Diff line number Diff line Loading @@ -144,10 +144,15 @@ public final class MediaRoute2ProviderInfo implements Parcelable { } public Builder(@NonNull MediaRoute2ProviderInfo descriptor) { this(descriptor, descriptor.mRoutes); } public Builder(@NonNull MediaRoute2ProviderInfo descriptor, ArrayMap<String, MediaRoute2Info> routes) { Objects.requireNonNull(descriptor, "descriptor must not be null"); mUniqueId = descriptor.mUniqueId; mRoutes = new ArrayMap<>(descriptor.mRoutes); mRoutes = new ArrayMap<>(routes); } /** Loading
media/java/android/media/MediaRouter2.java +32 −10 Original line number Diff line number Diff line Loading @@ -980,6 +980,18 @@ public final class MediaRouter2 { } mDiscoveryPreference = newDiscoveryPreference; updateFilteredRoutesLocked(); if (Flags.enableRouteVisibilityControlCompatFixes()) { mHandler.sendMessage( obtainMessage( MediaRouter2::dispatchFilteredRoutesUpdatedOnHandler, this, mFilteredRoutes)); mHandler.sendMessage( obtainMessage( MediaRouter2::dispatchControllerUpdatedIfNeededOnHandler, this, new HashMap<>(mRoutes))); } return true; } Loading Loading @@ -1426,6 +1438,10 @@ public final class MediaRouter2 { mRoutes.put(route.getId(), route); } updateFilteredRoutesLocked(); if (Flags.enableRouteVisibilityControlCompatFixes()) { dispatchFilteredRoutesUpdatedOnHandler(mFilteredRoutes); dispatchControllerUpdatedIfNeededOnHandler(mRoutes); } } } Loading @@ -1435,6 +1451,7 @@ public final class MediaRouter2 { mFilteredRoutes = Collections.unmodifiableList( filterRoutesWithCompositePreferenceLocked(List.copyOf(mRoutes.values()))); if (!Flags.enableRouteVisibilityControlCompatFixes()) { mHandler.sendMessage( obtainMessage( MediaRouter2::dispatchFilteredRoutesUpdatedOnHandler, Loading @@ -1446,6 +1463,7 @@ public final class MediaRouter2 { this, new HashMap<>(mRoutes))); } } /** * Creates a controller and calls the {@link TransferCallback#onTransfer}. If the controller Loading Loading @@ -3886,6 +3904,10 @@ public final class MediaRouter2 { updateFilteredRoutesLocked(); } notifyPreferredFeaturesChanged(preference.getPreferredFeatures()); if (Flags.enableRouteVisibilityControlCompatFixes()) { dispatchFilteredRoutesUpdatedOnHandler(mFilteredRoutes); dispatchControllerUpdatedIfNeededOnHandler(mRoutes); } } private void onRouteListingPreferenceChangedOnHandler( Loading
services/core/java/com/android/server/media/MediaRoute2Provider.java +82 −0 Original line number Diff line number Diff line Loading @@ -28,11 +28,15 @@ import android.media.RouteDiscoveryPreference; import android.media.RoutingSessionInfo; import android.os.Bundle; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; import com.android.media.flags.Flags; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; Loading Loading @@ -112,6 +116,17 @@ abstract class MediaRoute2Provider { void setProviderState(MediaRoute2ProviderInfo providerInfo) { if (providerInfo == null) { mProviderInfo = null; return; } List<MediaRoute2Info> possiblyUpdatedRoutes = null; if (Flags.enableRouteVisibilityControlCompatFixes()) { possiblyUpdatedRoutes = getVisibilityUpdatedRoutesIfNeeded(providerInfo.getRoutes(), getSessionInfos()); } if (possiblyUpdatedRoutes != null) { setProviderStateWithUpdatedRoutes(providerInfo, possiblyUpdatedRoutes); } else { mProviderInfo = new MediaRoute2ProviderInfo.Builder(providerInfo) .setUniqueId(mComponentName.getPackageName(), mUniqueId) Loading @@ -120,6 +135,15 @@ abstract class MediaRoute2Provider { } } private void setProviderStateWithUpdatedRoutes(@NonNull MediaRoute2ProviderInfo providerInfo, @NonNull List<MediaRoute2Info> updatedRoutes) { mProviderInfo = new MediaRoute2ProviderInfo.Builder(providerInfo, new ArrayMap<>()) .addRoutes(updatedRoutes) .setUniqueId(mComponentName.getPackageName(), mUniqueId) .setSystemRouteProvider(mIsSystemRouteProvider) .build(); } protected boolean haveCallback() { return mCallback != null; } Loading @@ -132,6 +156,7 @@ abstract class MediaRoute2Provider { protected void notifySessionCreated(long requestId, @Nullable RoutingSessionInfo sessionInfo) { if (mCallback != null) { maybeUpdateProviderStateForRouteVisibility(); mCallback.onSessionCreated(this, requestId, sessionInfo); } } Loading @@ -142,6 +167,7 @@ abstract class MediaRoute2Provider { Set<String> packageNamesWithRoutingSessionOverrides, boolean shouldShowVolumeSystemUi) { if (mCallback != null) { maybeUpdateProviderStateForRouteVisibility(); mCallback.onSessionUpdated(this, sessionInfo, packageNamesWithRoutingSessionOverrides, shouldShowVolumeSystemUi); } Loading @@ -150,6 +176,7 @@ abstract class MediaRoute2Provider { protected void notifySessionReleased(@NonNull RoutingSessionInfo sessionInfo) { if (mCallback != null) { mCallback.onSessionReleased(this, sessionInfo); maybeUpdateProviderStateForRouteVisibility(); } } Loading Loading @@ -312,4 +339,59 @@ abstract class MediaRoute2Provider { .anyMatch(mTargetOriginalRouteId::equals); } } private void maybeUpdateProviderStateForRouteVisibility() { if (!Flags.enableRouteVisibilityControlCompatFixes()) { return; } List<MediaRoute2Info> possiblyUpdatedRoutes = getVisibilityUpdatedRoutesIfNeeded(mProviderInfo.getRoutes(), mSessionInfos); if (possiblyUpdatedRoutes != null) { setProviderStateWithUpdatedRoutes(mProviderInfo, possiblyUpdatedRoutes); notifyProviderStateChanged(); } } /** * Returns a copy of routes with any missing visibility added, or null if the existing * visibility is sufficient. * * <p>We consider visibility to be missing when a route is not visible to a given app, but a * routing session exists where that app is the {@link #getClientPackageName client} and that * route is selected. * * <p>In summary, this method ensures that all routes which are selected by an app are visible * to that app. */ @Nullable private List<MediaRoute2Info> getVisibilityUpdatedRoutesIfNeeded( Collection<MediaRoute2Info> routes, List<RoutingSessionInfo> sessions) { ArrayMap<String, Set<String>> selectedRouteToClient = new ArrayMap<>(); for (RoutingSessionInfo session : sessions) { session.getSelectedRoutes().forEach(routeId -> { Set<String> clients = selectedRouteToClient.computeIfAbsent(routeId, k -> new ArraySet<>()); clients.add(session.getClientPackageName()); }); } boolean updatedSomeRoute = false; ArrayList<MediaRoute2Info> updatedRoutes = new ArrayList<>(); for (MediaRoute2Info route : routes) { String fullId = MediaRouter2Utils.toUniqueId(mUniqueId, route.getOriginalId()); MediaRoute2Info routeToAdd = route; if (!route.isPublic()) { Set<String> clients = selectedRouteToClient.getOrDefault(fullId, Set.of()); if (!clients.equals(route.getTemporaryVisibilityPackages())) { routeToAdd = new MediaRoute2Info.Builder(route) .setTemporaryAllowedPackages(clients) .build(); updatedSomeRoute = true; } } updatedRoutes.add(routeToAdd); } return updatedSomeRoute ? updatedRoutes : null; } }
services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +4 −0 Original line number Diff line number Diff line Loading @@ -2852,6 +2852,10 @@ class MediaRouter2ServiceImpl { if (!Flags.enableRouteVisibilityControlApi()) { return true; } if (Flags.enableRouteVisibilityControlCompatFixes() && route.getTemporaryVisibilityPackages().contains(mPackageName)) { return true; } List<Set<String>> permissionSets = route.getRequiredPermissions(); if (permissionSets.isEmpty()) { return true; Loading