diff options
Diffstat (limited to 'com/android/support/mediarouter/media/MediaRouteDescriptor.java')
-rw-r--r-- | com/android/support/mediarouter/media/MediaRouteDescriptor.java | 693 |
1 files changed, 693 insertions, 0 deletions
diff --git a/com/android/support/mediarouter/media/MediaRouteDescriptor.java b/com/android/support/mediarouter/media/MediaRouteDescriptor.java new file mode 100644 index 00000000..6bc84fc7 --- /dev/null +++ b/com/android/support/mediarouter/media/MediaRouteDescriptor.java @@ -0,0 +1,693 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.support.mediarouter.media; + +import android.content.IntentFilter; +import android.content.IntentSender; +import android.net.Uri; +import android.os.Bundle; +import android.text.TextUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * Describes the properties of a route. + * <p> + * Each route is uniquely identified by an opaque id string. This token + * may take any form as long as it is unique within the media route provider. + * </p><p> + * This object is immutable once created using a {@link Builder} instance. + * </p> + */ +public final class MediaRouteDescriptor { + static final String KEY_ID = "id"; + static final String KEY_GROUP_MEMBER_IDS = "groupMemberIds"; + static final String KEY_NAME = "name"; + static final String KEY_DESCRIPTION = "status"; + static final String KEY_ICON_URI = "iconUri"; + static final String KEY_ENABLED = "enabled"; + static final String KEY_CONNECTING = "connecting"; + static final String KEY_CONNECTION_STATE = "connectionState"; + static final String KEY_CONTROL_FILTERS = "controlFilters"; + static final String KEY_PLAYBACK_TYPE = "playbackType"; + static final String KEY_PLAYBACK_STREAM = "playbackStream"; + static final String KEY_DEVICE_TYPE = "deviceType"; + static final String KEY_VOLUME = "volume"; + static final String KEY_VOLUME_MAX = "volumeMax"; + static final String KEY_VOLUME_HANDLING = "volumeHandling"; + static final String KEY_PRESENTATION_DISPLAY_ID = "presentationDisplayId"; + static final String KEY_EXTRAS = "extras"; + static final String KEY_CAN_DISCONNECT = "canDisconnect"; + static final String KEY_SETTINGS_INTENT = "settingsIntent"; + static final String KEY_MIN_CLIENT_VERSION = "minClientVersion"; + static final String KEY_MAX_CLIENT_VERSION = "maxClientVersion"; + + final Bundle mBundle; + List<IntentFilter> mControlFilters; + + MediaRouteDescriptor(Bundle bundle, List<IntentFilter> controlFilters) { + mBundle = bundle; + mControlFilters = controlFilters; + } + + /** + * Gets the unique id of the route. + * <p> + * The route id associated with a route descriptor functions as a stable + * identifier for the route and must be unique among all routes offered + * by the provider. + * </p> + */ + public String getId() { + return mBundle.getString(KEY_ID); + } + + /** + * Gets the group member ids of the route. + * <p> + * A route descriptor that has one or more group member route ids + * represents a route group. A member route may belong to another group. + * </p> + * @hide + */ + // @RestrictTo(LIBRARY_GROUP) + public List<String> getGroupMemberIds() { + return mBundle.getStringArrayList(KEY_GROUP_MEMBER_IDS); + } + + /** + * Gets the user-visible name of the route. + * <p> + * The route name identifies the destination represented by the route. + * It may be a user-supplied name, an alias, or device serial number. + * </p> + */ + public String getName() { + return mBundle.getString(KEY_NAME); + } + + /** + * Gets the user-visible description of the route. + * <p> + * The route description describes the kind of destination represented by the route. + * It may be a user-supplied string, a model number or brand of device. + * </p> + */ + public String getDescription() { + return mBundle.getString(KEY_DESCRIPTION); + } + + /** + * Gets the URI of the icon representing this route. + * <p> + * This icon will be used in picker UIs if available. + * </p> + */ + public Uri getIconUri() { + String iconUri = mBundle.getString(KEY_ICON_URI); + return iconUri == null ? null : Uri.parse(iconUri); + } + + /** + * Gets whether the route is enabled. + */ + public boolean isEnabled() { + return mBundle.getBoolean(KEY_ENABLED, true); + } + + /** + * Gets whether the route is connecting. + * @deprecated Use {@link #getConnectionState} instead + */ + @Deprecated + public boolean isConnecting() { + return mBundle.getBoolean(KEY_CONNECTING, false); + } + + /** + * Gets the connection state of the route. + * + * @return The connection state of this route: + * {@link MediaRouter.RouteInfo#CONNECTION_STATE_DISCONNECTED}, + * {@link MediaRouter.RouteInfo#CONNECTION_STATE_CONNECTING}, or + * {@link MediaRouter.RouteInfo#CONNECTION_STATE_CONNECTED}. + */ + public int getConnectionState() { + return mBundle.getInt(KEY_CONNECTION_STATE, + MediaRouter.RouteInfo.CONNECTION_STATE_DISCONNECTED); + } + + /** + * Gets whether the route can be disconnected without stopping playback. + * <p> + * The route can normally be disconnected without stopping playback when + * the destination device on the route is connected to two or more source + * devices. The route provider should update the route immediately when the + * number of connected devices changes. + * </p><p> + * To specify that the route should disconnect without stopping use + * {@link MediaRouter#unselect(int)} with + * {@link MediaRouter#UNSELECT_REASON_DISCONNECTED}. + * </p> + */ + public boolean canDisconnectAndKeepPlaying() { + return mBundle.getBoolean(KEY_CAN_DISCONNECT, false); + } + + /** + * Gets an {@link IntentSender} for starting a settings activity for this + * route. The activity may have specific route settings or general settings + * for the connected device or route provider. + * + * @return An {@link IntentSender} to start a settings activity. + */ + public IntentSender getSettingsActivity() { + return mBundle.getParcelable(KEY_SETTINGS_INTENT); + } + + /** + * Gets the route's {@link MediaControlIntent media control intent} filters. + */ + public List<IntentFilter> getControlFilters() { + ensureControlFilters(); + return mControlFilters; + } + + void ensureControlFilters() { + if (mControlFilters == null) { + mControlFilters = mBundle.<IntentFilter>getParcelableArrayList(KEY_CONTROL_FILTERS); + if (mControlFilters == null) { + mControlFilters = Collections.<IntentFilter>emptyList(); + } + } + } + + /** + * Gets the type of playback associated with this route. + * + * @return The type of playback associated with this route: + * {@link MediaRouter.RouteInfo#PLAYBACK_TYPE_LOCAL} or + * {@link MediaRouter.RouteInfo#PLAYBACK_TYPE_REMOTE}. + */ + public int getPlaybackType() { + return mBundle.getInt(KEY_PLAYBACK_TYPE, MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE); + } + + /** + * Gets the route's playback stream. + */ + public int getPlaybackStream() { + return mBundle.getInt(KEY_PLAYBACK_STREAM, -1); + } + + /** + * Gets the type of the receiver device associated with this route. + * + * @return The type of the receiver device associated with this route: + * {@link MediaRouter.RouteInfo#DEVICE_TYPE_TV} or + * {@link MediaRouter.RouteInfo#DEVICE_TYPE_SPEAKER}. + */ + public int getDeviceType() { + return mBundle.getInt(KEY_DEVICE_TYPE); + } + + /** + * Gets the route's current volume, or 0 if unknown. + */ + public int getVolume() { + return mBundle.getInt(KEY_VOLUME); + } + + /** + * Gets the route's maximum volume, or 0 if unknown. + */ + public int getVolumeMax() { + return mBundle.getInt(KEY_VOLUME_MAX); + } + + /** + * Gets information about how volume is handled on the route. + * + * @return How volume is handled on the route: + * {@link MediaRouter.RouteInfo#PLAYBACK_VOLUME_FIXED} or + * {@link MediaRouter.RouteInfo#PLAYBACK_VOLUME_VARIABLE}. + */ + public int getVolumeHandling() { + return mBundle.getInt(KEY_VOLUME_HANDLING, + MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED); + } + + /** + * Gets the route's presentation display id, or -1 if none. + */ + public int getPresentationDisplayId() { + return mBundle.getInt( + KEY_PRESENTATION_DISPLAY_ID, MediaRouter.RouteInfo.PRESENTATION_DISPLAY_ID_NONE); + } + + /** + * Gets a bundle of extras for this route descriptor. + * The extras will be ignored by the media router but they may be used + * by applications. + */ + public Bundle getExtras() { + return mBundle.getBundle(KEY_EXTRAS); + } + + /** + * Gets the minimum client version required for this route. + * @hide + */ + // @RestrictTo(LIBRARY_GROUP) + public int getMinClientVersion() { + return mBundle.getInt(KEY_MIN_CLIENT_VERSION, + MediaRouteProviderProtocol.CLIENT_VERSION_START); + } + + /** + * Gets the maximum client version required for this route. + * @hide + */ + // @RestrictTo(LIBRARY_GROUP) + public int getMaxClientVersion() { + return mBundle.getInt(KEY_MAX_CLIENT_VERSION, Integer.MAX_VALUE); + } + + /** + * Returns true if the route descriptor has all of the required fields. + */ + public boolean isValid() { + ensureControlFilters(); + if (TextUtils.isEmpty(getId()) + || TextUtils.isEmpty(getName()) + || mControlFilters.contains(null)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("MediaRouteDescriptor{ "); + result.append("id=").append(getId()); + result.append(", groupMemberIds=").append(getGroupMemberIds()); + result.append(", name=").append(getName()); + result.append(", description=").append(getDescription()); + result.append(", iconUri=").append(getIconUri()); + result.append(", isEnabled=").append(isEnabled()); + result.append(", isConnecting=").append(isConnecting()); + result.append(", connectionState=").append(getConnectionState()); + result.append(", controlFilters=").append(Arrays.toString(getControlFilters().toArray())); + result.append(", playbackType=").append(getPlaybackType()); + result.append(", playbackStream=").append(getPlaybackStream()); + result.append(", deviceType=").append(getDeviceType()); + result.append(", volume=").append(getVolume()); + result.append(", volumeMax=").append(getVolumeMax()); + result.append(", volumeHandling=").append(getVolumeHandling()); + result.append(", presentationDisplayId=").append(getPresentationDisplayId()); + result.append(", extras=").append(getExtras()); + result.append(", isValid=").append(isValid()); + result.append(", minClientVersion=").append(getMinClientVersion()); + result.append(", maxClientVersion=").append(getMaxClientVersion()); + result.append(" }"); + return result.toString(); + } + + /** + * Converts this object to a bundle for serialization. + * + * @return The contents of the object represented as a bundle. + */ + public Bundle asBundle() { + return mBundle; + } + + /** + * Creates an instance from a bundle. + * + * @param bundle The bundle, or null if none. + * @return The new instance, or null if the bundle was null. + */ + public static MediaRouteDescriptor fromBundle(Bundle bundle) { + return bundle != null ? new MediaRouteDescriptor(bundle, null) : null; + } + + /** + * Builder for {@link MediaRouteDescriptor media route descriptors}. + */ + public static final class Builder { + private final Bundle mBundle; + private ArrayList<String> mGroupMemberIds; + private ArrayList<IntentFilter> mControlFilters; + + /** + * Creates a media route descriptor builder. + * + * @param id The unique id of the route. + * @param name The user-visible name of the route. + */ + public Builder(String id, String name) { + mBundle = new Bundle(); + setId(id); + setName(name); + } + + /** + * Creates a media route descriptor builder whose initial contents are + * copied from an existing descriptor. + */ + public Builder(MediaRouteDescriptor descriptor) { + if (descriptor == null) { + throw new IllegalArgumentException("descriptor must not be null"); + } + + mBundle = new Bundle(descriptor.mBundle); + + descriptor.ensureControlFilters(); + if (!descriptor.mControlFilters.isEmpty()) { + mControlFilters = new ArrayList<IntentFilter>(descriptor.mControlFilters); + } + } + + /** + * Sets the unique id of the route. + * <p> + * The route id associated with a route descriptor functions as a stable + * identifier for the route and must be unique among all routes offered + * by the provider. + * </p> + */ + public Builder setId(String id) { + mBundle.putString(KEY_ID, id); + return this; + } + + /** + * Adds a group member id of the route. + * <p> + * A route descriptor that has one or more group member route ids + * represents a route group. A member route may belong to another group. + * </p> + * @hide + */ + // @RestrictTo(LIBRARY_GROUP) + public Builder addGroupMemberId(String groupMemberId) { + if (TextUtils.isEmpty(groupMemberId)) { + throw new IllegalArgumentException("groupMemberId must not be empty"); + } + + if (mGroupMemberIds == null) { + mGroupMemberIds = new ArrayList<>(); + } + if (!mGroupMemberIds.contains(groupMemberId)) { + mGroupMemberIds.add(groupMemberId); + } + return this; + } + + /** + * Adds a list of group member ids of the route. + * <p> + * A route descriptor that has one or more group member route ids + * represents a route group. A member route may belong to another group. + * </p> + * @hide + */ + // @RestrictTo(LIBRARY_GROUP) + public Builder addGroupMemberIds(Collection<String> groupMemberIds) { + if (groupMemberIds == null) { + throw new IllegalArgumentException("groupMemberIds must not be null"); + } + + if (!groupMemberIds.isEmpty()) { + for (String groupMemberId : groupMemberIds) { + addGroupMemberId(groupMemberId); + } + } + return this; + } + + /** + * Sets the user-visible name of the route. + * <p> + * The route name identifies the destination represented by the route. + * It may be a user-supplied name, an alias, or device serial number. + * </p> + */ + public Builder setName(String name) { + mBundle.putString(KEY_NAME, name); + return this; + } + + /** + * Sets the user-visible description of the route. + * <p> + * The route description describes the kind of destination represented by the route. + * It may be a user-supplied string, a model number or brand of device. + * </p> + */ + public Builder setDescription(String description) { + mBundle.putString(KEY_DESCRIPTION, description); + return this; + } + + /** + * Sets the URI of the icon representing this route. + * <p> + * This icon will be used in picker UIs if available. + * </p><p> + * The URI must be one of the following formats: + * <ul> + * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li> + * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE}) + * </li> + * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li> + * </ul> + * </p> + */ + public Builder setIconUri(Uri iconUri) { + if (iconUri == null) { + throw new IllegalArgumentException("iconUri must not be null"); + } + mBundle.putString(KEY_ICON_URI, iconUri.toString()); + return this; + } + + /** + * Sets whether the route is enabled. + * <p> + * Disabled routes represent routes that a route provider knows about, such as paired + * Wifi Display receivers, but that are not currently available for use. + * </p> + */ + public Builder setEnabled(boolean enabled) { + mBundle.putBoolean(KEY_ENABLED, enabled); + return this; + } + + /** + * Sets whether the route is in the process of connecting and is not yet + * ready for use. + * @deprecated Use {@link #setConnectionState} instead. + */ + @Deprecated + public Builder setConnecting(boolean connecting) { + mBundle.putBoolean(KEY_CONNECTING, connecting); + return this; + } + + /** + * Sets the route's connection state. + * + * @param connectionState The connection state of the route: + * {@link MediaRouter.RouteInfo#CONNECTION_STATE_DISCONNECTED}, + * {@link MediaRouter.RouteInfo#CONNECTION_STATE_CONNECTING}, or + * {@link MediaRouter.RouteInfo#CONNECTION_STATE_CONNECTED}. + */ + public Builder setConnectionState(int connectionState) { + mBundle.putInt(KEY_CONNECTION_STATE, connectionState); + return this; + } + + /** + * Sets whether the route can be disconnected without stopping playback. + */ + public Builder setCanDisconnect(boolean canDisconnect) { + mBundle.putBoolean(KEY_CAN_DISCONNECT, canDisconnect); + return this; + } + + /** + * Sets an intent sender for launching the settings activity for this + * route. + */ + public Builder setSettingsActivity(IntentSender is) { + mBundle.putParcelable(KEY_SETTINGS_INTENT, is); + return this; + } + + /** + * Adds a {@link MediaControlIntent media control intent} filter for the route. + */ + public Builder addControlFilter(IntentFilter filter) { + if (filter == null) { + throw new IllegalArgumentException("filter must not be null"); + } + + if (mControlFilters == null) { + mControlFilters = new ArrayList<IntentFilter>(); + } + if (!mControlFilters.contains(filter)) { + mControlFilters.add(filter); + } + return this; + } + + /** + * Adds a list of {@link MediaControlIntent media control intent} filters for the route. + */ + public Builder addControlFilters(Collection<IntentFilter> filters) { + if (filters == null) { + throw new IllegalArgumentException("filters must not be null"); + } + + if (!filters.isEmpty()) { + for (IntentFilter filter : filters) { + addControlFilter(filter); + } + } + return this; + } + + /** + * Sets the route's playback type. + * + * @param playbackType The playback type of the route: + * {@link MediaRouter.RouteInfo#PLAYBACK_TYPE_LOCAL} or + * {@link MediaRouter.RouteInfo#PLAYBACK_TYPE_REMOTE}. + */ + public Builder setPlaybackType(int playbackType) { + mBundle.putInt(KEY_PLAYBACK_TYPE, playbackType); + return this; + } + + /** + * Sets the route's playback stream. + */ + public Builder setPlaybackStream(int playbackStream) { + mBundle.putInt(KEY_PLAYBACK_STREAM, playbackStream); + return this; + } + + /** + * Sets the route's receiver device type. + * + * @param deviceType The receive device type of the route: + * {@link MediaRouter.RouteInfo#DEVICE_TYPE_TV} or + * {@link MediaRouter.RouteInfo#DEVICE_TYPE_SPEAKER}. + */ + public Builder setDeviceType(int deviceType) { + mBundle.putInt(KEY_DEVICE_TYPE, deviceType); + return this; + } + + /** + * Sets the route's current volume, or 0 if unknown. + */ + public Builder setVolume(int volume) { + mBundle.putInt(KEY_VOLUME, volume); + return this; + } + + /** + * Sets the route's maximum volume, or 0 if unknown. + */ + public Builder setVolumeMax(int volumeMax) { + mBundle.putInt(KEY_VOLUME_MAX, volumeMax); + return this; + } + + /** + * Sets the route's volume handling. + * + * @param volumeHandling how volume is handled on the route: + * {@link MediaRouter.RouteInfo#PLAYBACK_VOLUME_FIXED} or + * {@link MediaRouter.RouteInfo#PLAYBACK_VOLUME_VARIABLE}. + */ + public Builder setVolumeHandling(int volumeHandling) { + mBundle.putInt(KEY_VOLUME_HANDLING, volumeHandling); + return this; + } + + /** + * Sets the route's presentation display id, or -1 if none. + */ + public Builder setPresentationDisplayId(int presentationDisplayId) { + mBundle.putInt(KEY_PRESENTATION_DISPLAY_ID, presentationDisplayId); + return this; + } + + /** + * Sets a bundle of extras for this route descriptor. + * The extras will be ignored by the media router but they may be used + * by applications. + */ + public Builder setExtras(Bundle extras) { + mBundle.putBundle(KEY_EXTRAS, extras); + return this; + } + + /** + * Sets the route's minimum client version. + * A router whose version is lower than this will not be able to connect to this route. + * @hide + */ + // @RestrictTo(LIBRARY_GROUP) + public Builder setMinClientVersion(int minVersion) { + mBundle.putInt(KEY_MIN_CLIENT_VERSION, minVersion); + return this; + } + + /** + * Sets the route's maximum client version. + * A router whose version is higher than this will not be able to connect to this route. + * @hide + */ + // @RestrictTo(LIBRARY_GROUP) + public Builder setMaxClientVersion(int maxVersion) { + mBundle.putInt(KEY_MAX_CLIENT_VERSION, maxVersion); + return this; + } + + /** + * Builds the {@link MediaRouteDescriptor media route descriptor}. + */ + public MediaRouteDescriptor build() { + if (mControlFilters != null) { + mBundle.putParcelableArrayList(KEY_CONTROL_FILTERS, mControlFilters); + } + if (mGroupMemberIds != null) { + mBundle.putStringArrayList(KEY_GROUP_MEMBER_IDS, mGroupMemberIds); + } + return new MediaRouteDescriptor(mBundle, mControlFilters); + } + } +} |