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.os.Bundle; 19 20import java.util.ArrayList; 21import java.util.Arrays; 22import java.util.Collection; 23import java.util.Collections; 24import java.util.List; 25 26/** 27 * Describes the state of a media route provider and the routes that it publishes. 28 * <p> 29 * This object is immutable once created using a {@link Builder} instance. 30 * </p> 31 */ 32public final class MediaRouteProviderDescriptor { 33 private static final String KEY_ROUTES = "routes"; 34 35 private final Bundle mBundle; 36 private List<MediaRouteDescriptor> mRoutes; 37 38 private MediaRouteProviderDescriptor(Bundle bundle, List<MediaRouteDescriptor> routes) { 39 mBundle = bundle; 40 mRoutes = routes; 41 } 42 43 /** 44 * Gets the list of all routes that this provider has published. 45 */ 46 public List<MediaRouteDescriptor> getRoutes() { 47 ensureRoutes(); 48 return mRoutes; 49 } 50 51 private void ensureRoutes() { 52 if (mRoutes == null) { 53 ArrayList<Bundle> routeBundles = mBundle.<Bundle>getParcelableArrayList(KEY_ROUTES); 54 if (routeBundles == null || routeBundles.isEmpty()) { 55 mRoutes = Collections.<MediaRouteDescriptor>emptyList(); 56 } else { 57 final int count = routeBundles.size(); 58 mRoutes = new ArrayList<MediaRouteDescriptor>(count); 59 for (int i = 0; i < count; i++) { 60 mRoutes.add(MediaRouteDescriptor.fromBundle(routeBundles.get(i))); 61 } 62 } 63 } 64 } 65 66 /** 67 * Returns true if the route provider descriptor and all of the routes that 68 * it contains have all of the required fields. 69 * <p> 70 * This verification is deep. If the provider descriptor is known to be 71 * valid then it is not necessary to call {@link #isValid} on each of its routes. 72 * </p> 73 */ 74 public boolean isValid() { 75 ensureRoutes(); 76 final int routeCount = mRoutes.size(); 77 for (int i = 0; i < routeCount; i++) { 78 MediaRouteDescriptor route = mRoutes.get(i); 79 if (route == null || !route.isValid()) { 80 return false; 81 } 82 } 83 return true; 84 } 85 86 @Override 87 public String toString() { 88 StringBuilder result = new StringBuilder(); 89 result.append("MediaRouteProviderDescriptor{ "); 90 result.append("routes=").append( 91 Arrays.toString(getRoutes().toArray())); 92 result.append(", isValid=").append(isValid()); 93 result.append(" }"); 94 return result.toString(); 95 } 96 97 /** 98 * Converts this object to a bundle for serialization. 99 * 100 * @return The contents of the object represented as a bundle. 101 */ 102 public Bundle asBundle() { 103 return mBundle; 104 } 105 106 /** 107 * Creates an instance from a bundle. 108 * 109 * @param bundle The bundle, or null if none. 110 * @return The new instance, or null if the bundle was null. 111 */ 112 public static MediaRouteProviderDescriptor fromBundle(Bundle bundle) { 113 return bundle != null ? new MediaRouteProviderDescriptor(bundle, null) : null; 114 } 115 116 /** 117 * Builder for {@link MediaRouteProviderDescriptor media route provider descriptors}. 118 */ 119 public static final class Builder { 120 private final Bundle mBundle; 121 private ArrayList<MediaRouteDescriptor> mRoutes; 122 123 /** 124 * Creates an empty media route provider descriptor builder. 125 */ 126 public Builder() { 127 mBundle = new Bundle(); 128 } 129 130 /** 131 * Creates a media route provider descriptor builder whose initial contents are 132 * copied from an existing descriptor. 133 */ 134 public Builder(MediaRouteProviderDescriptor descriptor) { 135 if (descriptor == null) { 136 throw new IllegalArgumentException("descriptor must not be null"); 137 } 138 139 mBundle = new Bundle(descriptor.mBundle); 140 141 descriptor.ensureRoutes(); 142 if (!descriptor.mRoutes.isEmpty()) { 143 mRoutes = new ArrayList<MediaRouteDescriptor>(descriptor.mRoutes); 144 } 145 } 146 147 /** 148 * Adds a route. 149 */ 150 public Builder addRoute(MediaRouteDescriptor route) { 151 if (route == null) { 152 throw new IllegalArgumentException("route must not be null"); 153 } 154 155 if (mRoutes == null) { 156 mRoutes = new ArrayList<MediaRouteDescriptor>(); 157 } else if (mRoutes.contains(route)) { 158 throw new IllegalArgumentException("route descriptor already added"); 159 } 160 mRoutes.add(route); 161 return this; 162 } 163 164 /** 165 * Adds a list of routes. 166 */ 167 public Builder addRoutes(Collection<MediaRouteDescriptor> routes) { 168 if (routes == null) { 169 throw new IllegalArgumentException("routes must not be null"); 170 } 171 172 if (!routes.isEmpty()) { 173 for (MediaRouteDescriptor route : routes) { 174 addRoute(route); 175 } 176 } 177 return this; 178 } 179 180 /** 181 * Sets the list of routes. 182 */ 183 Builder setRoutes(Collection<MediaRouteDescriptor> routes) { 184 if (routes == null || routes.isEmpty()) { 185 mRoutes = null; 186 mBundle.remove(KEY_ROUTES); 187 } else { 188 mRoutes = new ArrayList<>(routes); 189 } 190 return this; 191 } 192 193 /** 194 * Builds the {@link MediaRouteProviderDescriptor media route provider descriptor}. 195 */ 196 public MediaRouteProviderDescriptor build() { 197 if (mRoutes != null) { 198 final int count = mRoutes.size(); 199 ArrayList<Bundle> routeBundles = new ArrayList<Bundle>(count); 200 for (int i = 0; i < count; i++) { 201 routeBundles.add(mRoutes.get(i).asBundle()); 202 } 203 mBundle.putParcelableArrayList(KEY_ROUTES, routeBundles); 204 } 205 return new MediaRouteProviderDescriptor(mBundle, mRoutes); 206 } 207 } 208}