blob: a51e3714b6f7ee72da9225ff1d357b65a6937188 [file] [log] [blame]
Kyunglyul Hyund51666d2019-04-11 04:08:40 +00001/*
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
Hyundo Moon5de706f2020-02-03 20:16:33 +090017package com.android.mediaroutertest;
Kyunglyul Hyund51666d2019-04-11 04:08:40 +000018
Kyunglyul Hyun5161b372020-02-05 18:45:35 +090019import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
Kyunglyul Hyun8828c892020-02-17 20:49:58 +090020import static android.media.MediaRoute2Info.TYPE_REMOTE_SPEAKER;
21import static android.media.MediaRoute2Info.TYPE_REMOTE_TV;
Kyunglyul Hyun3aeabe02019-12-20 19:42:39 +090022
Kyunglyul Hyunc943f212020-02-14 17:58:23 +090023import android.annotation.NonNull;
Hyundo Moon84e027d2020-01-16 17:39:05 +090024import android.annotation.Nullable;
Kyunglyul Hyund51666d2019-04-11 04:08:40 +000025import android.content.Intent;
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +090026import android.media.MediaRoute2Info;
Kyunglyul Hyund51666d2019-04-11 04:08:40 +000027import android.media.MediaRoute2ProviderService;
Hyundo Moonf829e6f2020-01-11 19:31:35 +090028import android.media.RoutingSessionInfo;
Hyundo Moon84e027d2020-01-16 17:39:05 +090029import android.os.Bundle;
Kyunglyul Hyund51666d2019-04-11 04:08:40 +000030import android.os.IBinder;
Hyundo Moon63a05402019-12-19 20:13:56 +090031import android.text.TextUtils;
Kyunglyul Hyund51666d2019-04-11 04:08:40 +000032
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +090033import java.util.HashMap;
34import java.util.Map;
Kyunglyul Hyunc943f212020-02-14 17:58:23 +090035import java.util.Objects;
36
37import javax.annotation.concurrent.GuardedBy;
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +090038
Hyundo Moon1c888e22020-03-15 19:46:41 +090039public class StubMediaRoute2ProviderService extends MediaRoute2ProviderService {
Hyundo Moon7d3ab332019-10-16 11:09:56 +090040 private static final String TAG = "SampleMR2ProviderSvc";
Kyunglyul Hyunc943f212020-02-14 17:58:23 +090041 private static final Object sLock = new Object();
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +090042
Kyunglyul Hyuncaae8dc2019-04-29 15:45:23 +090043 public static final String ROUTE_ID1 = "route_id1";
44 public static final String ROUTE_NAME1 = "Sample Route 1";
45 public static final String ROUTE_ID2 = "route_id2";
46 public static final String ROUTE_NAME2 = "Sample Route 2";
Hyundo Moon63a05402019-12-19 20:13:56 +090047 public static final String ROUTE_ID3_SESSION_CREATION_FAILED =
48 "route_id3_session_creation_failed";
49 public static final String ROUTE_NAME3 = "Sample Route 3 - Session creation failed";
Hyundo Moon0a926572019-12-28 15:01:21 +090050 public static final String ROUTE_ID4_TO_SELECT_AND_DESELECT =
51 "route_id4_to_select_and_deselect";
52 public static final String ROUTE_NAME4 = "Sample Route 4 - Route to select and deselect";
53 public static final String ROUTE_ID5_TO_TRANSFER_TO = "route_id5_to_transfer_to";
54 public static final String ROUTE_NAME5 = "Sample Route 5 - Route to transfer to";
Kyunglyul Hyune23e5ed2019-07-15 16:06:26 +090055
Kyunglyul Hyun8df5fb62020-06-03 16:52:04 +090056 public static final String ROUTE_ID6_TO_BE_IGNORED = "route_id6_to_be_ignored";
57 public static final String ROUTE_NAME6 = "Sample Route 6 - Route to be ignored";
58
Kyunglyul Hyun616096e2020-01-09 16:15:03 +090059 public static final String ROUTE_ID_SPECIAL_FEATURE = "route_special_feature";
60 public static final String ROUTE_NAME_SPECIAL_FEATURE = "Special Feature Route";
Kyunglyul Hyune23e5ed2019-07-15 16:06:26 +090061
Kyunglyul Hyun9b10a642019-10-08 15:29:23 +090062 public static final int VOLUME_MAX = 100;
Kyunglyul Hyun5161b372020-02-05 18:45:35 +090063 public static final int SESSION_VOLUME_MAX = 50;
64 public static final int SESSION_VOLUME_INITIAL = 20;
Kyunglyul Hyun9b10a642019-10-08 15:29:23 +090065 public static final String ROUTE_ID_FIXED_VOLUME = "route_fixed_volume";
66 public static final String ROUTE_NAME_FIXED_VOLUME = "Fixed Volume Route";
67 public static final String ROUTE_ID_VARIABLE_VOLUME = "route_variable_volume";
68 public static final String ROUTE_NAME_VARIABLE_VOLUME = "Variable Volume Route";
69
Kyunglyul Hyun616096e2020-01-09 16:15:03 +090070 public static final String FEATURE_SAMPLE =
Kyunglyul Hyun350d7b42020-04-17 23:09:08 +090071 "com.android.mediaroutertest.FEATURE_SAMPLE";
Kyunglyul Hyun616096e2020-01-09 16:15:03 +090072 public static final String FEATURE_SPECIAL =
Kyunglyul Hyun350d7b42020-04-17 23:09:08 +090073 "com.android.mediaroutertest..FEATURE_SPECIAL";
Kyunglyul Hyune23e5ed2019-07-15 16:06:26 +090074
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +090075 Map<String, MediaRoute2Info> mRoutes = new HashMap<>();
Hyundo Moonf829e6f2020-01-11 19:31:35 +090076 Map<String, String> mRouteIdToSessionId = new HashMap<>();
Hyundo Moona64ca9e2019-12-27 17:41:17 +090077 private int mNextSessionId = 1000;
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +090078
Kyunglyul Hyunc943f212020-02-14 17:58:23 +090079 @GuardedBy("sLock")
Hyundo Moon1c888e22020-03-15 19:46:41 +090080 private static StubMediaRoute2ProviderService sInstance;
Hyundo Moon0fa60e82020-02-14 11:44:45 +090081 private Proxy mProxy;
Kyunglyul Hyun6a2f1d62020-05-19 23:00:17 +090082 private Spy mSpy;
Kyunglyul Hyunc943f212020-02-14 17:58:23 +090083
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +090084 private void initializeRoutes() {
85 MediaRoute2Info route1 = new MediaRoute2Info.Builder(ROUTE_ID1, ROUTE_NAME1)
Kyunglyul Hyun616096e2020-01-09 16:15:03 +090086 .addFeature(FEATURE_SAMPLE)
Kyunglyul Hyun8828c892020-02-17 20:49:58 +090087 .setType(TYPE_REMOTE_TV)
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +090088 .build();
Kyunglyul Hyuncaae8dc2019-04-29 15:45:23 +090089 MediaRoute2Info route2 = new MediaRoute2Info.Builder(ROUTE_ID2, ROUTE_NAME2)
Kyunglyul Hyun616096e2020-01-09 16:15:03 +090090 .addFeature(FEATURE_SAMPLE)
Kyunglyul Hyun8828c892020-02-17 20:49:58 +090091 .setType(TYPE_REMOTE_SPEAKER)
Kyunglyul Hyuncaae8dc2019-04-29 15:45:23 +090092 .build();
Hyundo Moon63a05402019-12-19 20:13:56 +090093 MediaRoute2Info route3 = new MediaRoute2Info.Builder(
94 ROUTE_ID3_SESSION_CREATION_FAILED, ROUTE_NAME3)
Kyunglyul Hyun616096e2020-01-09 16:15:03 +090095 .addFeature(FEATURE_SAMPLE)
Hyundo Moon63a05402019-12-19 20:13:56 +090096 .build();
Hyundo Moon0a926572019-12-28 15:01:21 +090097 MediaRoute2Info route4 = new MediaRoute2Info.Builder(
98 ROUTE_ID4_TO_SELECT_AND_DESELECT, ROUTE_NAME4)
Kyunglyul Hyun616096e2020-01-09 16:15:03 +090099 .addFeature(FEATURE_SAMPLE)
Hyundo Moon0a926572019-12-28 15:01:21 +0900100 .build();
101 MediaRoute2Info route5 = new MediaRoute2Info.Builder(
102 ROUTE_ID5_TO_TRANSFER_TO, ROUTE_NAME5)
Kyunglyul Hyun616096e2020-01-09 16:15:03 +0900103 .addFeature(FEATURE_SAMPLE)
Hyundo Moon0a926572019-12-28 15:01:21 +0900104 .build();
Kyunglyul Hyun8df5fb62020-06-03 16:52:04 +0900105 MediaRoute2Info route6 = new MediaRoute2Info.Builder(
106 ROUTE_ID6_TO_BE_IGNORED, ROUTE_NAME6)
107 .addFeature(FEATURE_SAMPLE)
108 .build();
Kyunglyul Hyune23e5ed2019-07-15 16:06:26 +0900109 MediaRoute2Info routeSpecial =
Kyunglyul Hyun616096e2020-01-09 16:15:03 +0900110 new MediaRoute2Info.Builder(ROUTE_ID_SPECIAL_FEATURE, ROUTE_NAME_SPECIAL_FEATURE)
111 .addFeature(FEATURE_SAMPLE)
112 .addFeature(FEATURE_SPECIAL)
Kyunglyul Hyune23e5ed2019-07-15 16:06:26 +0900113 .build();
Kyunglyul Hyun9b10a642019-10-08 15:29:23 +0900114 MediaRoute2Info fixedVolumeRoute =
115 new MediaRoute2Info.Builder(ROUTE_ID_FIXED_VOLUME, ROUTE_NAME_FIXED_VOLUME)
Kyunglyul Hyun616096e2020-01-09 16:15:03 +0900116 .addFeature(FEATURE_SAMPLE)
Kyunglyul Hyun9b10a642019-10-08 15:29:23 +0900117 .setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_FIXED)
118 .build();
119 MediaRoute2Info variableVolumeRoute =
120 new MediaRoute2Info.Builder(ROUTE_ID_VARIABLE_VOLUME, ROUTE_NAME_VARIABLE_VOLUME)
Kyunglyul Hyun616096e2020-01-09 16:15:03 +0900121 .addFeature(FEATURE_SAMPLE)
Kyunglyul Hyun9b10a642019-10-08 15:29:23 +0900122 .setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
123 .setVolumeMax(VOLUME_MAX)
124 .build();
125
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +0900126 mRoutes.put(route1.getId(), route1);
Kyunglyul Hyuncaae8dc2019-04-29 15:45:23 +0900127 mRoutes.put(route2.getId(), route2);
Hyundo Moon63a05402019-12-19 20:13:56 +0900128 mRoutes.put(route3.getId(), route3);
Hyundo Moon0a926572019-12-28 15:01:21 +0900129 mRoutes.put(route4.getId(), route4);
130 mRoutes.put(route5.getId(), route5);
Kyunglyul Hyun8df5fb62020-06-03 16:52:04 +0900131 mRoutes.put(route6.getId(), route6);
Kyunglyul Hyunc943f212020-02-14 17:58:23 +0900132
Kyunglyul Hyune23e5ed2019-07-15 16:06:26 +0900133 mRoutes.put(routeSpecial.getId(), routeSpecial);
Kyunglyul Hyun9b10a642019-10-08 15:29:23 +0900134 mRoutes.put(fixedVolumeRoute.getId(), fixedVolumeRoute);
135 mRoutes.put(variableVolumeRoute.getId(), variableVolumeRoute);
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +0900136 }
137
Hyundo Moon1c888e22020-03-15 19:46:41 +0900138 public static StubMediaRoute2ProviderService getInstance() {
Kyunglyul Hyunc943f212020-02-14 17:58:23 +0900139 synchronized (sLock) {
140 return sInstance;
141 }
142 }
143
144 /**
145 * Adds a route and publishes it. It could replace a route in the provider if
146 * they have the same route id.
147 */
148 public void addRoute(@NonNull MediaRoute2Info route) {
149 Objects.requireNonNull(route, "route must not be null");
150 mRoutes.put(route.getOriginalId(), route);
151 publishRoutes();
152 }
153
154 /**
155 * Removes a route and publishes it.
156 */
157 public void removeRoute(@NonNull String routeId) {
158 Objects.requireNonNull(routeId, "routeId must not be null");
159 MediaRoute2Info route = mRoutes.get(routeId);
160 if (route != null) {
161 mRoutes.remove(routeId);
162 publishRoutes();
163 }
164 }
165
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +0900166 @Override
167 public void onCreate() {
Kyunglyul Hyunc943f212020-02-14 17:58:23 +0900168 synchronized (sLock) {
169 sInstance = this;
170 }
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +0900171 initializeRoutes();
172 }
173
Kyunglyul Hyund51666d2019-04-11 04:08:40 +0000174 @Override
Kyunglyul Hyunc943f212020-02-14 17:58:23 +0900175 public void onDestroy() {
176 super.onDestroy();
177 synchronized (sLock) {
178 if (sInstance == this) {
179 sInstance = null;
180 }
181 }
182 }
183
184 @Override
Kyunglyul Hyund51666d2019-04-11 04:08:40 +0000185 public IBinder onBind(Intent intent) {
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +0900186 publishRoutes();
Kyunglyul Hyund51666d2019-04-11 04:08:40 +0000187 return super.onBind(intent);
188 }
189
190 @Override
Hyundo Moon0fa60e82020-02-14 11:44:45 +0900191 public void onSetRouteVolume(long requestId, String routeId, int volume) {
192 Proxy proxy = mProxy;
193 if (proxy != null) {
194 proxy.onSetRouteVolume(routeId, volume, requestId);
195 return;
196 }
197
Kyunglyul Hyun5a8dedc2019-10-10 14:09:44 +0900198 MediaRoute2Info route = mRoutes.get(routeId);
199 if (route == null) {
200 return;
201 }
Kyunglyul Hyun5161b372020-02-05 18:45:35 +0900202 volume = Math.max(0, Math.min(volume, route.getVolumeMax()));
Kyunglyul Hyun5a8dedc2019-10-10 14:09:44 +0900203 mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
204 .setVolume(volume)
205 .build());
206 publishRoutes();
207 }
208
209 @Override
Hyundo Moon0fa60e82020-02-14 11:44:45 +0900210 public void onSetSessionVolume(long requestId, String sessionId, int volume) {
Kyunglyul Hyun5161b372020-02-05 18:45:35 +0900211 RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
212 if (sessionInfo == null) {
213 return;
214 }
215 volume = Math.max(0, Math.min(volume, sessionInfo.getVolumeMax()));
216 RoutingSessionInfo newSessionInfo = new RoutingSessionInfo.Builder(sessionInfo)
217 .setVolume(volume)
218 .build();
219 notifySessionUpdated(newSessionInfo);
220 }
221
222 @Override
Hyundo Moon0fa60e82020-02-14 11:44:45 +0900223 public void onCreateSession(long requestId, String packageName, String routeId,
Hyundo Moon84e027d2020-01-16 17:39:05 +0900224 @Nullable Bundle sessionHints) {
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900225 MediaRoute2Info route = mRoutes.get(routeId);
226 if (route == null || TextUtils.equals(ROUTE_ID3_SESSION_CREATION_FAILED, routeId)) {
Hyundo Moon7c2059c2020-02-27 19:01:52 +0900227 notifyRequestFailed(requestId, REASON_UNKNOWN_ERROR);
Hyundo Moon63a05402019-12-19 20:13:56 +0900228 return;
229 }
Kyunglyul Hyun8df5fb62020-06-03 16:52:04 +0900230 // Ignores the request intentionally for testing
231 if (TextUtils.equals(ROUTE_ID6_TO_BE_IGNORED, routeId)) {
232 return;
233 }
Hyundo Moon9be35482019-12-30 17:33:13 +0900234 maybeDeselectRoute(routeId);
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900235
Hyundo Moonb26c4b22020-01-08 19:44:43 +0900236 final String sessionId = String.valueOf(mNextSessionId);
Hyundo Moona64ca9e2019-12-27 17:41:17 +0900237 mNextSessionId++;
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900238
239 mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
240 .setClientPackageName(packageName)
241 .build());
Hyundo Moonf829e6f2020-01-11 19:31:35 +0900242 mRouteIdToSessionId.put(routeId, sessionId);
Hyundo Moon63a05402019-12-19 20:13:56 +0900243
Hyundo Moondc79a7a2020-01-16 15:18:33 +0900244 RoutingSessionInfo sessionInfo = new RoutingSessionInfo.Builder(sessionId, packageName)
Kyunglyul Hyun24cc66f2019-12-19 19:04:20 +0900245 .addSelectedRoute(routeId)
Hyundo Moon0a926572019-12-28 15:01:21 +0900246 .addSelectableRoute(ROUTE_ID4_TO_SELECT_AND_DESELECT)
Kyunglyul Hyun6e0c08b2020-02-14 15:44:18 +0900247 .addTransferableRoute(ROUTE_ID5_TO_TRANSFER_TO)
Kyunglyul Hyun5161b372020-02-05 18:45:35 +0900248 .setVolumeHandling(PLAYBACK_VOLUME_VARIABLE)
249 .setVolumeMax(SESSION_VOLUME_MAX)
250 .setVolume(SESSION_VOLUME_INITIAL)
Hyundo Moon84e027d2020-01-16 17:39:05 +0900251 // Set control hints with given sessionHints
252 .setControlHints(sessionHints)
Kyunglyul Hyun24cc66f2019-12-19 19:04:20 +0900253 .build();
Hyundo Moonf8e49f4b2020-03-06 17:19:42 +0900254 notifySessionCreated(requestId, sessionInfo);
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900255 publishRoutes();
Kyunglyul Hyun24cc66f2019-12-19 19:04:20 +0900256 }
257
258 @Override
Hyundo Moon0fa60e82020-02-14 11:44:45 +0900259 public void onReleaseSession(long requestId, String sessionId) {
Kyunglyul Hyun6a2f1d62020-05-19 23:00:17 +0900260 Spy spy = mSpy;
261 if (spy != null) {
262 spy.onReleaseSession(requestId, sessionId);
263 }
264
Hyundo Moon6e30f1b2020-01-13 19:50:27 +0900265 RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
266 if (sessionInfo == null) {
267 return;
268 }
269
270 for (String routeId : sessionInfo.getSelectedRoutes()) {
Hyundo Moonf829e6f2020-01-11 19:31:35 +0900271 mRouteIdToSessionId.remove(routeId);
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900272 MediaRoute2Info route = mRoutes.get(routeId);
273 if (route != null) {
274 mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
275 .setClientPackageName(null)
276 .build());
277 }
278 }
Hyundo Moon6e30f1b2020-01-13 19:50:27 +0900279 notifySessionReleased(sessionId);
Kyunglyul Hyunc6583832020-01-17 11:11:46 +0000280 publishRoutes();
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900281 }
Kyunglyul Hyun24cc66f2019-12-19 19:04:20 +0900282
283 @Override
Hyundo Moon0fa60e82020-02-14 11:44:45 +0900284 public void onSelectRoute(long requestId, String sessionId, String routeId) {
Hyundo Moonf829e6f2020-01-11 19:31:35 +0900285 RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900286 MediaRoute2Info route = mRoutes.get(routeId);
287 if (route == null || sessionInfo == null) {
288 return;
289 }
Hyundo Moon9be35482019-12-30 17:33:13 +0900290 maybeDeselectRoute(routeId);
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900291
292 mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
Hyundo Moonb26c4b22020-01-08 19:44:43 +0900293 .setClientPackageName(sessionInfo.getClientPackageName())
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900294 .build());
Hyundo Moonf829e6f2020-01-11 19:31:35 +0900295 mRouteIdToSessionId.put(routeId, sessionId);
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900296
Hyundo Moonf829e6f2020-01-11 19:31:35 +0900297 RoutingSessionInfo newSessionInfo = new RoutingSessionInfo.Builder(sessionInfo)
Kyunglyul Hyun24cc66f2019-12-19 19:04:20 +0900298 .addSelectedRoute(routeId)
Hyundo Moon0a926572019-12-28 15:01:21 +0900299 .removeSelectableRoute(routeId)
300 .addDeselectableRoute(routeId)
Kyunglyul Hyun24cc66f2019-12-19 19:04:20 +0900301 .build();
Hyundo Moon6e30f1b2020-01-13 19:50:27 +0900302 notifySessionUpdated(newSessionInfo);
Kyunglyul Hyun24cc66f2019-12-19 19:04:20 +0900303 }
304
305 @Override
Hyundo Moon0fa60e82020-02-14 11:44:45 +0900306 public void onDeselectRoute(long requestId, String sessionId, String routeId) {
Hyundo Moonf829e6f2020-01-11 19:31:35 +0900307 RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900308 MediaRoute2Info route = mRoutes.get(routeId);
309
Hyundo Moon459dee32020-01-11 14:06:46 +0900310 if (sessionInfo == null || route == null
311 || !sessionInfo.getSelectedRoutes().contains(routeId)) {
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900312 return;
313 }
Hyundo Moon459dee32020-01-11 14:06:46 +0900314
Hyundo Moonf829e6f2020-01-11 19:31:35 +0900315 mRouteIdToSessionId.remove(routeId);
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900316 mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
317 .setClientPackageName(null)
318 .build());
319
Hyundo Moon459dee32020-01-11 14:06:46 +0900320 if (sessionInfo.getSelectedRoutes().size() == 1) {
Hyundo Moon6e30f1b2020-01-13 19:50:27 +0900321 notifySessionReleased(sessionId);
Hyundo Moon459dee32020-01-11 14:06:46 +0900322 return;
323 }
324
Hyundo Moonf829e6f2020-01-11 19:31:35 +0900325 RoutingSessionInfo newSessionInfo = new RoutingSessionInfo.Builder(sessionInfo)
Kyunglyul Hyun24cc66f2019-12-19 19:04:20 +0900326 .removeSelectedRoute(routeId)
Hyundo Moon0a926572019-12-28 15:01:21 +0900327 .addSelectableRoute(routeId)
328 .removeDeselectableRoute(routeId)
Kyunglyul Hyun24cc66f2019-12-19 19:04:20 +0900329 .build();
Hyundo Moon6e30f1b2020-01-13 19:50:27 +0900330 notifySessionUpdated(newSessionInfo);
Kyunglyul Hyun24cc66f2019-12-19 19:04:20 +0900331 }
332
333 @Override
Hyundo Moon0fa60e82020-02-14 11:44:45 +0900334 public void onTransferToRoute(long requestId, String sessionId, String routeId) {
Hyundo Moonf829e6f2020-01-11 19:31:35 +0900335 RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
Kyunglyul Hyunc6583832020-01-17 11:11:46 +0000336 MediaRoute2Info route = mRoutes.get(routeId);
337
338 if (sessionInfo == null || route == null) {
339 return;
340 }
341
342 for (String selectedRouteId : sessionInfo.getSelectedRoutes()) {
343 mRouteIdToSessionId.remove(selectedRouteId);
344 MediaRoute2Info selectedRoute = mRoutes.get(selectedRouteId);
345 if (selectedRoute != null) {
346 mRoutes.put(selectedRouteId, new MediaRoute2Info.Builder(selectedRoute)
347 .setClientPackageName(null)
348 .build());
349 }
350 }
351
352 mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
353 .setClientPackageName(sessionInfo.getClientPackageName())
354 .build());
355 mRouteIdToSessionId.put(routeId, sessionId);
356
Hyundo Moonf829e6f2020-01-11 19:31:35 +0900357 RoutingSessionInfo newSessionInfo = new RoutingSessionInfo.Builder(sessionInfo)
Kyunglyul Hyun24cc66f2019-12-19 19:04:20 +0900358 .clearSelectedRoutes()
359 .addSelectedRoute(routeId)
Hyundo Moon0a926572019-12-28 15:01:21 +0900360 .removeDeselectableRoute(routeId)
Kyunglyul Hyun6e0c08b2020-02-14 15:44:18 +0900361 .removeTransferableRoute(routeId)
Kyunglyul Hyun24cc66f2019-12-19 19:04:20 +0900362 .build();
Hyundo Moon6e30f1b2020-01-13 19:50:27 +0900363 notifySessionUpdated(newSessionInfo);
Kyunglyul Hyunc6583832020-01-17 11:11:46 +0000364 publishRoutes();
Kyunglyul Hyun24cc66f2019-12-19 19:04:20 +0900365 }
366
Hyundo Moon9be35482019-12-30 17:33:13 +0900367 void maybeDeselectRoute(String routeId) {
Hyundo Moonf829e6f2020-01-11 19:31:35 +0900368 if (!mRouteIdToSessionId.containsKey(routeId)) {
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900369 return;
370 }
371
Hyundo Moonf829e6f2020-01-11 19:31:35 +0900372 String sessionId = mRouteIdToSessionId.get(routeId);
Hyundo Moon0fa60e82020-02-14 11:44:45 +0900373 onDeselectRoute(REQUEST_ID_NONE, sessionId, routeId);
Kyunglyul Hyuncb8894d2019-12-27 14:24:46 +0900374 }
375
Kyunglyul Hyun3aedf022019-04-15 16:38:19 +0900376 void publishRoutes() {
Kyunglyul Hyun616096e2020-01-09 16:15:03 +0900377 notifyRoutes(mRoutes.values());
Kyunglyul Hyund51666d2019-04-11 04:08:40 +0000378 }
Hyundo Moon0fa60e82020-02-14 11:44:45 +0900379
380 public void setProxy(@Nullable Proxy proxy) {
381 mProxy = proxy;
382 }
383
Kyunglyul Hyun6a2f1d62020-05-19 23:00:17 +0900384 public void setSpy(@Nullable Spy spy) {
385 mSpy = spy;
386 }
387
388 /**
389 * It overrides the original service
390 */
Hyundo Moon0fa60e82020-02-14 11:44:45 +0900391 public static class Proxy {
392 public void onSetRouteVolume(String routeId, int volume, long requestId) {}
393 }
Kyunglyul Hyun6a2f1d62020-05-19 23:00:17 +0900394
395 /**
396 * It gets notified but doesn't prevent the original methods to be called.
397 */
398 public static class Spy {
399 public void onReleaseSession(long requestId, String sessionId) {}
400 }
Kyunglyul Hyund51666d2019-04-11 04:08:40 +0000401}