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