Home | History | Annotate | Download | only in media
      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 
     21 import java.util.ArrayList;
     22 import java.util.Arrays;
     23 import java.util.Collection;
     24 import java.util.Collections;
     25 import java.util.List;
     26 
     27 /**
     28  * Describes the capabilities of routes that applications would like to discover and use.
     29  * <p>
     30  * This object is immutable once created using a {@link Builder} instance.
     31  * </p>
     32  *
     33  * <h3>Example</h3>
     34  * <pre>
     35  * MediaRouteSelector selectorBuilder = new MediaRouteSelector.Builder()
     36  *         .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
     37  *         .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
     38  *         .build();
     39  *
     40  * MediaRouter router = MediaRouter.getInstance(context);
     41  * router.addCallback(selector, callback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
     42  * </pre>
     43  */
     44 public final class MediaRouteSelector {
     45     private static final String KEY_CONTROL_CATEGORIES = "controlCategories";
     46 
     47     private final Bundle mBundle;
     48     private List<String> mControlCategories;
     49 
     50     /**
     51      * An empty media route selector that will not match any routes.
     52      */
     53     public static final MediaRouteSelector EMPTY = new MediaRouteSelector(new Bundle(), null);
     54 
     55     private MediaRouteSelector(Bundle bundle, List<String> controlCategories) {
     56         mBundle = bundle;
     57         mControlCategories = controlCategories;
     58     }
     59 
     60     /**
     61      * Gets the list of {@link MediaControlIntent media control categories} in the selector.
     62      *
     63      * @return The list of categories.
     64      */
     65     public List<String> getControlCategories() {
     66         ensureControlCategories();
     67         return mControlCategories;
     68     }
     69 
     70     private void ensureControlCategories() {
     71         if (mControlCategories == null) {
     72             mControlCategories = mBundle.getStringArrayList(KEY_CONTROL_CATEGORIES);
     73             if (mControlCategories == null || mControlCategories.isEmpty()) {
     74                 mControlCategories = Collections.<String>emptyList();
     75             }
     76         }
     77     }
     78 
     79     /**
     80      * Returns true if the selector contains the specified category.
     81      *
     82      * @param category The category to check.
     83      * @return True if the category is present.
     84      */
     85     public boolean hasControlCategory(String category) {
     86         if (category != null) {
     87             ensureControlCategories();
     88             final int categoryCount = mControlCategories.size();
     89             for (int i = 0; i < categoryCount; i++) {
     90                 if (mControlCategories.get(i).equals(category)) {
     91                     return true;
     92                 }
     93             }
     94         }
     95         return false;
     96     }
     97 
     98     /**
     99      * Returns true if the selector matches at least one of the specified control filters.
    100      *
    101      * @param filters The list of control filters to consider.
    102      * @return True if a match is found.
    103      */
    104     public boolean matchesControlFilters(List<IntentFilter> filters) {
    105         if (filters != null) {
    106             ensureControlCategories();
    107             final int categoryCount = mControlCategories.size();
    108             if (categoryCount != 0) {
    109                 final int filterCount = filters.size();
    110                 for (int i = 0; i < filterCount; i++) {
    111                     final IntentFilter filter = filters.get(i);
    112                     if (filter != null) {
    113                         for (int j = 0; j < categoryCount; j++) {
    114                             if (filter.hasCategory(mControlCategories.get(j))) {
    115                                 return true;
    116                             }
    117                         }
    118                     }
    119                 }
    120             }
    121         }
    122         return false;
    123     }
    124 
    125     /**
    126      * Returns true if this selector contains all of the capabilities described
    127      * by the specified selector.
    128      *
    129      * @param selector The selector to be examined.
    130      * @return True if this selector contains all of the capabilities described
    131      * by the specified selector.
    132      */
    133     public boolean contains(MediaRouteSelector selector) {
    134         if (selector != null) {
    135             ensureControlCategories();
    136             selector.ensureControlCategories();
    137             return mControlCategories.containsAll(selector.mControlCategories);
    138         }
    139         return false;
    140     }
    141 
    142     /**
    143      * Returns true if the selector does not specify any capabilities.
    144      */
    145     public boolean isEmpty() {
    146         ensureControlCategories();
    147         return mControlCategories.isEmpty();
    148     }
    149 
    150     /**
    151      * Returns true if the selector has all of the required fields.
    152      */
    153     public boolean isValid() {
    154         ensureControlCategories();
    155         if (mControlCategories.contains(null)) {
    156             return false;
    157         }
    158         return true;
    159     }
    160 
    161     @Override
    162     public boolean equals(Object o) {
    163         if (o instanceof MediaRouteSelector) {
    164             MediaRouteSelector other = (MediaRouteSelector)o;
    165             ensureControlCategories();
    166             other.ensureControlCategories();
    167             return mControlCategories.equals(other.mControlCategories);
    168         }
    169         return false;
    170     }
    171 
    172     @Override
    173     public int hashCode() {
    174         ensureControlCategories();
    175         return mControlCategories.hashCode();
    176     }
    177 
    178     @Override
    179     public String toString() {
    180         StringBuilder result = new StringBuilder();
    181         result.append("MediaRouteSelector{ ");
    182         result.append("controlCategories=").append(
    183                 Arrays.toString(getControlCategories().toArray()));
    184         result.append(" }");
    185         return result.toString();
    186     }
    187 
    188     /**
    189      * Converts this object to a bundle for serialization.
    190      *
    191      * @return The contents of the object represented as a bundle.
    192      */
    193     public Bundle asBundle() {
    194         return mBundle;
    195     }
    196 
    197     /**
    198      * Creates an instance from a bundle.
    199      *
    200      * @param bundle The bundle, or null if none.
    201      * @return The new instance, or null if the bundle was null.
    202      */
    203     public static MediaRouteSelector fromBundle(Bundle bundle) {
    204         return bundle != null ? new MediaRouteSelector(bundle, null) : null;
    205     }
    206 
    207     /**
    208      * Builder for {@link MediaRouteSelector media route selectors}.
    209      */
    210     public static final class Builder {
    211         private ArrayList<String> mControlCategories;
    212 
    213         /**
    214          * Creates an empty media route selector builder.
    215          */
    216         public Builder() {
    217         }
    218 
    219         /**
    220          * Creates a media route selector descriptor builder whose initial contents are
    221          * copied from an existing selector.
    222          */
    223         public Builder(MediaRouteSelector selector) {
    224             if (selector == null) {
    225                 throw new IllegalArgumentException("selector must not be null");
    226             }
    227 
    228             selector.ensureControlCategories();
    229             if (!selector.mControlCategories.isEmpty()) {
    230                 mControlCategories = new ArrayList<String>(selector.mControlCategories);
    231             }
    232         }
    233 
    234         /**
    235          * Adds a {@link MediaControlIntent media control category} to the builder.
    236          *
    237          * @param category The category to add to the set of desired capabilities, such as
    238          * {@link MediaControlIntent#CATEGORY_LIVE_AUDIO}.
    239          * @return The builder instance for chaining.
    240          */
    241         public Builder addControlCategory(String category) {
    242             if (category == null) {
    243                 throw new IllegalArgumentException("category must not be null");
    244             }
    245 
    246             if (mControlCategories == null) {
    247                 mControlCategories = new ArrayList<String>();
    248             }
    249             if (!mControlCategories.contains(category)) {
    250                 mControlCategories.add(category);
    251             }
    252             return this;
    253         }
    254 
    255         /**
    256          * Adds a list of {@link MediaControlIntent media control categories} to the builder.
    257          *
    258          * @param categories The list categories to add to the set of desired capabilities,
    259          * such as {@link MediaControlIntent#CATEGORY_LIVE_AUDIO}.
    260          * @return The builder instance for chaining.
    261          */
    262         public Builder addControlCategories(Collection<String> categories) {
    263             if (categories == null) {
    264                 throw new IllegalArgumentException("categories must not be null");
    265             }
    266 
    267             if (!categories.isEmpty()) {
    268                 for (String category : categories) {
    269                     addControlCategory(category);
    270                 }
    271             }
    272             return this;
    273         }
    274 
    275         /**
    276          * Adds the contents of an existing media route selector to the builder.
    277          *
    278          * @param selector The media route selector whose contents are to be added.
    279          * @return The builder instance for chaining.
    280          */
    281         public Builder addSelector(MediaRouteSelector selector) {
    282             if (selector == null) {
    283                 throw new IllegalArgumentException("selector must not be null");
    284             }
    285 
    286             addControlCategories(selector.getControlCategories());
    287             return this;
    288         }
    289 
    290         /**
    291          * Builds the {@link MediaRouteSelector media route selector}.
    292          */
    293         public MediaRouteSelector build() {
    294             if (mControlCategories == null) {
    295                 return EMPTY;
    296             }
    297             Bundle bundle = new Bundle();
    298             bundle.putStringArrayList(KEY_CONTROL_CATEGORIES, mControlCategories);
    299             return new MediaRouteSelector(bundle, mControlCategories);
    300         }
    301     }
    302 }