summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt2
-rw-r--r--media/java/android/media/MediaRoute2Info.java56
-rw-r--r--media/java/android/media/MediaRouter2Manager.java13
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java82
4 files changed, 127 insertions, 26 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 8e2d421c1ded..dd3d6eb0fcd8 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -23797,6 +23797,8 @@ 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 @NonNull public android.media.MediaRoute2Info.Builder setVisibilityPublic();
+ method @NonNull public android.media.MediaRoute2Info.Builder setVisibilityRestricted(@NonNull java.util.Set<java.lang.String>);
method @NonNull public android.media.MediaRoute2Info.Builder setVolume(int);
method @NonNull public android.media.MediaRoute2Info.Builder setVolumeHandling(int);
method @NonNull public android.media.MediaRoute2Info.Builder setVolumeMax(int);
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index e8648cca3934..1022d930906d 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -353,6 +353,8 @@ public final class MediaRoute2Info implements Parcelable {
final Set<String> mDeduplicationIds;
final Bundle mExtras;
final String mProviderId;
+ final boolean mIsVisibilityRestricted;
+ final Set<String> mAllowedPackages;
MediaRoute2Info(@NonNull Builder builder) {
mId = builder.mId;
@@ -372,6 +374,8 @@ public final class MediaRoute2Info implements Parcelable {
mDeduplicationIds = builder.mDeduplicationIds;
mExtras = builder.mExtras;
mProviderId = builder.mProviderId;
+ mIsVisibilityRestricted = builder.mIsVisibilityRestricted;
+ mAllowedPackages = builder.mAllowedPackages;
}
MediaRoute2Info(@NonNull Parcel in) {
@@ -393,6 +397,8 @@ public final class MediaRoute2Info implements Parcelable {
mDeduplicationIds = Set.of(in.readStringArray());
mExtras = in.readBundle();
mProviderId = in.readString();
+ mIsVisibilityRestricted = in.readBoolean();
+ mAllowedPackages = Set.of(in.createString8Array());
}
/**
@@ -628,6 +634,15 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
+ * Returns whether this route is visible to the package with the given name.
+ * @hide
+ */
+ public boolean isVisibleTo(String packageName) {
+ return !mIsVisibilityRestricted || getPackageName().equals(packageName)
+ || mAllowedPackages.contains(packageName);
+ }
+
+ /**
* Dumps the current state of the object to the given {@code pw} as a human-readable string.
*
* <p> Used in the context of dumpsys. </p>
@@ -655,6 +670,8 @@ public final class MediaRoute2Info implements Parcelable {
pw.println(indent + "mDeduplicationIds=" + mDeduplicationIds);
pw.println(indent + "mExtras=" + mExtras);
pw.println(indent + "mProviderId=" + mProviderId);
+ pw.println(indent + "mIsVisibilityRestricted=" + mIsVisibilityRestricted);
+ pw.println(indent + "mAllowedPackages=" + mAllowedPackages);
}
private void dumpVolume(@NonNull PrintWriter pw, @NonNull String prefix) {
@@ -705,7 +722,9 @@ public final class MediaRoute2Info implements Parcelable {
&& (mVolume == other.mVolume)
&& Objects.equals(mAddress, other.mAddress)
&& Objects.equals(mDeduplicationIds, other.mDeduplicationIds)
- && Objects.equals(mProviderId, other.mProviderId);
+ && Objects.equals(mProviderId, other.mProviderId)
+ && (mIsVisibilityRestricted == other.mIsVisibilityRestricted)
+ && Objects.equals(mAllowedPackages, other.mAllowedPackages);
}
@Override
@@ -713,7 +732,8 @@ public final class MediaRoute2Info implements Parcelable {
// Note: mExtras is not included.
return Objects.hash(mId, mName, mFeatures, mType, mIsSystem, mIconUri, mDescription,
mConnectionState, mClientPackageName, mPackageName, mVolumeHandling, mVolumeMax,
- mVolume, mAddress, mDeduplicationIds, mProviderId);
+ mVolume, mAddress, mDeduplicationIds, mProviderId, mIsVisibilityRestricted,
+ mAllowedPackages);
}
@Override
@@ -733,6 +753,8 @@ public final class MediaRoute2Info implements Parcelable {
.append(", volume=").append(getVolume())
.append(", deduplicationIds=").append(String.join(",", getDeduplicationIds()))
.append(", providerId=").append(getProviderId())
+ .append(", isVisibilityRestricted=").append(mIsVisibilityRestricted)
+ .append(", allowedPackages=").append(String.join(",", mAllowedPackages))
.append(" }");
return result.toString();
}
@@ -761,6 +783,8 @@ public final class MediaRoute2Info implements Parcelable {
dest.writeStringArray(mDeduplicationIds.toArray(new String[mDeduplicationIds.size()]));
dest.writeBundle(mExtras);
dest.writeString(mProviderId);
+ dest.writeBoolean(mIsVisibilityRestricted);
+ dest.writeString8Array(mAllowedPackages.toArray(new String[0]));
}
/**
@@ -787,6 +811,8 @@ public final class MediaRoute2Info implements Parcelable {
Set<String> mDeduplicationIds;
Bundle mExtras;
String mProviderId;
+ boolean mIsVisibilityRestricted;
+ Set<String> mAllowedPackages;
/**
* Constructor for builder to create {@link MediaRoute2Info}.
@@ -809,6 +835,7 @@ public final class MediaRoute2Info implements Parcelable {
mName = name;
mFeatures = new ArrayList<>();
mDeduplicationIds = Set.of();
+ mAllowedPackages = Set.of();
}
/**
@@ -854,6 +881,8 @@ public final class MediaRoute2Info implements Parcelable {
mExtras = new Bundle(routeInfo.mExtras);
}
mProviderId = routeInfo.mProviderId;
+ mIsVisibilityRestricted = routeInfo.mIsVisibilityRestricted;
+ mAllowedPackages = routeInfo.mAllowedPackages;
}
/**
@@ -1057,6 +1086,29 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
+ * Sets the visibility of this route to public. This is the default
+ * visibility for routes that are public to all other apps.
+ */
+ @NonNull
+ public Builder setVisibilityPublic() {
+ mIsVisibilityRestricted = false;
+ mAllowedPackages = Set.of();
+ return this;
+ }
+
+ /**
+ * Sets the visibility of this route to restricted. This means that the
+ * route is only visible to a set of package name.
+ * @param allowedPackages set of package names which are allowed to see this route.
+ */
+ @NonNull
+ public Builder setVisibilityRestricted(@NonNull Set<String> allowedPackages) {
+ mIsVisibilityRestricted = true;
+ mAllowedPackages = Set.copyOf(allowedPackages);
+ return this;
+ }
+
+ /**
* Builds the {@link MediaRoute2Info media route info}.
*
* @throws IllegalArgumentException if no features are added.
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index aea6bcb8f89f..3abfc6297b0b 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -247,7 +247,6 @@ public final class MediaRouter2Manager {
return getTransferableRoutes(sessions.get(sessions.size() - 1));
}
-
/**
* Gets available routes for the given routing session.
* The returned routes can be passed to
@@ -313,9 +312,15 @@ public final class MediaRouter2Manager {
mDiscoveryPreferenceMap.getOrDefault(packageName, RouteDiscoveryPreference.EMPTY);
for (MediaRoute2Info route : getSortedRoutes(discoveryPreference)) {
- if (sessionInfo.getTransferableRoutes().contains(route.getId())
- || (includeSelectedRoutes
- && sessionInfo.getSelectedRoutes().contains(route.getId()))) {
+ if (!route.isVisibleTo(packageName)) {
+ continue;
+ }
+ boolean transferableRoutesContainRoute =
+ sessionInfo.getTransferableRoutes().contains(route.getId());
+ boolean selectedRoutesContainRoute =
+ sessionInfo.getSelectedRoutes().contains(route.getId());
+ if (transferableRoutesContainRoute
+ || (includeSelectedRoutes && selectedRoutesContainRoute)) {
routes.add(route);
continue;
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 90d75691c0e8..cde4ea9db1b0 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -1642,7 +1642,7 @@ class MediaRouter2ServiceImpl {
* <p>This list contains all routes exposed by route providers. This includes routes from
* both system route providers and user route providers.
*
- * <p>See {@link #getRouters(boolean hasModifyAudioRoutingPermission)}.
+ * <p>See {@link #getRouterRecords(boolean hasModifyAudioRoutingPermission)}.
*/
private final Map<String, MediaRoute2Info> mLastNotifiedRoutesToPrivilegedRouters =
new ArrayMap<>();
@@ -1912,9 +1912,10 @@ class MediaRouter2ServiceImpl {
if (!hasAddedOrModifiedRoutes && !hasRemovedRoutes) {
return;
}
-
- List<IMediaRouter2> routersWithModifyAudioRoutingPermission = getRouters(true);
- List<IMediaRouter2> routersWithoutModifyAudioRoutingPermission = getRouters(false);
+ List<RouterRecord> routerRecordsWithModifyAudioRoutingPermission =
+ getRouterRecords(true);
+ List<RouterRecord> routerRecordsWithoutModifyAudioRoutingPermission =
+ getRouterRecords(false);
List<IMediaRouter2Manager> managers = getManagers();
// Managers receive all provider updates with all routes.
@@ -1923,22 +1924,22 @@ class MediaRouter2ServiceImpl {
// Routers with modify audio permission (usually system routers) receive all provider
// updates with all routes.
- notifyRoutesUpdatedToRouters(
- routersWithModifyAudioRoutingPermission,
+ notifyRoutesUpdatedToRouterRecords(
+ routerRecordsWithModifyAudioRoutingPermission,
new ArrayList<>(mLastNotifiedRoutesToPrivilegedRouters.values()));
if (!isSystemProvider) {
// Regular routers receive updates from all non-system providers with all non-system
// routes.
- notifyRoutesUpdatedToRouters(
- routersWithoutModifyAudioRoutingPermission,
+ notifyRoutesUpdatedToRouterRecords(
+ routerRecordsWithoutModifyAudioRoutingPermission,
new ArrayList<>(mLastNotifiedRoutesToNonPrivilegedRouters.values()));
} else if (hasAddedOrModifiedRoutes) {
// On system provider updates, regular routers receive the updated default route.
// This is the only system route they should receive.
mLastNotifiedRoutesToNonPrivilegedRouters.put(defaultRoute.getId(), defaultRoute);
- notifyRoutesUpdatedToRouters(
- routersWithoutModifyAudioRoutingPermission,
+ notifyRoutesUpdatedToRouterRecords(
+ routerRecordsWithoutModifyAudioRoutingPermission,
new ArrayList<>(mLastNotifiedRoutesToNonPrivilegedRouters.values()));
}
}
@@ -2207,8 +2208,8 @@ class MediaRouter2ServiceImpl {
if (mServiceRef.get() == null) {
return;
}
- notifySessionInfoChangedToRouters(getRouters(true), sessionInfo);
- notifySessionInfoChangedToRouters(getRouters(false),
+ notifySessionInfoChangedToRouters(getRouterRecords(true), sessionInfo);
+ notifySessionInfoChangedToRouters(getRouterRecords(false),
mSystemProvider.getDefaultSessionInfo());
return;
}
@@ -2219,7 +2220,7 @@ class MediaRouter2ServiceImpl {
+ sessionInfo);
return;
}
- notifySessionInfoChangedToRouters(Arrays.asList(routerRecord.mRouter), sessionInfo);
+ notifySessionInfoChangedToRouters(Arrays.asList(routerRecord), sessionInfo);
}
private void onSessionReleasedOnHandler(@NonNull MediaRoute2Provider provider,
@@ -2332,6 +2333,7 @@ class MediaRouter2ServiceImpl {
== routerRecord.mHasModifyAudioRoutingPermission) {
routers.add(routerRecord.mRouter);
}
+ routers.add(routerRecord.mRouter);
}
}
return routers;
@@ -2361,6 +2363,23 @@ class MediaRouter2ServiceImpl {
}
}
+ private List<RouterRecord> getRouterRecords(boolean hasModifyAudioRoutingPermission) {
+ MediaRouter2ServiceImpl service = mServiceRef.get();
+ List<RouterRecord> routerRecords = new ArrayList<>();
+ if (service == null) {
+ return routerRecords;
+ }
+ synchronized (service.mLock) {
+ for (RouterRecord routerRecord : mUserRecord.mRouterRecords) {
+ if (hasModifyAudioRoutingPermission
+ == routerRecord.mHasModifyAudioRoutingPermission) {
+ routerRecords.add(routerRecord);
+ }
+ }
+ return routerRecords;
+ }
+ }
+
private List<ManagerRecord> getManagerRecords() {
MediaRouter2ServiceImpl service = mServiceRef.get();
if (service == null) {
@@ -2411,22 +2430,45 @@ class MediaRouter2ServiceImpl {
}
}
- private void notifyRoutesUpdatedToRouters(
- @NonNull List<IMediaRouter2> routers, @NonNull List<MediaRoute2Info> routes) {
- for (IMediaRouter2 router : routers) {
+ private static void notifyRoutesUpdatedToRouterRecords(
+ @NonNull List<RouterRecord> routerRecords,
+ @NonNull List<MediaRoute2Info> routes) {
+ for (RouterRecord routerRecord: routerRecords) {
+ List<MediaRoute2Info> filteredRoutes = getFilteredRoutesForPackageName(routes,
+ routerRecord.mPackageName);
try {
- router.notifyRoutesUpdated(routes);
+ routerRecord.mRouter.notifyRoutesUpdated(filteredRoutes);
} catch (RemoteException ex) {
Slog.w(TAG, "Failed to notify routes updated. Router probably died.", ex);
}
}
}
+ /**
+ * Filters list of routes to return only public routes or routes provided by
+ * the same package name or routes containing this package name in its allow list.
+ * @param routes initial list of routes to be filtered.
+ * @param packageName router's package name to filter routes for it.
+ * @return only the routes that this package name is allowed to see.
+ */
+ private static List<MediaRoute2Info> getFilteredRoutesForPackageName(
+ @NonNull List<MediaRoute2Info> routes,
+ @NonNull String packageName) {
+ List<MediaRoute2Info> filteredRoutes = new ArrayList<>();
+ for (MediaRoute2Info route : routes) {
+ if (route.isVisibleTo(packageName)) {
+ filteredRoutes.add(route);
+ }
+ }
+ return filteredRoutes;
+ }
+
private void notifySessionInfoChangedToRouters(
- @NonNull List<IMediaRouter2> routers, @NonNull RoutingSessionInfo sessionInfo) {
- for (IMediaRouter2 router : routers) {
+ @NonNull List<RouterRecord> routerRecords,
+ @NonNull RoutingSessionInfo sessionInfo) {
+ for (RouterRecord routerRecord : routerRecords) {
try {
- router.notifySessionInfoChanged(sessionInfo);
+ routerRecord.mRouter.notifySessionInfoChanged(sessionInfo);
} catch (RemoteException ex) {
Slog.w(TAG, "Failed to notify session info changed. Router probably died.", ex);
}