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