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

Commit 661abb54 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add a new API to let media routes have visibility restricted by permissions" into main

parents 82cfb600 8b52b29b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
+36 −0
Original line number Diff line number Diff line
@@ -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();
    }

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

@@ -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.
         *
+23 −3
Original line number Diff line number Diff line
@@ -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 {