diff options
| -rw-r--r-- | core/api/current.txt | 2 | ||||
| -rw-r--r-- | media/java/android/media/MediaRoute2Info.java | 56 | ||||
| -rw-r--r-- | media/java/android/media/MediaRouter2Manager.java | 13 | ||||
| -rw-r--r-- | services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java | 82 |
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); } |