summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt2
-rw-r--r--media/java/android/media/MediaRoute2Info.java36
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java26
3 files changed, 61 insertions, 3 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 1d11cac13197..6fb319b68f28 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -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();
@@ -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);
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index d433ec876af9..dd5067a3ee67 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -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;
@@ -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) {
@@ -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) {
@@ -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();
}
@@ -907,6 +911,15 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
+ * @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.
*
* @see #isSystemRoute()
@@ -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) {
@@ -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;
}
@@ -1039,6 +1054,7 @@ public final class MediaRoute2Info implements Parcelable {
mProviderId,
mIsVisibilityRestricted,
mAllowedPackages,
+ mRequiredPermissions,
mSuitabilityStatus);
}
@@ -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(" }")
@@ -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);
}
@@ -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;
/**
@@ -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();
}
/**
@@ -1334,6 +1355,7 @@ public final class MediaRoute2Info implements Parcelable {
mIsVisibilityRestricted = routeInfo.mIsVisibilityRestricted;
mAllowedPackages = routeInfo.mAllowedPackages;
mSuitabilityStatus = routeInfo.mSuitabilityStatus;
+ mRequiredPermissions = routeInfo.mRequiredPermissions;
}
/**
@@ -1565,6 +1587,7 @@ public final class MediaRoute2Info implements Parcelable {
public Builder setVisibilityPublic() {
mIsVisibilityRestricted = false;
mAllowedPackages = Set.of();
+ mRequiredPermissions = Set.of();
return this;
}
@@ -1589,6 +1612,19 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
+ * 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.
*
* <p>The default value is {@link
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 2d2d2584edfd..1abe5261e3e3 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -1144,6 +1144,7 @@ class MediaRouter2ServiceImpl {
UserRecord userRecord = getOrCreateUserRecordLocked(userId);
RouterRecord routerRecord =
new RouterRecord(
+ mContext,
userRecord,
router,
uid,
@@ -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;
@@ -2081,6 +2083,7 @@ class MediaRouter2ServiceImpl {
@Nullable public RouteListingPreference mRouteListingPreference;
RouterRecord(
+ Context context,
UserRecord userRecord,
IMediaRouter2 router,
int uid,
@@ -2090,6 +2093,7 @@ class MediaRouter2ServiceImpl {
boolean hasModifyAudioRoutingPermission,
boolean hasMediaContentControlPermission,
boolean hasMediaRoutingControl) {
+ mContext = context;
mUserRecord = userRecord;
mPackageName = packageName;
mSelectRouteSequenceNumbers = new ArrayList<>();
@@ -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 {