Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4c6aad8 authored by Bishoy Gendy's avatar Bishoy Gendy Committed by Android (Google) Code Review
Browse files

Merge "Add route visibility support in platform"

parents d528f81e 41cf690b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
+54 −2
Original line number Diff line number Diff line
@@ -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());
    }

    /**
@@ -627,6 +633,15 @@ public final class MediaRoute2Info implements Parcelable {
        return true;
    }

    /**
     * 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.
     *
@@ -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;
        }

        /**
@@ -1056,6 +1085,29 @@ public final class MediaRoute2Info implements Parcelable {
            return this;
        }

        /**
         * 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}.
         *
+9 −4
Original line number Diff line number Diff line
@@ -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;
            }
+62 −20
Original line number Diff line number Diff line
@@ -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);
                }