1692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim/*
2692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * Copyright 2018 The Android Open Source Project
3692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim *
4692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * Licensed under the Apache License, Version 2.0 (the "License");
5692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * you may not use this file except in compliance with the License.
6692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * You may obtain a copy of the License at
7692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim *
8692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim *      http://www.apache.org/licenses/LICENSE-2.0
9692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim *
10692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * Unless required by applicable law or agreed to in writing, software
11692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * distributed under the License is distributed on an "AS IS" BASIS,
12692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * See the License for the specific language governing permissions and
14692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * limitations under the License.
15692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim */
16692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limpackage com.android.support.mediarouter.media;
17692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
18692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.os.Bundle;
19692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
20692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.util.ArrayList;
21692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.util.Arrays;
22692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.util.Collection;
23692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.util.Collections;
24692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.util.List;
25692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
26692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim/**
27692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * Describes the state of a media route provider and the routes that it publishes.
28692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * <p>
29692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * This object is immutable once created using a {@link Builder} instance.
30692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * </p>
31692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim */
32692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limpublic final class MediaRouteProviderDescriptor {
33692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private static final String KEY_ROUTES = "routes";
34692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
35692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private final Bundle mBundle;
36692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private List<MediaRouteDescriptor> mRoutes;
37692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
38692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private MediaRouteProviderDescriptor(Bundle bundle, List<MediaRouteDescriptor> routes) {
39692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mBundle = bundle;
40692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mRoutes = routes;
41692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
42692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
43692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
44692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Gets the list of all routes that this provider has published.
45692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
46692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public List<MediaRouteDescriptor> getRoutes() {
47692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        ensureRoutes();
48692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return mRoutes;
49692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
50692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
51692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private void ensureRoutes() {
52692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mRoutes == null) {
53692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            ArrayList<Bundle> routeBundles = mBundle.<Bundle>getParcelableArrayList(KEY_ROUTES);
54692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (routeBundles == null || routeBundles.isEmpty()) {
55692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mRoutes = Collections.<MediaRouteDescriptor>emptyList();
56692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else {
57692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                final int count = routeBundles.size();
58692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mRoutes = new ArrayList<MediaRouteDescriptor>(count);
59692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                for (int i = 0; i < count; i++) {
60692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    mRoutes.add(MediaRouteDescriptor.fromBundle(routeBundles.get(i)));
61692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
62692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
63692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
64692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
65692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
66692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
67692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Returns true if the route provider descriptor and all of the routes that
68692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * it contains have all of the required fields.
69692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * <p>
70692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * This verification is deep.  If the provider descriptor is known to be
71692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * valid then it is not necessary to call {@link #isValid} on each of its routes.
72692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * </p>
73692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
74692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public boolean isValid() {
75692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        ensureRoutes();
76692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        final int routeCount = mRoutes.size();
77692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        for (int i = 0; i < routeCount; i++) {
78692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            MediaRouteDescriptor route = mRoutes.get(i);
79692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (route == null || !route.isValid()) {
80692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                return false;
81692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
82692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
83692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return true;
84692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
85692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
86692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    @Override
87692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public String toString() {
88692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        StringBuilder result = new StringBuilder();
89692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        result.append("MediaRouteProviderDescriptor{ ");
90692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        result.append("routes=").append(
91692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                Arrays.toString(getRoutes().toArray()));
92692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        result.append(", isValid=").append(isValid());
93692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        result.append(" }");
94692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return result.toString();
95692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
96692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
97692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
98692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Converts this object to a bundle for serialization.
99692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     *
100692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * @return The contents of the object represented as a bundle.
101692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
102692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public Bundle asBundle() {
103692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return mBundle;
104692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
105692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
106692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
107692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Creates an instance from a bundle.
108692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     *
109692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * @param bundle The bundle, or null if none.
110692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * @return The new instance, or null if the bundle was null.
111692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
112692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public static MediaRouteProviderDescriptor fromBundle(Bundle bundle) {
113692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return bundle != null ? new MediaRouteProviderDescriptor(bundle, null) : null;
114692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
115692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
116692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
117692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Builder for {@link MediaRouteProviderDescriptor media route provider descriptors}.
118692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
119692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public static final class Builder {
120692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        private final Bundle mBundle;
121692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        private ArrayList<MediaRouteDescriptor> mRoutes;
122692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
123692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        /**
124692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim         * Creates an empty media route provider descriptor builder.
125692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim         */
126692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public Builder() {
127692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mBundle = new Bundle();
128692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
129692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
130692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        /**
131692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim         * Creates a media route provider descriptor builder whose initial contents are
132692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim         * copied from an existing descriptor.
133692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim         */
134692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public Builder(MediaRouteProviderDescriptor descriptor) {
135692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (descriptor == null) {
136692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                throw new IllegalArgumentException("descriptor must not be null");
137692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
138692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
139692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mBundle = new Bundle(descriptor.mBundle);
140692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
141692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            descriptor.ensureRoutes();
142692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (!descriptor.mRoutes.isEmpty()) {
143692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mRoutes = new ArrayList<MediaRouteDescriptor>(descriptor.mRoutes);
144692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
145692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
146692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
147692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        /**
148692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim         * Adds a route.
149692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim         */
150692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public Builder addRoute(MediaRouteDescriptor route) {
151692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (route == null) {
152692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                throw new IllegalArgumentException("route must not be null");
153692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
154692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
155692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (mRoutes == null) {
156692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mRoutes = new ArrayList<MediaRouteDescriptor>();
157692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else if (mRoutes.contains(route)) {
158692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                throw new IllegalArgumentException("route descriptor already added");
159692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
160692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mRoutes.add(route);
161692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return this;
162692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
163692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
164692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        /**
165692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim         * Adds a list of routes.
166692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim         */
167692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public Builder addRoutes(Collection<MediaRouteDescriptor> routes) {
168692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (routes == null) {
169692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                throw new IllegalArgumentException("routes must not be null");
170692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
171692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
172692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (!routes.isEmpty()) {
173692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                for (MediaRouteDescriptor route : routes) {
174692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    addRoute(route);
175692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
176692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
177692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return this;
178692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
179692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
180692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        /**
181692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim         * Sets the list of routes.
182692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim         */
183692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        Builder setRoutes(Collection<MediaRouteDescriptor> routes) {
184692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (routes == null || routes.isEmpty()) {
185692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mRoutes = null;
186692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mBundle.remove(KEY_ROUTES);
187692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else {
188692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mRoutes = new ArrayList<>(routes);
189692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
190692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return this;
191692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
192692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
193692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        /**
194692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim         * Builds the {@link MediaRouteProviderDescriptor media route provider descriptor}.
195692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim         */
196692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public MediaRouteProviderDescriptor build() {
197692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (mRoutes != null) {
198692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                final int count = mRoutes.size();
199692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                ArrayList<Bundle> routeBundles = new ArrayList<Bundle>(count);
200692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                for (int i = 0; i < count; i++) {
201692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    routeBundles.add(mRoutes.get(i).asBundle());
202692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
203692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mBundle.putParcelableArrayList(KEY_ROUTES, routeBundles);
204692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
205692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return new MediaRouteProviderDescriptor(mBundle, mRoutes);
206692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
207692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
208692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim}