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

Commit 91c792e4 authored by Kyunglyul Hyun's avatar Kyunglyul Hyun
Browse files

MediaRouter: Introduce discovery request

Providers are notified of change of discovery request
to respond properly.

Whenever a media app registers a callback it should provide
discovery request which includes route types and a way to scan.

MediaRouter combines all discovery request into a single request
and sends it to the media router service, which combines requests
from all clients and notifies provider of the combined request.

This CL also changes control category as route type.

Bug: 139033746
Test: atest mediaroutertest
Change-Id: I5ca37683ae0761ff587c1c920e32fd6d768a2cd3
parent 9cb12384
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ import android.media.IMediaRoute2ProviderClient;
oneway interface IMediaRoute2Provider {
    void setClient(IMediaRoute2ProviderClient client);
    void requestCreateSession(String packageName, String routeId,
            String controlCategory, long requestId);
            String routeType, long requestId);
    void releaseSession(int sessionId);

    void selectRoute(int sessionId, String routeId);
+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ import android.media.MediaRoute2Info;
 */
oneway interface IMediaRouter2Manager {
    void notifyRouteSelected(String packageName, in MediaRoute2Info route);
    void notifyControlCategoriesChanged(String packageName, in List<String> categories);
    void notifyRouteTypesChanged(String packageName, in List<String> routeTypes);
    void notifyRoutesAdded(in List<MediaRoute2Info> routes);
    void notifyRoutesRemoved(in List<MediaRoute2Info> routes);
    void notifyRoutesChanged(in List<MediaRoute2Info> routes);
+3 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.media.IMediaRouter2Manager;
import android.media.IMediaRouterClient;
import android.media.MediaRoute2Info;
import android.media.MediaRouterClientState;
import android.media.RouteDiscoveryRequest;
import android.media.RouteSessionInfo;

/**
@@ -51,8 +52,8 @@ interface IMediaRouterService {
    void requestUpdateVolume2(IMediaRouter2Client client, in MediaRoute2Info route, int direction);

    void requestCreateSession(IMediaRouter2Client client, in MediaRoute2Info route,
            String controlCategory, int requestId);
    void setControlCategories(IMediaRouter2Client client, in List<String> categories);
            String routeType, int requestId);
    void setDiscoveryRequest2(IMediaRouter2Client client, in RouteDiscoveryRequest request);
    void selectRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
    void deselectRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
    void transferToRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
+34 −49
Original line number Diff line number Diff line
@@ -83,12 +83,14 @@ public final class MediaRoute2Info implements Parcelable {
     * controlled from this object. An example of fixed playback volume is a remote player,
     * playing over HDMI where the user prefers to control the volume on the HDMI sink, rather
     * than attenuate at the source.
     *
     * @see #getVolumeHandling()
     */
    public static final int PLAYBACK_VOLUME_FIXED = 0;
    /**
     * Playback information indicating the playback volume is variable and can be controlled
     * from this object.
     *
     * @see #getVolumeHandling()
     */
    public static final int PLAYBACK_VOLUME_VARIABLE = 1;
@@ -148,7 +150,7 @@ public final class MediaRoute2Info implements Parcelable {
    @Nullable
    final String mClientPackageName;
    @NonNull
    final List<String> mSupportedCategories;
    final List<String> mRouteTypes;
    final int mVolume;
    final int mVolumeMax;
    final int mVolumeHandling;
@@ -164,7 +166,7 @@ public final class MediaRoute2Info implements Parcelable {
        mConnectionState = builder.mConnectionState;
        mIconUri = builder.mIconUri;
        mClientPackageName = builder.mClientPackageName;
        mSupportedCategories = builder.mSupportedCategories;
        mRouteTypes = builder.mRouteTypes;
        mVolume = builder.mVolume;
        mVolumeMax = builder.mVolumeMax;
        mVolumeHandling = builder.mVolumeHandling;
@@ -180,7 +182,7 @@ public final class MediaRoute2Info implements Parcelable {
        mConnectionState = in.readInt();
        mIconUri = in.readParcelable(null);
        mClientPackageName = in.readString();
        mSupportedCategories = in.createStringArrayList();
        mRouteTypes = in.createStringArrayList();
        mVolume = in.readInt();
        mVolumeMax = in.readInt();
        mVolumeHandling = in.readInt();
@@ -226,7 +228,7 @@ public final class MediaRoute2Info implements Parcelable {
                && (mConnectionState == other.mConnectionState)
                && Objects.equals(mIconUri, other.mIconUri)
                && Objects.equals(mClientPackageName, other.mClientPackageName)
                && Objects.equals(mSupportedCategories, other.mSupportedCategories)
                && Objects.equals(mRouteTypes, other.mRouteTypes)
                && (mVolume == other.mVolume)
                && (mVolumeMax == other.mVolumeMax)
                && (mVolumeHandling == other.mVolumeHandling)
@@ -238,7 +240,7 @@ public final class MediaRoute2Info implements Parcelable {
    @Override
    public int hashCode() {
        return Objects.hash(mId, mName, mDescription, mConnectionState, mIconUri,
                mSupportedCategories, mVolume, mVolumeMax, mVolumeHandling, mDeviceType);
                mRouteTypes, mVolume, mVolumeMax, mVolumeHandling, mDeviceType);
    }

    /**
@@ -327,8 +329,8 @@ public final class MediaRoute2Info implements Parcelable {
     * Gets the supported categories of the route.
     */
    @NonNull
    public List<String> getSupportedCategories() {
        return mSupportedCategories;
    public List<String> getRouteTypes() {
        return mRouteTypes;
    }

    //TODO: once device types are confirmed, reflect those into the comment.
@@ -372,32 +374,15 @@ public final class MediaRoute2Info implements Parcelable {
    }

    /**
     * Returns if the route supports the specified control category
     *
     * @param controlCategory control category to consider
     * @return true if the route supports at the category
     */
    public boolean supportsControlCategory(@NonNull String controlCategory) {
        Objects.requireNonNull(controlCategory, "control category must not be null");
        for (String supportedCategory : getSupportedCategories()) {
            if (TextUtils.equals(controlCategory, supportedCategory)) {
                return true;
            }
        }
        return false;
    }

    //TODO: Move this if we re-define control category / selector things.
    /**
     * Returns if the route supports at least one of the specified control categories
     * Returns if the route contains at least one of the specified route types.
     *
     * @param controlCategories the list of control categories to consider
     * @return true if the route supports at least one category
     * @param routeTypes the list of route types to consider
     * @return true if the route contains at least one type in the list
     */
    public boolean supportsControlCategories(@NonNull Collection<String> controlCategories) {
        Objects.requireNonNull(controlCategories, "control categories must not be null");
        for (String controlCategory : controlCategories) {
            if (supportsControlCategory(controlCategory)) {
    public boolean containsRouteTypes(@NonNull Collection<String> routeTypes) {
        Objects.requireNonNull(routeTypes, "routeTypes must not be null");
        for (String routeType : routeTypes) {
            if (getRouteTypes().contains(routeType)) {
                return true;
            }
        }
@@ -418,7 +403,7 @@ public final class MediaRoute2Info implements Parcelable {
        dest.writeInt(mConnectionState);
        dest.writeParcelable(mIconUri, flags);
        dest.writeString(mClientPackageName);
        dest.writeStringList(mSupportedCategories);
        dest.writeStringList(mRouteTypes);
        dest.writeInt(mVolume);
        dest.writeInt(mVolumeMax);
        dest.writeInt(mVolumeHandling);
@@ -456,7 +441,7 @@ public final class MediaRoute2Info implements Parcelable {
        int mConnectionState;
        Uri mIconUri;
        String mClientPackageName;
        List<String> mSupportedCategories;
        List<String> mRouteTypes;
        int mVolume;
        int mVolumeMax;
        int mVolumeHandling = PLAYBACK_VOLUME_FIXED;
@@ -467,7 +452,7 @@ public final class MediaRoute2Info implements Parcelable {
        public Builder(@NonNull String id, @NonNull CharSequence name) {
            setId(id);
            setName(name);
            mSupportedCategories = new ArrayList<>();
            mRouteTypes = new ArrayList<>();
        }

        public Builder(@NonNull MediaRoute2Info routeInfo) {
@@ -484,7 +469,7 @@ public final class MediaRoute2Info implements Parcelable {
            mConnectionState = routeInfo.mConnectionState;
            mIconUri = routeInfo.mIconUri;
            setClientPackageName(routeInfo.mClientPackageName);
            setSupportedCategories(routeInfo.mSupportedCategories);
            setRouteTypes(routeInfo.mRouteTypes);
            setVolume(routeInfo.mVolume);
            setVolumeMax(routeInfo.mVolumeMax);
            setVolumeHandling(routeInfo.mVolumeHandling);
@@ -589,35 +574,35 @@ public final class MediaRoute2Info implements Parcelable {
        }

        /**
         * Sets the supported categories of the route.
         * Sets the types of the route.
         */
        @NonNull
        public Builder setSupportedCategories(@NonNull Collection<String> categories) {
            mSupportedCategories = new ArrayList<>();
            return addSupportedCategories(categories);
        public Builder setRouteTypes(@NonNull Collection<String> routeTypes) {
            mRouteTypes = new ArrayList<>();
            return addRouteTypes(routeTypes);
        }

        /**
         * Adds supported categories for the route.
         * Adds types for the route.
         */
        @NonNull
        public Builder addSupportedCategories(@NonNull Collection<String> categories) {
            Objects.requireNonNull(categories, "categories must not be null");
            for (String category: categories) {
                addSupportedCategory(category);
        public Builder addRouteTypes(@NonNull Collection<String> routeTypes) {
            Objects.requireNonNull(routeTypes, "routeTypes must not be null");
            for (String routeType: routeTypes) {
                addRouteType(routeType);
            }
            return this;
        }

        /**
         * Add a supported category for the route.
         * Add a type for the route.
         */
        @NonNull
        public Builder addSupportedCategory(@NonNull String category) {
            if (TextUtils.isEmpty(category)) {
                throw new IllegalArgumentException("category must not be null or empty");
        public Builder addRouteType(@NonNull String routeType) {
            if (TextUtils.isEmpty(routeType)) {
                throw new IllegalArgumentException("routeType must not be null or empty");
            }
            mSupportedCategories.add(category);
            mRouteTypes.add(routeType);
            return this;
        }

+23 −4
Original line number Diff line number Diff line
@@ -246,11 +246,11 @@ public abstract class MediaRoute2ProviderService extends Service {
     *
     * @param packageName the package name of the application that selected the route
     * @param routeId the id of the route initially being connected
     * @param controlCategory the control category of the new session
     * @param routeType the route type of the new session
     * @param requestId the id of this session creation request
     */
    public abstract void onCreateSession(@NonNull String packageName, @NonNull String routeId,
            @NonNull String controlCategory, long requestId);
            @NonNull String routeType, long requestId);

    /**
     * Called when a session is about to be destroyed.
@@ -300,6 +300,25 @@ public abstract class MediaRoute2ProviderService extends Service {
     */
    public abstract void onTransferToRoute(int sessionId, @NonNull String routeId);

    /**
     * Called when the {@link RouteDiscoveryRequest discovery request} has changed.
     * <p>
     * Whenever an application registers a {@link MediaRouter2.RouteCallback callback},
     * it also provides a discovery request to specify types of routes that it is interested in.
     * The media router combines all of these discovery request into a single discovery request
     * and notifies each provider.
     * </p><p>
     * The provider should examine {@link RouteDiscoveryRequest#getRouteTypes() route types}
     * in the discovery request to determine what kind of routes it should try to discover
     * and whether it should perform active or passive scans. In many cases, the provider may be
     * able to save power by not performing any scans when the request doesn't have any matching
     * route types.
     * </p>
     *
     * @param request the new discovery request
     */
    public void onDiscoveryRequestChanged(@NonNull RouteDiscoveryRequest request) {}

    /**
     * Updates provider info and publishes routes and session info.
     */
@@ -357,12 +376,12 @@ public abstract class MediaRoute2ProviderService extends Service {

        @Override
        public void requestCreateSession(String packageName, String routeId,
                String controlCategory, long requestId) {
                String routeType, long requestId) {
            if (!checkCallerisSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onCreateSession,
                    MediaRoute2ProviderService.this, packageName, routeId, controlCategory,
                    MediaRoute2ProviderService.this, packageName, routeId, routeType,
                    requestId));
        }
        @Override
Loading