MediaRouteDescriptor.java revision cb63b6ecac9786891514f241dec71695f09d3efb
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.os.Bundle;
20import android.text.TextUtils;
21
22import java.util.ArrayList;
23import java.util.Arrays;
24import java.util.Collection;
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_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}