1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.support.v7.media; 17 18 import android.content.IntentFilter; 19 import android.os.Bundle; 20 import android.text.TextUtils; 21 22 import java.util.ArrayList; 23 import java.util.Arrays; 24 import java.util.Collection; 25 import java.util.Collections; 26 import java.util.List; 27 28 /** 29 * Describes the properties of a route. 30 * <p> 31 * Each route is uniquely identified by an opaque id string. This token 32 * may take any form as long as it is unique within the media route provider. 33 * </p><p> 34 * This object is immutable once created using a {@link Builder} instance. 35 * </p> 36 */ 37 public final class MediaRouteDescriptor { 38 private static final String KEY_ID = "id"; 39 private static final String KEY_NAME = "name"; 40 private static final String KEY_DESCRIPTION = "status"; 41 private static final String KEY_ENABLED = "enabled"; 42 private static final String KEY_CONNECTING = "connecting"; 43 private static final String KEY_CONTROL_FILTERS = "controlFilters"; 44 private static final String KEY_PLAYBACK_TYPE = "playbackType"; 45 private static final String KEY_PLAYBACK_STREAM = "playbackStream"; 46 private static final String KEY_VOLUME = "volume"; 47 private static final String KEY_VOLUME_MAX = "volumeMax"; 48 private static final String KEY_VOLUME_HANDLING = "volumeHandling"; 49 private static final String KEY_PRESENTATION_DISPLAY_ID = "presentationDisplayId"; 50 private static final String KEY_EXTRAS = "extras"; 51 52 private final Bundle mBundle; 53 private List<IntentFilter> mControlFilters; 54 55 private MediaRouteDescriptor(Bundle bundle, List<IntentFilter> controlFilters) { 56 mBundle = bundle; 57 mControlFilters = controlFilters; 58 } 59 60 /** 61 * Gets the unique id of the route. 62 * <p> 63 * The route id associated with a route descriptor functions as a stable 64 * identifier for the route and must be unique among all routes offered 65 * by the provider. 66 * </p> 67 */ 68 public String getId() { 69 return mBundle.getString(KEY_ID); 70 } 71 72 /** 73 * Gets the user-visible name of the route. 74 * <p> 75 * The route name identifies the destination represented by the route. 76 * It may be a user-supplied name, an alias, or device serial number. 77 * </p> 78 */ 79 public String getName() { 80 return mBundle.getString(KEY_NAME); 81 } 82 83 /** 84 * Gets the user-visible description of the route. 85 * <p> 86 * The route description describes the kind of destination represented by the route. 87 * It may be a user-supplied string, a model number or brand of device. 88 * </p> 89 */ 90 public String getDescription() { 91 return mBundle.getString(KEY_DESCRIPTION); 92 } 93 94 /** 95 * Gets whether the route is enabled. 96 */ 97 public boolean isEnabled() { 98 return mBundle.getBoolean(KEY_ENABLED, true); 99 } 100 101 /** 102 * Gets whether the route is connecting. 103 */ 104 public boolean isConnecting() { 105 return mBundle.getBoolean(KEY_CONNECTING, false); 106 } 107 108 /** 109 * Gets the route's {@link MediaControlIntent media control intent} filters. 110 */ 111 public List<IntentFilter> getControlFilters() { 112 ensureControlFilters(); 113 return mControlFilters; 114 } 115 116 private void ensureControlFilters() { 117 if (mControlFilters == null) { 118 mControlFilters = mBundle.<IntentFilter>getParcelableArrayList(KEY_CONTROL_FILTERS); 119 if (mControlFilters == null) { 120 mControlFilters = Collections.<IntentFilter>emptyList(); 121 } 122 } 123 } 124 125 /** 126 * Gets the route's playback type. 127 */ 128 public int getPlaybackType() { 129 return mBundle.getInt(KEY_PLAYBACK_TYPE, MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE); 130 } 131 132 /** 133 * Gets the route's playback stream. 134 */ 135 public int getPlaybackStream() { 136 return mBundle.getInt(KEY_PLAYBACK_STREAM, -1); 137 } 138 139 /** 140 * Gets the route's current volume, or 0 if unknown. 141 */ 142 public int getVolume() { 143 return mBundle.getInt(KEY_VOLUME); 144 } 145 146 /** 147 * Gets the route's maximum volume, or 0 if unknown. 148 */ 149 public int getVolumeMax() { 150 return mBundle.getInt(KEY_VOLUME_MAX); 151 } 152 153 /** 154 * Gets the route's volume handling. 155 */ 156 public int getVolumeHandling() { 157 return mBundle.getInt(KEY_VOLUME_HANDLING, 158 MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED); 159 } 160 161 /** 162 * Gets the route's presentation display id, or -1 if none. 163 */ 164 public int getPresentationDisplayId() { 165 return mBundle.getInt(KEY_PRESENTATION_DISPLAY_ID, -1); 166 } 167 168 /** 169 * Gets a bundle of extras for this route descriptor. 170 * The extras will be ignored by the media router but they may be used 171 * by applications. 172 */ 173 public Bundle getExtras() { 174 return mBundle.getBundle(KEY_EXTRAS); 175 } 176 177 /** 178 * Returns true if the route descriptor has all of the required fields. 179 */ 180 public boolean isValid() { 181 ensureControlFilters(); 182 if (TextUtils.isEmpty(getId()) 183 || TextUtils.isEmpty(getName()) 184 || mControlFilters.contains(null)) { 185 return false; 186 } 187 return true; 188 } 189 190 @Override 191 public String toString() { 192 StringBuilder result = new StringBuilder(); 193 result.append("MediaRouteDescriptor{ "); 194 result.append("id=").append(getId()); 195 result.append(", name=").append(getName()); 196 result.append(", description=").append(getDescription()); 197 result.append(", isEnabled=").append(isEnabled()); 198 result.append(", isConnecting=").append(isConnecting()); 199 result.append(", controlFilters=").append(Arrays.toString(getControlFilters().toArray())); 200 result.append(", playbackType=").append(getPlaybackType()); 201 result.append(", playbackStream=").append(getPlaybackStream()); 202 result.append(", volume=").append(getVolume()); 203 result.append(", volumeMax=").append(getVolumeMax()); 204 result.append(", volumeHandling=").append(getVolumeHandling()); 205 result.append(", presentationDisplayId=").append(getPresentationDisplayId()); 206 result.append(", extras=").append(getExtras()); 207 result.append(", isValid=").append(isValid()); 208 result.append(" }"); 209 return result.toString(); 210 } 211 212 /** 213 * Converts this object to a bundle for serialization. 214 * 215 * @return The contents of the object represented as a bundle. 216 */ 217 public Bundle asBundle() { 218 return mBundle; 219 } 220 221 /** 222 * Creates an instance from a bundle. 223 * 224 * @param bundle The bundle, or null if none. 225 * @return The new instance, or null if the bundle was null. 226 */ 227 public static MediaRouteDescriptor fromBundle(Bundle bundle) { 228 return bundle != null ? new MediaRouteDescriptor(bundle, null) : null; 229 } 230 231 /** 232 * Builder for {@link MediaRouteDescriptor media route descriptors}. 233 */ 234 public static final class Builder { 235 private final Bundle mBundle; 236 private ArrayList<IntentFilter> mControlFilters; 237 238 /** 239 * Creates a media route descriptor builder. 240 * 241 * @param id The unique id of the route. 242 * @param name The user-visible name of the route. 243 */ 244 public Builder(String id, String name) { 245 mBundle = new Bundle(); 246 setId(id); 247 setName(name); 248 } 249 250 /** 251 * Creates a media route descriptor builder whose initial contents are 252 * copied from an existing descriptor. 253 */ 254 public Builder(MediaRouteDescriptor descriptor) { 255 if (descriptor == null) { 256 throw new IllegalArgumentException("descriptor must not be null"); 257 } 258 259 mBundle = new Bundle(descriptor.mBundle); 260 261 descriptor.ensureControlFilters(); 262 if (!descriptor.mControlFilters.isEmpty()) { 263 mControlFilters = new ArrayList<IntentFilter>(descriptor.mControlFilters); 264 } 265 } 266 267 /** 268 * Sets the unique id of the route. 269 * <p> 270 * The route id associated with a route descriptor functions as a stable 271 * identifier for the route and must be unique among all routes offered 272 * by the provider. 273 * </p> 274 */ 275 public Builder setId(String id) { 276 mBundle.putString(KEY_ID, id); 277 return this; 278 } 279 280 /** 281 * Sets the user-visible name of the route. 282 * <p> 283 * The route name identifies the destination represented by the route. 284 * It may be a user-supplied name, an alias, or device serial number. 285 * </p> 286 */ 287 public Builder setName(String name) { 288 mBundle.putString(KEY_NAME, name); 289 return this; 290 } 291 292 /** 293 * Sets the user-visible description of the route. 294 * <p> 295 * The route description describes the kind of destination represented by the route. 296 * It may be a user-supplied string, a model number or brand of device. 297 * </p> 298 */ 299 public Builder setDescription(String description) { 300 mBundle.putString(KEY_DESCRIPTION, description); 301 return this; 302 } 303 304 /** 305 * Sets whether the route is enabled. 306 * <p> 307 * Disabled routes represent routes that a route provider knows about, such as paired 308 * Wifi Display receivers, but that are not currently available for use. 309 * </p> 310 */ 311 public Builder setEnabled(boolean enabled) { 312 mBundle.putBoolean(KEY_ENABLED, enabled); 313 return this; 314 } 315 316 /** 317 * Sets whether the route is in the process of connecting and is not yet 318 * ready for use. 319 */ 320 public Builder setConnecting(boolean connecting) { 321 mBundle.putBoolean(KEY_CONNECTING, connecting); 322 return this; 323 } 324 325 /** 326 * Adds a {@link MediaControlIntent media control intent} filter for the route. 327 */ 328 public Builder addControlFilter(IntentFilter filter) { 329 if (filter == null) { 330 throw new IllegalArgumentException("filter must not be null"); 331 } 332 333 if (mControlFilters == null) { 334 mControlFilters = new ArrayList<IntentFilter>(); 335 } 336 if (!mControlFilters.contains(filter)) { 337 mControlFilters.add(filter); 338 } 339 return this; 340 } 341 342 /** 343 * Adds a list of {@link MediaControlIntent media control intent} filters for the route. 344 */ 345 public Builder addControlFilters(Collection<IntentFilter> filters) { 346 if (filters == null) { 347 throw new IllegalArgumentException("filters must not be null"); 348 } 349 350 if (!filters.isEmpty()) { 351 for (IntentFilter filter : filters) { 352 addControlFilter(filter); 353 } 354 } 355 return this; 356 } 357 358 /** 359 * Sets the route's playback type. 360 */ 361 public Builder setPlaybackType(int playbackType) { 362 mBundle.putInt(KEY_PLAYBACK_TYPE, playbackType); 363 return this; 364 } 365 366 /** 367 * Sets the route's playback stream. 368 */ 369 public Builder setPlaybackStream(int playbackStream) { 370 mBundle.putInt(KEY_PLAYBACK_STREAM, playbackStream); 371 return this; 372 } 373 374 /** 375 * Sets the route's current volume, or 0 if unknown. 376 */ 377 public Builder setVolume(int volume) { 378 mBundle.putInt(KEY_VOLUME, volume); 379 return this; 380 } 381 382 /** 383 * Sets the route's maximum volume, or 0 if unknown. 384 */ 385 public Builder setVolumeMax(int volumeMax) { 386 mBundle.putInt(KEY_VOLUME_MAX, volumeMax); 387 return this; 388 } 389 390 /** 391 * Sets the route's volume handling. 392 */ 393 public Builder setVolumeHandling(int volumeHandling) { 394 mBundle.putInt(KEY_VOLUME_HANDLING, volumeHandling); 395 return this; 396 } 397 398 /** 399 * Sets the route's presentation display id, or -1 if none. 400 */ 401 public Builder setPresentationDisplayId(int presentationDisplayId) { 402 mBundle.putInt(KEY_PRESENTATION_DISPLAY_ID, presentationDisplayId); 403 return this; 404 } 405 406 /** 407 * Sets a bundle of extras for this route descriptor. 408 * The extras will be ignored by the media router but they may be used 409 * by applications. 410 */ 411 public Builder setExtras(Bundle extras) { 412 mBundle.putBundle(KEY_EXTRAS, extras); 413 return this; 414 } 415 416 /** 417 * Builds the {@link MediaRouteDescriptor media route descriptor}. 418 */ 419 public MediaRouteDescriptor build() { 420 if (mControlFilters != null) { 421 mBundle.putParcelableArrayList(KEY_CONTROL_FILTERS, mControlFilters); 422 } 423 return new MediaRouteDescriptor(mBundle, mControlFilters); 424 } 425 } 426 }