1 /* 2 * Copyright 2019 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 17 package android.media; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.text.TextUtils; 24 import android.util.ArrayMap; 25 26 import java.util.Arrays; 27 import java.util.Collection; 28 import java.util.Map; 29 import java.util.Objects; 30 31 /** 32 * Describes the state of a media router provider and the routes that it publishes. 33 * @hide 34 */ 35 public final class MediaRoute2ProviderInfo implements Parcelable { 36 @NonNull 37 public static final Creator<MediaRoute2ProviderInfo> CREATOR = 38 new Creator<MediaRoute2ProviderInfo>() { 39 @Override 40 public MediaRoute2ProviderInfo createFromParcel(Parcel in) { 41 return new MediaRoute2ProviderInfo(in); 42 } 43 @Override 44 public MediaRoute2ProviderInfo[] newArray(int size) { 45 return new MediaRoute2ProviderInfo[size]; 46 } 47 }; 48 49 @Nullable 50 final String mUniqueId; 51 @NonNull 52 final ArrayMap<String, MediaRoute2Info> mRoutes; 53 MediaRoute2ProviderInfo(@onNull Builder builder)54 MediaRoute2ProviderInfo(@NonNull Builder builder) { 55 Objects.requireNonNull(builder, "builder must not be null."); 56 57 mUniqueId = builder.mUniqueId; 58 mRoutes = builder.mRoutes; 59 } 60 MediaRoute2ProviderInfo(@onNull Parcel src)61 MediaRoute2ProviderInfo(@NonNull Parcel src) { 62 mUniqueId = src.readString(); 63 ArrayMap<String, MediaRoute2Info> routes = src.createTypedArrayMap(MediaRoute2Info.CREATOR); 64 mRoutes = (routes == null) ? ArrayMap.EMPTY : routes; 65 } 66 67 /** 68 * Returns true if the information of the provider and all of it's routes have all 69 * of the required fields. 70 * @hide 71 */ isValid()72 public boolean isValid() { 73 if (mUniqueId == null) { 74 return false; 75 } 76 final int count = mRoutes.size(); 77 for (int i = 0; i < count; i++) { 78 MediaRoute2Info route = mRoutes.valueAt(i); 79 if (route == null || !route.isValid()) { 80 return false; 81 } 82 } 83 return true; 84 } 85 86 /** 87 * @hide 88 */ 89 @Nullable getUniqueId()90 public String getUniqueId() { 91 return mUniqueId; 92 } 93 94 /** 95 * Gets the route for the given route id or null if no matching route exists. 96 * Please note that id should be original id. 97 * 98 * @see MediaRoute2Info#getOriginalId() 99 */ 100 @Nullable getRoute(@onNull String routeId)101 public MediaRoute2Info getRoute(@NonNull String routeId) { 102 return mRoutes.get(Objects.requireNonNull(routeId, "routeId must not be null")); 103 } 104 105 /** 106 * Gets the unmodifiable list of all routes that this provider has published. 107 */ 108 @NonNull getRoutes()109 public Collection<MediaRoute2Info> getRoutes() { 110 return mRoutes.values(); 111 } 112 113 @Override describeContents()114 public int describeContents() { 115 return 0; 116 } 117 118 @Override writeToParcel(@onNull Parcel dest, int flags)119 public void writeToParcel(@NonNull Parcel dest, int flags) { 120 dest.writeString(mUniqueId); 121 dest.writeTypedArrayMap(mRoutes, flags); 122 } 123 124 @Override toString()125 public String toString() { 126 StringBuilder result = new StringBuilder() 127 .append("MediaRouteProviderInfo { ") 128 .append("uniqueId=").append(mUniqueId) 129 .append(", routes=").append(Arrays.toString(getRoutes().toArray())) 130 .append(" }"); 131 return result.toString(); 132 } 133 134 /** 135 * Builder for {@link MediaRoute2ProviderInfo media route provider info}. 136 */ 137 public static final class Builder { 138 @NonNull 139 final ArrayMap<String, MediaRoute2Info> mRoutes; 140 String mUniqueId; 141 Builder()142 public Builder() { 143 mRoutes = new ArrayMap<>(); 144 } 145 Builder(@onNull MediaRoute2ProviderInfo descriptor)146 public Builder(@NonNull MediaRoute2ProviderInfo descriptor) { 147 Objects.requireNonNull(descriptor, "descriptor must not be null"); 148 149 mUniqueId = descriptor.mUniqueId; 150 mRoutes = new ArrayMap<>(descriptor.mRoutes); 151 } 152 153 /** 154 * Sets the unique id of the provider info. 155 * <p> 156 * The unique id is automatically set by 157 * {@link com.android.server.media.MediaRouterService} and used to identify providers. 158 * The id set by {@link MediaRoute2ProviderService} will be ignored. 159 * </p> 160 * @hide 161 */ 162 @NonNull setUniqueId(@ullable String uniqueId)163 public Builder setUniqueId(@Nullable String uniqueId) { 164 if (TextUtils.equals(mUniqueId, uniqueId)) { 165 return this; 166 } 167 mUniqueId = uniqueId; 168 169 final ArrayMap<String, MediaRoute2Info> newRoutes = new ArrayMap<>(); 170 for (Map.Entry<String, MediaRoute2Info> entry : mRoutes.entrySet()) { 171 MediaRoute2Info routeWithProviderId = new MediaRoute2Info.Builder(entry.getValue()) 172 .setProviderId(mUniqueId) 173 .build(); 174 newRoutes.put(routeWithProviderId.getOriginalId(), routeWithProviderId); 175 } 176 177 mRoutes.clear(); 178 mRoutes.putAll(newRoutes); 179 return this; 180 } 181 182 /** 183 * Sets whether the provider provides system routes or not 184 */ 185 @NonNull setSystemRouteProvider(boolean isSystem)186 public Builder setSystemRouteProvider(boolean isSystem) { 187 int count = mRoutes.size(); 188 for (int i = 0; i < count; i++) { 189 MediaRoute2Info route = mRoutes.valueAt(i); 190 if (route.isSystemRoute() != isSystem) { 191 mRoutes.setValueAt(i, new MediaRoute2Info.Builder(route) 192 .setSystemRoute(isSystem) 193 .build()); 194 } 195 } 196 return this; 197 } 198 199 /** 200 * Adds a route to the provider 201 */ 202 @NonNull addRoute(@onNull MediaRoute2Info route)203 public Builder addRoute(@NonNull MediaRoute2Info route) { 204 Objects.requireNonNull(route, "route must not be null"); 205 206 if (mRoutes.containsKey(route.getOriginalId())) { 207 throw new IllegalArgumentException("A route with the same id is already added"); 208 } 209 if (mUniqueId != null) { 210 mRoutes.put(route.getOriginalId(), 211 new MediaRoute2Info.Builder(route).setProviderId(mUniqueId).build()); 212 } else { 213 mRoutes.put(route.getOriginalId(), route); 214 } 215 return this; 216 } 217 218 /** 219 * Adds a list of routes to the provider 220 */ 221 @NonNull addRoutes(@onNull Collection<MediaRoute2Info> routes)222 public Builder addRoutes(@NonNull Collection<MediaRoute2Info> routes) { 223 Objects.requireNonNull(routes, "routes must not be null"); 224 225 if (!routes.isEmpty()) { 226 for (MediaRoute2Info route : routes) { 227 addRoute(route); 228 } 229 } 230 return this; 231 } 232 233 /** 234 * Builds {@link MediaRoute2ProviderInfo media route provider info}. 235 */ 236 @NonNull build()237 public MediaRoute2ProviderInfo build() { 238 return new MediaRoute2ProviderInfo(this); 239 } 240 } 241 } 242