Loading core/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -24861,6 +24861,7 @@ package android.media { method @Nullable public android.net.Uri getIconUri(); method @NonNull public String getId(); method @NonNull public CharSequence getName(); method @FlaggedApi("com.android.media.flags.enable_route_visibility_control_api") @NonNull public java.util.Set<java.lang.String> getRequiredPermissions(); method @FlaggedApi("com.android.media.flags.enable_built_in_speaker_route_suitability_statuses") public int getSuitabilityStatus(); method @FlaggedApi("com.android.media.flags.enable_mirroring_in_media_router_2") public int getSupportedRoutingTypes(); method public int getType(); Loading Loading @@ -24929,6 +24930,7 @@ package android.media { method @NonNull public android.media.MediaRoute2Info.Builder setDescription(@Nullable CharSequence); method @NonNull public android.media.MediaRoute2Info.Builder setExtras(@Nullable android.os.Bundle); method @NonNull public android.media.MediaRoute2Info.Builder setIconUri(@Nullable android.net.Uri); method @FlaggedApi("com.android.media.flags.enable_route_visibility_control_api") @NonNull public android.media.MediaRoute2Info.Builder setRequiredPermissions(@NonNull java.util.Set<java.lang.String>); method @FlaggedApi("com.android.media.flags.enable_built_in_speaker_route_suitability_statuses") @NonNull public android.media.MediaRoute2Info.Builder setSuitabilityStatus(int); method @FlaggedApi("com.android.media.flags.enable_mirroring_in_media_router_2") @NonNull public android.media.MediaRoute2Info.Builder setSupportedRoutingTypes(int); method @NonNull public android.media.MediaRoute2Info.Builder setType(int); media/java/android/media/MediaRoute2Info.java +36 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static com.android.media.flags.Flags.FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_S import static com.android.media.flags.Flags.FLAG_ENABLE_MIRRORING_IN_MEDIA_ROUTER_2; import static com.android.media.flags.Flags.FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES; import static com.android.media.flags.Flags.FLAG_ENABLE_NEW_WIRED_MEDIA_ROUTE_2_INFO_TYPES; import static com.android.media.flags.Flags.FLAG_ENABLE_ROUTE_VISIBILITY_CONTROL_API; import android.annotation.FlaggedApi; import android.annotation.IntDef; Loading Loading @@ -616,6 +617,7 @@ public final class MediaRoute2Info implements Parcelable { private final String mProviderId; private final boolean mIsVisibilityRestricted; private final Set<String> mAllowedPackages; private final Set<String> mRequiredPermissions; @SuitabilityStatus private final int mSuitabilityStatus; MediaRoute2Info(@NonNull Builder builder) { Loading @@ -640,6 +642,7 @@ public final class MediaRoute2Info implements Parcelable { mIsVisibilityRestricted = builder.mIsVisibilityRestricted; mAllowedPackages = builder.mAllowedPackages; mSuitabilityStatus = builder.mSuitabilityStatus; mRequiredPermissions = Set.copyOf(builder.mRequiredPermissions); } MediaRoute2Info(@NonNull Parcel in) { Loading @@ -664,6 +667,7 @@ public final class MediaRoute2Info implements Parcelable { mProviderId = in.readString(); mIsVisibilityRestricted = in.readBoolean(); mAllowedPackages = Set.of(in.createString8Array()); mRequiredPermissions = Set.of(in.createString8Array()); mSuitabilityStatus = in.readInt(); } Loading Loading @@ -906,6 +910,15 @@ public final class MediaRoute2Info implements Parcelable { || mAllowedPackages.contains(packageName); } /** * @return the set of permissions which must be held to see this route */ @NonNull @FlaggedApi(FLAG_ENABLE_ROUTE_VISIBILITY_CONTROL_API) public Set<String> getRequiredPermissions() { return mRequiredPermissions; } /** * Returns whether this route's type can only be published by the system route provider. * Loading Loading @@ -977,6 +990,7 @@ public final class MediaRoute2Info implements Parcelable { pw.println(indent + "mIsVisibilityRestricted=" + mIsVisibilityRestricted); pw.println(indent + "mAllowedPackages=" + mAllowedPackages); pw.println(indent + "mSuitabilityStatus=" + mSuitabilityStatus); pw.println(indent + "mRequiredPermissions=" + mRequiredPermissions); } private void dumpVolume(@NonNull PrintWriter pw, @NonNull String prefix) { Loading Loading @@ -1013,6 +1027,7 @@ public final class MediaRoute2Info implements Parcelable { && Objects.equals(mProviderId, other.mProviderId) && (mIsVisibilityRestricted == other.mIsVisibilityRestricted) && Objects.equals(mAllowedPackages, other.mAllowedPackages) && Objects.equals(mRequiredPermissions, other.mRequiredPermissions) && mSuitabilityStatus == other.mSuitabilityStatus; } Loading @@ -1039,6 +1054,7 @@ public final class MediaRoute2Info implements Parcelable { mProviderId, mIsVisibilityRestricted, mAllowedPackages, mRequiredPermissions, mSuitabilityStatus); } Loading Loading @@ -1079,6 +1095,8 @@ public final class MediaRoute2Info implements Parcelable { .append(mIsVisibilityRestricted) .append(", allowedPackages=") .append(String.join(",", mAllowedPackages)) .append(", mRequiredPermissions=") .append(String.join(",", mRequiredPermissions)) .append(", suitabilityStatus=") .append(mSuitabilityStatus) .append(" }") Loading Loading @@ -1112,6 +1130,7 @@ public final class MediaRoute2Info implements Parcelable { dest.writeString(mProviderId); dest.writeBoolean(mIsVisibilityRestricted); dest.writeString8Array(mAllowedPackages.toArray(new String[0])); dest.writeString8Array(mRequiredPermissions.toArray(new String[0])); dest.writeInt(mSuitabilityStatus); } Loading Loading @@ -1260,6 +1279,7 @@ public final class MediaRoute2Info implements Parcelable { private String mProviderId; private boolean mIsVisibilityRestricted; private Set<String> mAllowedPackages; private Set<String> mRequiredPermissions; @SuitabilityStatus private int mSuitabilityStatus; /** Loading @@ -1285,6 +1305,7 @@ public final class MediaRoute2Info implements Parcelable { mDeduplicationIds = Set.of(); mAllowedPackages = Set.of(); mSuitabilityStatus = SUITABILITY_STATUS_SUITABLE_FOR_DEFAULT_TRANSFER; mRequiredPermissions = Set.of(); } /** Loading Loading @@ -1334,6 +1355,7 @@ public final class MediaRoute2Info implements Parcelable { mIsVisibilityRestricted = routeInfo.mIsVisibilityRestricted; mAllowedPackages = routeInfo.mAllowedPackages; mSuitabilityStatus = routeInfo.mSuitabilityStatus; mRequiredPermissions = routeInfo.mRequiredPermissions; } /** Loading Loading @@ -1565,6 +1587,7 @@ public final class MediaRoute2Info implements Parcelable { public Builder setVisibilityPublic() { mIsVisibilityRestricted = false; mAllowedPackages = Set.of(); mRequiredPermissions = Set.of(); return this; } Loading @@ -1588,6 +1611,19 @@ public final class MediaRoute2Info implements Parcelable { return this; } /** * Limits the visibility of this route to holders of a set of permissions. * * @param requiredPermissions the list of all permissions which must be held in order to * see this route. */ @NonNull @FlaggedApi(FLAG_ENABLE_ROUTE_VISIBILITY_CONTROL_API) public Builder setRequiredPermissions(@NonNull Set<String> requiredPermissions) { mRequiredPermissions = Set.copyOf(requiredPermissions); return this; } /** * Sets route suitability status. * Loading services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +23 −3 Original line number Diff line number Diff line Loading @@ -1144,6 +1144,7 @@ class MediaRouter2ServiceImpl { UserRecord userRecord = getOrCreateUserRecordLocked(userId); RouterRecord routerRecord = new RouterRecord( mContext, userRecord, router, uid, Loading Loading @@ -2063,6 +2064,7 @@ class MediaRouter2ServiceImpl { } final class RouterRecord implements IBinder.DeathRecipient { public final Context mContext; public final UserRecord mUserRecord; public final String mPackageName; public final List<Integer> mSelectRouteSequenceNumbers; Loading @@ -2081,6 +2083,7 @@ class MediaRouter2ServiceImpl { @Nullable public RouteListingPreference mRouteListingPreference; RouterRecord( Context context, UserRecord userRecord, IMediaRouter2 router, int uid, Loading @@ -2090,6 +2093,7 @@ class MediaRouter2ServiceImpl { boolean hasModifyAudioRoutingPermission, boolean hasMediaContentControlPermission, boolean hasMediaRoutingControl) { mContext = context; mUserRecord = userRecord; mPackageName = packageName; mSelectRouteSequenceNumbers = new ArrayList<>(); Loading Loading @@ -2331,18 +2335,34 @@ class MediaRouter2ServiceImpl { } /** * Returns a filtered copy of {@code routes} that contains only the routes that are {@link * MediaRoute2Info#isVisibleTo visible} to the router corresponding to this record. * Returns a filtered copy of {@code routes} that contains only the routes that are visible * to this RouterRecord. */ private List<MediaRoute2Info> getVisibleRoutes(@NonNull List<MediaRoute2Info> routes) { List<MediaRoute2Info> filteredRoutes = new ArrayList<>(); for (MediaRoute2Info route : routes) { if (route.isVisibleTo(mPackageName)) { if (route.isVisibleTo(mPackageName) && hasPermissionsToSeeRoute(route)) { filteredRoutes.add(route); } } return filteredRoutes; } /** * @return whether this RouterRecord has the required permissions to see the given route. */ private boolean hasPermissionsToSeeRoute(MediaRoute2Info route) { if (!Flags.enableRouteVisibilityControlApi()) { return true; } for (String permission : route.getRequiredPermissions()) { if (mContext.checkPermission(permission, mPid, mUid) != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } } final class ManagerRecord implements IBinder.DeathRecipient { Loading Loading
core/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -24861,6 +24861,7 @@ package android.media { method @Nullable public android.net.Uri getIconUri(); method @NonNull public String getId(); method @NonNull public CharSequence getName(); method @FlaggedApi("com.android.media.flags.enable_route_visibility_control_api") @NonNull public java.util.Set<java.lang.String> getRequiredPermissions(); method @FlaggedApi("com.android.media.flags.enable_built_in_speaker_route_suitability_statuses") public int getSuitabilityStatus(); method @FlaggedApi("com.android.media.flags.enable_mirroring_in_media_router_2") public int getSupportedRoutingTypes(); method public int getType(); Loading Loading @@ -24929,6 +24930,7 @@ package android.media { method @NonNull public android.media.MediaRoute2Info.Builder setDescription(@Nullable CharSequence); method @NonNull public android.media.MediaRoute2Info.Builder setExtras(@Nullable android.os.Bundle); method @NonNull public android.media.MediaRoute2Info.Builder setIconUri(@Nullable android.net.Uri); method @FlaggedApi("com.android.media.flags.enable_route_visibility_control_api") @NonNull public android.media.MediaRoute2Info.Builder setRequiredPermissions(@NonNull java.util.Set<java.lang.String>); method @FlaggedApi("com.android.media.flags.enable_built_in_speaker_route_suitability_statuses") @NonNull public android.media.MediaRoute2Info.Builder setSuitabilityStatus(int); method @FlaggedApi("com.android.media.flags.enable_mirroring_in_media_router_2") @NonNull public android.media.MediaRoute2Info.Builder setSupportedRoutingTypes(int); method @NonNull public android.media.MediaRoute2Info.Builder setType(int);
media/java/android/media/MediaRoute2Info.java +36 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static com.android.media.flags.Flags.FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_S import static com.android.media.flags.Flags.FLAG_ENABLE_MIRRORING_IN_MEDIA_ROUTER_2; import static com.android.media.flags.Flags.FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES; import static com.android.media.flags.Flags.FLAG_ENABLE_NEW_WIRED_MEDIA_ROUTE_2_INFO_TYPES; import static com.android.media.flags.Flags.FLAG_ENABLE_ROUTE_VISIBILITY_CONTROL_API; import android.annotation.FlaggedApi; import android.annotation.IntDef; Loading Loading @@ -616,6 +617,7 @@ public final class MediaRoute2Info implements Parcelable { private final String mProviderId; private final boolean mIsVisibilityRestricted; private final Set<String> mAllowedPackages; private final Set<String> mRequiredPermissions; @SuitabilityStatus private final int mSuitabilityStatus; MediaRoute2Info(@NonNull Builder builder) { Loading @@ -640,6 +642,7 @@ public final class MediaRoute2Info implements Parcelable { mIsVisibilityRestricted = builder.mIsVisibilityRestricted; mAllowedPackages = builder.mAllowedPackages; mSuitabilityStatus = builder.mSuitabilityStatus; mRequiredPermissions = Set.copyOf(builder.mRequiredPermissions); } MediaRoute2Info(@NonNull Parcel in) { Loading @@ -664,6 +667,7 @@ public final class MediaRoute2Info implements Parcelable { mProviderId = in.readString(); mIsVisibilityRestricted = in.readBoolean(); mAllowedPackages = Set.of(in.createString8Array()); mRequiredPermissions = Set.of(in.createString8Array()); mSuitabilityStatus = in.readInt(); } Loading Loading @@ -906,6 +910,15 @@ public final class MediaRoute2Info implements Parcelable { || mAllowedPackages.contains(packageName); } /** * @return the set of permissions which must be held to see this route */ @NonNull @FlaggedApi(FLAG_ENABLE_ROUTE_VISIBILITY_CONTROL_API) public Set<String> getRequiredPermissions() { return mRequiredPermissions; } /** * Returns whether this route's type can only be published by the system route provider. * Loading Loading @@ -977,6 +990,7 @@ public final class MediaRoute2Info implements Parcelable { pw.println(indent + "mIsVisibilityRestricted=" + mIsVisibilityRestricted); pw.println(indent + "mAllowedPackages=" + mAllowedPackages); pw.println(indent + "mSuitabilityStatus=" + mSuitabilityStatus); pw.println(indent + "mRequiredPermissions=" + mRequiredPermissions); } private void dumpVolume(@NonNull PrintWriter pw, @NonNull String prefix) { Loading Loading @@ -1013,6 +1027,7 @@ public final class MediaRoute2Info implements Parcelable { && Objects.equals(mProviderId, other.mProviderId) && (mIsVisibilityRestricted == other.mIsVisibilityRestricted) && Objects.equals(mAllowedPackages, other.mAllowedPackages) && Objects.equals(mRequiredPermissions, other.mRequiredPermissions) && mSuitabilityStatus == other.mSuitabilityStatus; } Loading @@ -1039,6 +1054,7 @@ public final class MediaRoute2Info implements Parcelable { mProviderId, mIsVisibilityRestricted, mAllowedPackages, mRequiredPermissions, mSuitabilityStatus); } Loading Loading @@ -1079,6 +1095,8 @@ public final class MediaRoute2Info implements Parcelable { .append(mIsVisibilityRestricted) .append(", allowedPackages=") .append(String.join(",", mAllowedPackages)) .append(", mRequiredPermissions=") .append(String.join(",", mRequiredPermissions)) .append(", suitabilityStatus=") .append(mSuitabilityStatus) .append(" }") Loading Loading @@ -1112,6 +1130,7 @@ public final class MediaRoute2Info implements Parcelable { dest.writeString(mProviderId); dest.writeBoolean(mIsVisibilityRestricted); dest.writeString8Array(mAllowedPackages.toArray(new String[0])); dest.writeString8Array(mRequiredPermissions.toArray(new String[0])); dest.writeInt(mSuitabilityStatus); } Loading Loading @@ -1260,6 +1279,7 @@ public final class MediaRoute2Info implements Parcelable { private String mProviderId; private boolean mIsVisibilityRestricted; private Set<String> mAllowedPackages; private Set<String> mRequiredPermissions; @SuitabilityStatus private int mSuitabilityStatus; /** Loading @@ -1285,6 +1305,7 @@ public final class MediaRoute2Info implements Parcelable { mDeduplicationIds = Set.of(); mAllowedPackages = Set.of(); mSuitabilityStatus = SUITABILITY_STATUS_SUITABLE_FOR_DEFAULT_TRANSFER; mRequiredPermissions = Set.of(); } /** Loading Loading @@ -1334,6 +1355,7 @@ public final class MediaRoute2Info implements Parcelable { mIsVisibilityRestricted = routeInfo.mIsVisibilityRestricted; mAllowedPackages = routeInfo.mAllowedPackages; mSuitabilityStatus = routeInfo.mSuitabilityStatus; mRequiredPermissions = routeInfo.mRequiredPermissions; } /** Loading Loading @@ -1565,6 +1587,7 @@ public final class MediaRoute2Info implements Parcelable { public Builder setVisibilityPublic() { mIsVisibilityRestricted = false; mAllowedPackages = Set.of(); mRequiredPermissions = Set.of(); return this; } Loading @@ -1588,6 +1611,19 @@ public final class MediaRoute2Info implements Parcelable { return this; } /** * Limits the visibility of this route to holders of a set of permissions. * * @param requiredPermissions the list of all permissions which must be held in order to * see this route. */ @NonNull @FlaggedApi(FLAG_ENABLE_ROUTE_VISIBILITY_CONTROL_API) public Builder setRequiredPermissions(@NonNull Set<String> requiredPermissions) { mRequiredPermissions = Set.copyOf(requiredPermissions); return this; } /** * Sets route suitability status. * Loading
services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +23 −3 Original line number Diff line number Diff line Loading @@ -1144,6 +1144,7 @@ class MediaRouter2ServiceImpl { UserRecord userRecord = getOrCreateUserRecordLocked(userId); RouterRecord routerRecord = new RouterRecord( mContext, userRecord, router, uid, Loading Loading @@ -2063,6 +2064,7 @@ class MediaRouter2ServiceImpl { } final class RouterRecord implements IBinder.DeathRecipient { public final Context mContext; public final UserRecord mUserRecord; public final String mPackageName; public final List<Integer> mSelectRouteSequenceNumbers; Loading @@ -2081,6 +2083,7 @@ class MediaRouter2ServiceImpl { @Nullable public RouteListingPreference mRouteListingPreference; RouterRecord( Context context, UserRecord userRecord, IMediaRouter2 router, int uid, Loading @@ -2090,6 +2093,7 @@ class MediaRouter2ServiceImpl { boolean hasModifyAudioRoutingPermission, boolean hasMediaContentControlPermission, boolean hasMediaRoutingControl) { mContext = context; mUserRecord = userRecord; mPackageName = packageName; mSelectRouteSequenceNumbers = new ArrayList<>(); Loading Loading @@ -2331,18 +2335,34 @@ class MediaRouter2ServiceImpl { } /** * Returns a filtered copy of {@code routes} that contains only the routes that are {@link * MediaRoute2Info#isVisibleTo visible} to the router corresponding to this record. * Returns a filtered copy of {@code routes} that contains only the routes that are visible * to this RouterRecord. */ private List<MediaRoute2Info> getVisibleRoutes(@NonNull List<MediaRoute2Info> routes) { List<MediaRoute2Info> filteredRoutes = new ArrayList<>(); for (MediaRoute2Info route : routes) { if (route.isVisibleTo(mPackageName)) { if (route.isVisibleTo(mPackageName) && hasPermissionsToSeeRoute(route)) { filteredRoutes.add(route); } } return filteredRoutes; } /** * @return whether this RouterRecord has the required permissions to see the given route. */ private boolean hasPermissionsToSeeRoute(MediaRoute2Info route) { if (!Flags.enableRouteVisibilityControlApi()) { return true; } for (String permission : route.getRequiredPermissions()) { if (mContext.checkPermission(permission, mPid, mUid) != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } } final class ManagerRecord implements IBinder.DeathRecipient { Loading