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

Commit da20c5b3 authored by Antony Sargent's avatar Antony Sargent
Browse files

Add list-based API for media route visibility by permissions

Bug: 367799834
Flag: com.android.media.flags.enable_route_visibility_control_api
Test: MediaRoute2InfoTest and MediaRouter2HostSideTest
Change-Id: I0f6c7ee3590734b2f3884f9aed54eaaab4e71cec
parent 58705529
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -24861,7 +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_route_visibility_control_api") @NonNull public java.util.List<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();
@@ -24931,6 +24931,7 @@ package android.media {
    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_route_visibility_control_api") @NonNull public android.media.MediaRoute2Info.Builder setRequiredPermissions(@NonNull java.util.List<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);
+40 −11
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Describes the properties of a route.
@@ -617,7 +618,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;
    private final List<Set<String>> mRequiredPermissions;
    @SuitabilityStatus private final int mSuitabilityStatus;

    MediaRoute2Info(@NonNull Builder builder) {
@@ -642,7 +643,7 @@ public final class MediaRoute2Info implements Parcelable {
        mIsVisibilityRestricted = builder.mIsVisibilityRestricted;
        mAllowedPackages = builder.mAllowedPackages;
        mSuitabilityStatus = builder.mSuitabilityStatus;
        mRequiredPermissions = Set.copyOf(builder.mRequiredPermissions);
        mRequiredPermissions = List.copyOf(builder.mRequiredPermissions);
    }

    MediaRoute2Info(@NonNull Parcel in) {
@@ -667,7 +668,12 @@ public final class MediaRoute2Info implements Parcelable {
        mProviderId = in.readString();
        mIsVisibilityRestricted = in.readBoolean();
        mAllowedPackages = Set.of(in.createString8Array());
        mRequiredPermissions = Set.of(in.createString8Array());
        ArrayList<Set<String>> requiredPermissions = new ArrayList<>();
        int numRequiredPermissionSets = in.readInt();
        for (int i = 0; i < numRequiredPermissionSets; i++) {
            requiredPermissions.add(Set.of(in.createString8Array()));
        }
        mRequiredPermissions = List.copyOf(requiredPermissions); // Use copyOf to make it immutable.
        mSuitabilityStatus = in.readInt();
    }

@@ -911,11 +917,12 @@ public final class MediaRoute2Info implements Parcelable {
    }

    /**
     * @return the set of permissions which must be held to see this route
     * @return a list of permission sets - all the permissions in at least one of these sets must be
     * held to see this route.
     */
    @NonNull
    @FlaggedApi(FLAG_ENABLE_ROUTE_VISIBILITY_CONTROL_API)
    public Set<String> getRequiredPermissions() {
    public List<Set<String>> getRequiredPermissions() {
        return mRequiredPermissions;
    }

@@ -1096,7 +1103,8 @@ public final class MediaRoute2Info implements Parcelable {
                .append(", allowedPackages=")
                .append(String.join(",", mAllowedPackages))
                .append(", mRequiredPermissions=")
                .append(String.join(",", mRequiredPermissions))
                .append(mRequiredPermissions.stream().map(set -> String.join(",", set)).collect(
                                Collectors.joining("),(", "(", ")")))
                .append(", suitabilityStatus=")
                .append(mSuitabilityStatus)
                .append(" }")
@@ -1130,7 +1138,10 @@ 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(mRequiredPermissions.size());
        for (Set<String> permissionSet : mRequiredPermissions) {
            dest.writeString8Array(permissionSet.toArray(new String[0]));
        }
        dest.writeInt(mSuitabilityStatus);
    }

@@ -1279,7 +1290,7 @@ public final class MediaRoute2Info implements Parcelable {
        private String mProviderId;
        private boolean mIsVisibilityRestricted;
        private Set<String> mAllowedPackages;
        private Set<String> mRequiredPermissions;
        private List<Set<String>> mRequiredPermissions;
        @SuitabilityStatus private int mSuitabilityStatus;

        /**
@@ -1305,7 +1316,7 @@ public final class MediaRoute2Info implements Parcelable {
            mDeduplicationIds = Set.of();
            mAllowedPackages = Set.of();
            mSuitabilityStatus = SUITABILITY_STATUS_SUITABLE_FOR_DEFAULT_TRANSFER;
            mRequiredPermissions = Set.of();
            mRequiredPermissions = List.of();
        }

        /**
@@ -1587,7 +1598,7 @@ public final class MediaRoute2Info implements Parcelable {
        public Builder setVisibilityPublic() {
            mIsVisibilityRestricted = false;
            mAllowedPackages = Set.of();
            mRequiredPermissions = Set.of();
            mRequiredPermissions = List.of();
            return this;
        }

@@ -1614,13 +1625,31 @@ public final class MediaRoute2Info implements Parcelable {
        /**
         * Limits the visibility of this route to holders of a set of permissions.
         *
         * <p>Calls to this method override any previous calls of
         * {@link #setRequiredPermissions(Set)} or {@link #setRequiredPermissions(List)}.
         *
         * @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 setRequiredPermissions(List.of(requiredPermissions));
        }

        /**
         * Limits the visibility of this route to holders of one of a set of permissions.
         *
         * <p>Calls to this method override any previous calls of
         * {@link #setRequiredPermissions(Set)} or {@link #setRequiredPermissions(List)}.
         *
         * @param requiresOneOf a list of Sets of permissions. Holding all permissions in at least
         *                      one of the Sets is required for the route to be visible.
         */
        @NonNull
        @FlaggedApi(FLAG_ENABLE_ROUTE_VISIBILITY_CONTROL_API)
        public Builder setRequiredPermissions(@NonNull List<Set<String>> requiresOneOf) {
            mRequiredPermissions = List.copyOf(requiresOneOf);
            return this;
        }

+16 −5
Original line number Diff line number Diff line
@@ -2355,15 +2355,26 @@ class MediaRouter2ServiceImpl {
            if (!Flags.enableRouteVisibilityControlApi()) {
                return true;
            }
            for (String permission : route.getRequiredPermissions()) {
            List<Set<String>> permissionSets = route.getRequiredPermissions();
            if (permissionSets.isEmpty()) {
                return true;
            }
            for (Set<String> permissionSet : permissionSets) {
                boolean hasAllInSet = true;
                for (String permission : permissionSet) {
                    if (mContext.checkPermission(permission, mPid, mUid)
                            != PackageManager.PERMISSION_GRANTED) {
                    return false;
                        hasAllInSet = false;
                        break;
                    }
                }
                if (hasAllInSet) {
                    return true;
                }
            }
            return false;
        }
    }

    final class ManagerRecord implements IBinder.DeathRecipient {
        @NonNull public final UserRecord mUserRecord;