| /* |
| * Copyright 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.support.mediarouter.media; |
| |
| import android.content.IntentFilter; |
| import android.os.Bundle; |
| import android.support.annotation.NonNull; |
| import android.support.annotation.Nullable; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.List; |
| |
| /** |
| * Describes the capabilities of routes that applications would like to discover and use. |
| * <p> |
| * This object is immutable once created using a {@link Builder} instance. |
| * </p> |
| * |
| * <h3>Example</h3> |
| * <pre> |
| * MediaRouteSelector selectorBuilder = new MediaRouteSelector.Builder() |
| * .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO) |
| * .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) |
| * .build(); |
| * |
| * MediaRouter router = MediaRouter.getInstance(context); |
| * router.addCallback(selector, callback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY); |
| * </pre> |
| */ |
| public final class MediaRouteSelector { |
| static final String KEY_CONTROL_CATEGORIES = "controlCategories"; |
| |
| private final Bundle mBundle; |
| List<String> mControlCategories; |
| |
| /** |
| * An empty media route selector that will not match any routes. |
| */ |
| public static final MediaRouteSelector EMPTY = new MediaRouteSelector(new Bundle(), null); |
| |
| MediaRouteSelector(Bundle bundle, List<String> controlCategories) { |
| mBundle = bundle; |
| mControlCategories = controlCategories; |
| } |
| |
| /** |
| * Gets the list of {@link MediaControlIntent media control categories} in the selector. |
| * |
| * @return The list of categories. |
| */ |
| public List<String> getControlCategories() { |
| ensureControlCategories(); |
| return mControlCategories; |
| } |
| |
| void ensureControlCategories() { |
| if (mControlCategories == null) { |
| mControlCategories = mBundle.getStringArrayList(KEY_CONTROL_CATEGORIES); |
| if (mControlCategories == null || mControlCategories.isEmpty()) { |
| mControlCategories = Collections.<String>emptyList(); |
| } |
| } |
| } |
| |
| /** |
| * Returns true if the selector contains the specified category. |
| * |
| * @param category The category to check. |
| * @return True if the category is present. |
| */ |
| public boolean hasControlCategory(String category) { |
| if (category != null) { |
| ensureControlCategories(); |
| final int categoryCount = mControlCategories.size(); |
| for (int i = 0; i < categoryCount; i++) { |
| if (mControlCategories.get(i).equals(category)) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Returns true if the selector matches at least one of the specified control filters. |
| * |
| * @param filters The list of control filters to consider. |
| * @return True if a match is found. |
| */ |
| public boolean matchesControlFilters(List<IntentFilter> filters) { |
| if (filters != null) { |
| ensureControlCategories(); |
| final int categoryCount = mControlCategories.size(); |
| if (categoryCount != 0) { |
| final int filterCount = filters.size(); |
| for (int i = 0; i < filterCount; i++) { |
| final IntentFilter filter = filters.get(i); |
| if (filter != null) { |
| for (int j = 0; j < categoryCount; j++) { |
| if (filter.hasCategory(mControlCategories.get(j))) { |
| return true; |
| } |
| } |
| } |
| } |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Returns true if this selector contains all of the capabilities described |
| * by the specified selector. |
| * |
| * @param selector The selector to be examined. |
| * @return True if this selector contains all of the capabilities described |
| * by the specified selector. |
| */ |
| public boolean contains(MediaRouteSelector selector) { |
| if (selector != null) { |
| ensureControlCategories(); |
| selector.ensureControlCategories(); |
| return mControlCategories.containsAll(selector.mControlCategories); |
| } |
| return false; |
| } |
| |
| /** |
| * Returns true if the selector does not specify any capabilities. |
| */ |
| public boolean isEmpty() { |
| ensureControlCategories(); |
| return mControlCategories.isEmpty(); |
| } |
| |
| /** |
| * Returns true if the selector has all of the required fields. |
| */ |
| public boolean isValid() { |
| ensureControlCategories(); |
| if (mControlCategories.contains(null)) { |
| return false; |
| } |
| return true; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof MediaRouteSelector) { |
| MediaRouteSelector other = (MediaRouteSelector)o; |
| ensureControlCategories(); |
| other.ensureControlCategories(); |
| return mControlCategories.equals(other.mControlCategories); |
| } |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| ensureControlCategories(); |
| return mControlCategories.hashCode(); |
| } |
| |
| @Override |
| public String toString() { |
| StringBuilder result = new StringBuilder(); |
| result.append("MediaRouteSelector{ "); |
| result.append("controlCategories=").append( |
| Arrays.toString(getControlCategories().toArray())); |
| result.append(" }"); |
| return result.toString(); |
| } |
| |
| /** |
| * Converts this object to a bundle for serialization. |
| * |
| * @return The contents of the object represented as a bundle. |
| */ |
| public Bundle asBundle() { |
| return mBundle; |
| } |
| |
| /** |
| * Creates an instance from a bundle. |
| * |
| * @param bundle The bundle, or null if none. |
| * @return The new instance, or null if the bundle was null. |
| */ |
| public static MediaRouteSelector fromBundle(@Nullable Bundle bundle) { |
| return bundle != null ? new MediaRouteSelector(bundle, null) : null; |
| } |
| |
| /** |
| * Builder for {@link MediaRouteSelector media route selectors}. |
| */ |
| public static final class Builder { |
| private ArrayList<String> mControlCategories; |
| |
| /** |
| * Creates an empty media route selector builder. |
| */ |
| public Builder() { |
| } |
| |
| /** |
| * Creates a media route selector descriptor builder whose initial contents are |
| * copied from an existing selector. |
| */ |
| public Builder(@NonNull MediaRouteSelector selector) { |
| if (selector == null) { |
| throw new IllegalArgumentException("selector must not be null"); |
| } |
| |
| selector.ensureControlCategories(); |
| if (!selector.mControlCategories.isEmpty()) { |
| mControlCategories = new ArrayList<String>(selector.mControlCategories); |
| } |
| } |
| |
| /** |
| * Adds a {@link MediaControlIntent media control category} to the builder. |
| * |
| * @param category The category to add to the set of desired capabilities, such as |
| * {@link MediaControlIntent#CATEGORY_LIVE_AUDIO}. |
| * @return The builder instance for chaining. |
| */ |
| @NonNull |
| public Builder addControlCategory(@NonNull String category) { |
| if (category == null) { |
| throw new IllegalArgumentException("category must not be null"); |
| } |
| |
| if (mControlCategories == null) { |
| mControlCategories = new ArrayList<String>(); |
| } |
| if (!mControlCategories.contains(category)) { |
| mControlCategories.add(category); |
| } |
| return this; |
| } |
| |
| /** |
| * Adds a list of {@link MediaControlIntent media control categories} to the builder. |
| * |
| * @param categories The list categories to add to the set of desired capabilities, |
| * such as {@link MediaControlIntent#CATEGORY_LIVE_AUDIO}. |
| * @return The builder instance for chaining. |
| */ |
| @NonNull |
| public Builder addControlCategories(@NonNull Collection<String> categories) { |
| if (categories == null) { |
| throw new IllegalArgumentException("categories must not be null"); |
| } |
| |
| if (!categories.isEmpty()) { |
| for (String category : categories) { |
| addControlCategory(category); |
| } |
| } |
| return this; |
| } |
| |
| /** |
| * Adds the contents of an existing media route selector to the builder. |
| * |
| * @param selector The media route selector whose contents are to be added. |
| * @return The builder instance for chaining. |
| */ |
| @NonNull |
| public Builder addSelector(@NonNull MediaRouteSelector selector) { |
| if (selector == null) { |
| throw new IllegalArgumentException("selector must not be null"); |
| } |
| |
| addControlCategories(selector.getControlCategories()); |
| return this; |
| } |
| |
| /** |
| * Builds the {@link MediaRouteSelector media route selector}. |
| */ |
| @NonNull |
| public MediaRouteSelector build() { |
| if (mControlCategories == null) { |
| return EMPTY; |
| } |
| Bundle bundle = new Bundle(); |
| bundle.putStringArrayList(KEY_CONTROL_CATEGORIES, mControlCategories); |
| return new MediaRouteSelector(bundle, mControlCategories); |
| } |
| } |
| } |