blob: 0c7404aa5e954f711f4b3e106f082b56f859bf3b [file] [log] [blame]
Santos Cordon52d8a152014-06-17 19:08:45 -07001/*
2 * Copyright (C) 2014 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
Ihab Awadb19a0bc2014-08-07 19:46:01 -070014 * limitations under the License.
Santos Cordon52d8a152014-06-17 19:08:45 -070015 */
16
Tyler Gunnef9f6f92014-09-12 22:16:17 -070017package android.telecom;
Santos Cordon52d8a152014-06-17 19:08:45 -070018
Santos Cordon52d8a152014-06-17 19:08:45 -070019import android.net.Uri;
Santos Cordon6b7f9552015-05-27 17:21:45 -070020import android.os.Bundle;
Ihab Awad5d0410f2014-07-30 10:07:40 -070021import android.os.IBinder;
Santos Cordone8dc4be2014-07-21 01:28:28 -070022import android.os.IBinder.DeathRecipient;
Santos Cordon52d8a152014-06-17 19:08:45 -070023import android.os.RemoteException;
Brad Ebinger4d75bee2016-10-28 12:29:55 -070024import android.telecom.Logging.Session;
Santos Cordon52d8a152014-06-17 19:08:45 -070025
Tyler Gunnef9f6f92014-09-12 22:16:17 -070026import com.android.internal.telecom.IConnectionService;
27import com.android.internal.telecom.IConnectionServiceAdapter;
28import com.android.internal.telecom.IVideoProvider;
29import com.android.internal.telecom.RemoteServiceCallback;
Santos Cordon52d8a152014-06-17 19:08:45 -070030
Ihab Awadb8e85c72014-08-23 20:34:57 -070031import java.util.ArrayList;
Ihab Awad5d0410f2014-07-30 10:07:40 -070032import java.util.HashMap;
33import java.util.HashSet;
34import java.util.Map;
35import java.util.Set;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070036import java.util.List;
Santos Cordon52d8a152014-06-17 19:08:45 -070037import java.util.UUID;
38
39/**
40 * Remote connection service which other connection services can use to place calls on their behalf.
Sailesh Nepal091768c2014-06-30 15:15:23 -070041 *
42 * @hide
Santos Cordon52d8a152014-06-17 19:08:45 -070043 */
Ihab Awad5d0410f2014-07-30 10:07:40 -070044final class RemoteConnectionService {
Sailesh Nepal48031592014-07-18 14:21:23 -070045
Tyler Gunn4a57b9b2014-10-30 14:27:48 -070046 // Note: Casting null to avoid ambiguous constructor reference.
Ihab Awadb8e85c72014-08-23 20:34:57 -070047 private static final RemoteConnection NULL_CONNECTION =
Tyler Gunn4a57b9b2014-10-30 14:27:48 -070048 new RemoteConnection("NULL", null, (ConnectionRequest) null);
Ihab Awadb8e85c72014-08-23 20:34:57 -070049
50 private static final RemoteConference NULL_CONFERENCE =
51 new RemoteConference("NULL", null);
Santos Cordon52d8a152014-06-17 19:08:45 -070052
Ihab Awad5d0410f2014-07-30 10:07:40 -070053 private final IConnectionServiceAdapter mServantDelegate = new IConnectionServiceAdapter() {
Sailesh Nepal48031592014-07-18 14:21:23 -070054 @Override
Ihab Awad6107bab2014-08-18 09:23:25 -070055 public void handleCreateConnectionComplete(
Ihab Awadb19a0bc2014-08-07 19:46:01 -070056 String id,
57 ConnectionRequest request,
Brad Ebinger4d75bee2016-10-28 12:29:55 -070058 ParcelableConnection parcel,
59 Session.Info info) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -070060 RemoteConnection connection =
61 findConnectionForAction(id, "handleCreateConnectionSuccessful");
Ihab Awad5d0410f2014-07-30 10:07:40 -070062 if (connection != NULL_CONNECTION && mPendingConnections.contains(connection)) {
63 mPendingConnections.remove(connection);
Ihab Awad6107bab2014-08-18 09:23:25 -070064 // Unconditionally initialize the connection ...
Ihab Awad5c9c86e2014-11-12 13:41:16 -080065 connection.setConnectionCapabilities(parcel.getConnectionCapabilities());
Tyler Gunn720c6642016-03-22 09:02:47 -070066 connection.setConnectionProperties(parcel.getConnectionProperties());
Sailesh Nepal2d3ced72015-01-31 20:17:35 -080067 if (parcel.getHandle() != null
68 || parcel.getState() != Connection.STATE_DISCONNECTED) {
69 connection.setAddress(parcel.getHandle(), parcel.getHandlePresentation());
70 }
71 if (parcel.getCallerDisplayName() != null
72 || parcel.getState() != Connection.STATE_DISCONNECTED) {
73 connection.setCallerDisplayName(
74 parcel.getCallerDisplayName(),
75 parcel.getCallerDisplayNamePresentation());
76 }
Sailesh Nepal70638f12014-09-09 21:49:14 -070077 // Set state after handle so that the client can identify the connection.
Sailesh Nepalc2a978d2014-09-20 18:23:05 -070078 if (parcel.getState() == Connection.STATE_DISCONNECTED) {
79 connection.setDisconnected(parcel.getDisconnectCause());
80 } else {
81 connection.setState(parcel.getState());
82 }
Ihab Awadb8e85c72014-08-23 20:34:57 -070083 List<RemoteConnection> conferenceable = new ArrayList<>();
84 for (String confId : parcel.getConferenceableConnectionIds()) {
85 if (mConnectionById.containsKey(confId)) {
86 conferenceable.add(mConnectionById.get(confId));
87 }
88 }
89 connection.setConferenceableConnections(conferenceable);
Ihab Awada64627c2014-08-20 09:36:40 -070090 connection.setVideoState(parcel.getVideoState());
Ihab Awad6107bab2014-08-18 09:23:25 -070091 if (connection.getState() == Connection.STATE_DISCONNECTED) {
92 // ... then, if it was created in a disconnected state, that indicates
93 // failure on the providing end, so immediately mark it destroyed
94 connection.setDestroyed();
95 }
Sailesh Nepal48031592014-07-18 14:21:23 -070096 }
97 }
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -070098
Sailesh Nepal2a46b902014-07-04 17:21:07 -070099 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700100 public void setActive(String callId, Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700101 if (mConnectionById.containsKey(callId)) {
102 findConnectionForAction(callId, "setActive")
103 .setState(Connection.STATE_ACTIVE);
104 } else {
105 findConferenceForAction(callId, "setActive")
106 .setState(Connection.STATE_ACTIVE);
107 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700108 }
109
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700110 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700111 public void setRinging(String callId, Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700112 findConnectionForAction(callId, "setRinging")
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700113 .setState(Connection.STATE_RINGING);
Andrew Lee5ffbe8b2014-06-20 16:29:33 -0700114 }
115
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700116 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700117 public void setDialing(String callId, Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700118 findConnectionForAction(callId, "setDialing")
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700119 .setState(Connection.STATE_DIALING);
Santos Cordon52d8a152014-06-17 19:08:45 -0700120 }
121
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700122 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700123 public void setPulling(String callId, Session.Info sessionInfo) {
Tyler Gunnc96b5e02016-07-07 22:53:57 -0700124 findConnectionForAction(callId, "setPulling")
125 .setState(Connection.STATE_PULLING_CALL);
126 }
127
128 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700129 public void setDisconnected(String callId, DisconnectCause disconnectCause,
130 Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700131 if (mConnectionById.containsKey(callId)) {
132 findConnectionForAction(callId, "setDisconnected")
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700133 .setDisconnected(disconnectCause);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700134 } else {
135 findConferenceForAction(callId, "setDisconnected")
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700136 .setDisconnected(disconnectCause);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700137 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700138 }
139
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700140 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700141 public void setOnHold(String callId, Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700142 if (mConnectionById.containsKey(callId)) {
143 findConnectionForAction(callId, "setOnHold")
144 .setState(Connection.STATE_HOLDING);
145 } else {
146 findConferenceForAction(callId, "setOnHold")
147 .setState(Connection.STATE_HOLDING);
148 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700149 }
150
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700151 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700152 public void setRingbackRequested(String callId, boolean ringing, Session.Info sessionInfo) {
Andrew Lee100e2932014-09-08 15:34:24 -0700153 findConnectionForAction(callId, "setRingbackRequested")
154 .setRingbackRequested(ringing);
Santos Cordon52d8a152014-06-17 19:08:45 -0700155 }
156
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700157 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700158 public void setConnectionCapabilities(String callId, int connectionCapabilities,
159 Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700160 if (mConnectionById.containsKey(callId)) {
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800161 findConnectionForAction(callId, "setConnectionCapabilities")
162 .setConnectionCapabilities(connectionCapabilities);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700163 } else {
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800164 findConferenceForAction(callId, "setConnectionCapabilities")
165 .setConnectionCapabilities(connectionCapabilities);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700166 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700167 }
168
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700169 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700170 public void setConnectionProperties(String callId, int connectionProperties,
171 Session.Info sessionInfo) {
Tyler Gunn720c6642016-03-22 09:02:47 -0700172 if (mConnectionById.containsKey(callId)) {
173 findConnectionForAction(callId, "setConnectionProperties")
174 .setConnectionProperties(connectionProperties);
175 } else {
176 findConferenceForAction(callId, "setConnectionProperties")
177 .setConnectionProperties(connectionProperties);
178 }
179 }
180
181 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700182 public void setIsConferenced(String callId, String conferenceCallId,
183 Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700184 // Note: callId should not be null; conferenceCallId may be null
185 RemoteConnection connection =
186 findConnectionForAction(callId, "setIsConferenced");
187 if (connection != NULL_CONNECTION) {
188 if (conferenceCallId == null) {
189 // 'connection' is being split from its conference
190 if (connection.getConference() != null) {
191 connection.getConference().removeConnection(connection);
192 }
193 } else {
194 RemoteConference conference =
195 findConferenceForAction(conferenceCallId, "setIsConferenced");
196 if (conference != NULL_CONFERENCE) {
197 conference.addConnection(connection);
198 }
199 }
200 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700201 }
202
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700203 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700204 public void setConferenceMergeFailed(String callId, Session.Info sessionInfo) {
Anthony Lee17455a32015-04-24 15:25:29 -0700205 // Nothing to do here.
206 // The event has already been handled and there is no state to update
207 // in the underlying connection or conference objects
208 }
209
210 @Override
Ihab Awadb8e85c72014-08-23 20:34:57 -0700211 public void addConferenceCall(
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700212 final String callId, ParcelableConference parcel, Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700213 RemoteConference conference = new RemoteConference(callId,
214 mOutgoingConnectionServiceRpc);
215
216 for (String id : parcel.getConnectionIds()) {
217 RemoteConnection c = mConnectionById.get(id);
218 if (c != null) {
219 conference.addConnection(c);
220 }
221 }
Ihab Awadb8e85c72014-08-23 20:34:57 -0700222 if (conference.getConnections().size() == 0) {
223 // A conference was created, but none of its connections are ones that have been
224 // created by, and therefore being tracked by, this remote connection service. It
225 // is of no interest to us.
Tyler Gunncd6ccfd2016-10-17 15:48:19 -0700226 Log.d(this, "addConferenceCall - skipping");
Ihab Awadb8e85c72014-08-23 20:34:57 -0700227 return;
228 }
229
230 conference.setState(parcel.getState());
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800231 conference.setConnectionCapabilities(parcel.getConnectionCapabilities());
Tyler Gunn04ce7572016-08-15 10:56:12 -0700232 conference.setConnectionProperties(parcel.getConnectionProperties());
Tyler Gunncd6ccfd2016-10-17 15:48:19 -0700233 conference.putExtras(parcel.getExtras());
Ihab Awadb8e85c72014-08-23 20:34:57 -0700234 mConferenceById.put(callId, conference);
Tyler Gunncd6ccfd2016-10-17 15:48:19 -0700235
236 // Stash the original connection ID as it exists in the source ConnectionService.
237 // Telecom will use this to avoid adding duplicates later.
238 // See comments on Connection.EXTRA_ORIGINAL_CONNECTION_ID for more information.
239 Bundle newExtras = new Bundle();
240 newExtras.putString(Connection.EXTRA_ORIGINAL_CONNECTION_ID, callId);
241 conference.putExtras(newExtras);
242
Andrew Lee100e2932014-09-08 15:34:24 -0700243 conference.registerCallback(new RemoteConference.Callback() {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700244 @Override
245 public void onDestroyed(RemoteConference c) {
246 mConferenceById.remove(callId);
247 maybeDisconnectAdapter();
248 }
249 });
250
251 mOurConnectionServiceImpl.addRemoteConference(conference);
Santos Cordon52d8a152014-06-17 19:08:45 -0700252 }
253
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700254 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700255 public void removeCall(String callId, Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700256 if (mConnectionById.containsKey(callId)) {
257 findConnectionForAction(callId, "removeCall")
258 .setDestroyed();
259 } else {
260 findConferenceForAction(callId, "removeCall")
261 .setDestroyed();
262 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700263 }
264
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700265 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700266 public void onPostDialWait(String callId, String remaining, Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700267 findConnectionForAction(callId, "onPostDialWait")
268 .setPostDialWait(remaining);
Santos Cordon52d8a152014-06-17 19:08:45 -0700269 }
270
Santos Cordon52d8a152014-06-17 19:08:45 -0700271 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700272 public void onPostDialChar(String callId, char nextChar, Session.Info sessionInfo) {
Nancy Chen27d1c2d2014-12-15 16:12:50 -0800273 findConnectionForAction(callId, "onPostDialChar")
274 .onPostDialChar(nextChar);
275 }
276
277 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700278 public void queryRemoteConnectionServices(RemoteServiceCallback callback,
279 Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700280 // Not supported from remote connection service.
Santos Cordon52d8a152014-06-17 19:08:45 -0700281 }
Tyler Gunn8d83fa92014-07-01 11:31:21 -0700282
Sailesh Nepal33aaae42014-07-07 22:49:44 -0700283 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700284 public void setVideoProvider(String callId, IVideoProvider videoProvider,
285 Session.Info sessionInfo) {
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800286
287 String callingPackage = mOurConnectionServiceImpl.getApplicationContext()
288 .getOpPackageName();
Sailesh Nepal11aeae52015-01-28 16:54:09 -0800289 RemoteConnection.VideoProvider remoteVideoProvider = null;
290 if (videoProvider != null) {
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800291 remoteVideoProvider = new RemoteConnection.VideoProvider(videoProvider,
292 callingPackage);
Sailesh Nepal11aeae52015-01-28 16:54:09 -0800293 }
Ihab Awada64627c2014-08-20 09:36:40 -0700294 findConnectionForAction(callId, "setVideoProvider")
Sailesh Nepal11aeae52015-01-28 16:54:09 -0800295 .setVideoProvider(remoteVideoProvider);
Tyler Gunnaa07df82014-07-17 07:50:22 -0700296 }
297
298 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700299 public void setVideoState(String callId, int videoState, Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700300 findConnectionForAction(callId, "setVideoState")
301 .setVideoState(videoState);
Sailesh Nepal33aaae42014-07-07 22:49:44 -0700302 }
Sailesh Nepale7ef59a2014-07-08 21:48:22 -0700303
Sailesh Nepale7ef59a2014-07-08 21:48:22 -0700304 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700305 public void setIsVoipAudioMode(String callId, boolean isVoip, Session.Info sessionInfo) {
Andrew Lee100e2932014-09-08 15:34:24 -0700306 findConnectionForAction(callId, "setIsVoipAudioMode")
307 .setIsVoipAudioMode(isVoip);
Sailesh Nepale7ef59a2014-07-08 21:48:22 -0700308 }
Sailesh Nepal61203862014-07-11 14:50:13 -0700309
310 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700311 public void setStatusHints(String callId, StatusHints statusHints,
312 Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700313 findConnectionForAction(callId, "setStatusHints")
314 .setStatusHints(statusHints);
Sailesh Nepal61203862014-07-11 14:50:13 -0700315 }
316
317 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700318 public void setAddress(String callId, Uri address, int presentation,
319 Session.Info sessionInfo) {
Andrew Lee100e2932014-09-08 15:34:24 -0700320 findConnectionForAction(callId, "setAddress")
321 .setAddress(address, presentation);
Sailesh Nepal61203862014-07-11 14:50:13 -0700322 }
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -0700323
324 @Override
Ihab Awad5d0410f2014-07-30 10:07:40 -0700325 public void setCallerDisplayName(String callId, String callerDisplayName,
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700326 int presentation, Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700327 findConnectionForAction(callId, "setCallerDisplayName")
328 .setCallerDisplayName(callerDisplayName, presentation);
329 }
330
331 @Override
Ihab Awad5d0410f2014-07-30 10:07:40 -0700332 public IBinder asBinder() {
333 throw new UnsupportedOperationException();
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -0700334 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700335
336 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700337 public final void setConferenceableConnections(String callId,
338 List<String> conferenceableConnectionIds, Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700339 List<RemoteConnection> conferenceable = new ArrayList<>();
340 for (String id : conferenceableConnectionIds) {
341 if (mConnectionById.containsKey(id)) {
342 conferenceable.add(mConnectionById.get(id));
343 }
344 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700345
Ihab Awad50e35062014-09-30 09:17:03 -0700346 if (hasConnection(callId)) {
347 findConnectionForAction(callId, "setConferenceableConnections")
348 .setConferenceableConnections(conferenceable);
349 } else {
350 findConferenceForAction(callId, "setConferenceableConnections")
351 .setConferenceableConnections(conferenceable);
352 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700353 }
Tyler Gunn4a57b9b2014-10-30 14:27:48 -0700354
355 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700356 public void addExistingConnection(String callId, ParcelableConnection connection,
357 Session.Info sessionInfo) {
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800358 String callingPackage = mOurConnectionServiceImpl.getApplicationContext().
359 getOpPackageName();
Tyler Gunncd6ccfd2016-10-17 15:48:19 -0700360 RemoteConnection remoteConnection = new RemoteConnection(callId,
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800361 mOutgoingConnectionServiceRpc, connection, callingPackage);
Tyler Gunncd6ccfd2016-10-17 15:48:19 -0700362 mConnectionById.put(callId, remoteConnection);
363 remoteConnection.registerCallback(new RemoteConnection.Callback() {
364 @Override
365 public void onDestroyed(RemoteConnection connection) {
366 mConnectionById.remove(callId);
367 maybeDisconnectAdapter();
368 }
369 });
370 mOurConnectionServiceImpl.addRemoteExistingConnection(remoteConnection);
Tyler Gunn4a57b9b2014-10-30 14:27:48 -0700371 }
Santos Cordon6b7f9552015-05-27 17:21:45 -0700372
373 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700374 public void putExtras(String callId, Bundle extras, Session.Info sessionInfo) {
Tyler Gunndee56a82016-03-23 16:06:34 -0700375 if (hasConnection(callId)) {
376 findConnectionForAction(callId, "putExtras").putExtras(extras);
Santos Cordon6b7f9552015-05-27 17:21:45 -0700377 } else {
Tyler Gunndee56a82016-03-23 16:06:34 -0700378 findConferenceForAction(callId, "putExtras").putExtras(extras);
379 }
380 }
381
382 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700383 public void removeExtras(String callId, List<String> keys, Session.Info sessionInfo) {
Tyler Gunndee56a82016-03-23 16:06:34 -0700384 if (hasConnection(callId)) {
385 findConnectionForAction(callId, "removeExtra").removeExtras(keys);
386 } else {
387 findConferenceForAction(callId, "removeExtra").removeExtras(keys);
Santos Cordon6b7f9552015-05-27 17:21:45 -0700388 }
389 }
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -0800390
391 @Override
Tyler Gunnf5035432017-01-09 09:43:12 -0800392 public void setAudioRoute(String callId, int audioRoute, Session.Info sessionInfo) {
393 if (hasConnection(callId)) {
394 // TODO(3pcalls): handle this for remote connections.
395 // Likely we don't want to do anything since it doesn't make sense for self-managed
396 // connections to go through a connection mgr.
397 }
398 }
399
400 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700401 public void onConnectionEvent(String callId, String event, Bundle extras,
402 Session.Info sessionInfo) {
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -0800403 if (mConnectionById.containsKey(callId)) {
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700404 findConnectionForAction(callId, "onConnectionEvent").onConnectionEvent(event,
405 extras);
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -0800406 }
407 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700408 };
409
Ihab Awad5d0410f2014-07-30 10:07:40 -0700410 private final ConnectionServiceAdapterServant mServant =
411 new ConnectionServiceAdapterServant(mServantDelegate);
Santos Cordon52d8a152014-06-17 19:08:45 -0700412
Ihab Awad5d0410f2014-07-30 10:07:40 -0700413 private final DeathRecipient mDeathRecipient = new DeathRecipient() {
414 @Override
415 public void binderDied() {
416 for (RemoteConnection c : mConnectionById.values()) {
417 c.setDestroyed();
418 }
Ihab Awadb8e85c72014-08-23 20:34:57 -0700419 for (RemoteConference c : mConferenceById.values()) {
420 c.setDestroyed();
421 }
Ihab Awad5d0410f2014-07-30 10:07:40 -0700422 mConnectionById.clear();
Ihab Awadb8e85c72014-08-23 20:34:57 -0700423 mConferenceById.clear();
Ihab Awad5d0410f2014-07-30 10:07:40 -0700424 mPendingConnections.clear();
Ihab Awadb8e85c72014-08-23 20:34:57 -0700425 mOutgoingConnectionServiceRpc.asBinder().unlinkToDeath(mDeathRecipient, 0);
Ihab Awad5d0410f2014-07-30 10:07:40 -0700426 }
427 };
428
Ihab Awadb8e85c72014-08-23 20:34:57 -0700429 private final IConnectionService mOutgoingConnectionServiceRpc;
430 private final ConnectionService mOurConnectionServiceImpl;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700431 private final Map<String, RemoteConnection> mConnectionById = new HashMap<>();
Ihab Awadb8e85c72014-08-23 20:34:57 -0700432 private final Map<String, RemoteConference> mConferenceById = new HashMap<>();
Ihab Awad5d0410f2014-07-30 10:07:40 -0700433 private final Set<RemoteConnection> mPendingConnections = new HashSet<>();
434
Ihab Awadb8e85c72014-08-23 20:34:57 -0700435 RemoteConnectionService(
436 IConnectionService outgoingConnectionServiceRpc,
437 ConnectionService ourConnectionServiceImpl) throws RemoteException {
438 mOutgoingConnectionServiceRpc = outgoingConnectionServiceRpc;
439 mOutgoingConnectionServiceRpc.asBinder().linkToDeath(mDeathRecipient, 0);
440 mOurConnectionServiceImpl = ourConnectionServiceImpl;
Santos Cordon52d8a152014-06-17 19:08:45 -0700441 }
442
443 @Override
444 public String toString() {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700445 return "[RemoteCS - " + mOutgoingConnectionServiceRpc.asBinder().toString() + "]";
Santos Cordon52d8a152014-06-17 19:08:45 -0700446 }
447
Ihab Awadf8b69882014-07-25 15:14:01 -0700448 final RemoteConnection createRemoteConnection(
449 PhoneAccountHandle connectionManagerPhoneAccount,
450 ConnectionRequest request,
451 boolean isIncoming) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700452 final String id = UUID.randomUUID().toString();
Ihab Awad8aecfed2014-08-08 17:06:11 -0700453 final ConnectionRequest newRequest = new ConnectionRequest(
Ihab Awad5d0410f2014-07-30 10:07:40 -0700454 request.getAccountHandle(),
Nancy Chenea38cca2014-09-05 16:38:49 -0700455 request.getAddress(),
Ihab Awad5d0410f2014-07-30 10:07:40 -0700456 request.getExtras(),
457 request.getVideoState());
458 try {
Ihab Awad8aecfed2014-08-08 17:06:11 -0700459 if (mConnectionById.isEmpty()) {
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700460 mOutgoingConnectionServiceRpc.addConnectionServiceAdapter(mServant.getStub(),
461 null /*Session.Info*/);
Ihab Awad8aecfed2014-08-08 17:06:11 -0700462 }
463 RemoteConnection connection =
Ihab Awadb8e85c72014-08-23 20:34:57 -0700464 new RemoteConnection(id, mOutgoingConnectionServiceRpc, newRequest);
Ihab Awad8aecfed2014-08-08 17:06:11 -0700465 mPendingConnections.add(connection);
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700466 mConnectionById.put(id, connection);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700467 mOutgoingConnectionServiceRpc.createConnection(
Ihab Awad5d0410f2014-07-30 10:07:40 -0700468 connectionManagerPhoneAccount,
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700469 id,
Ihab Awad5d0410f2014-07-30 10:07:40 -0700470 newRequest,
Yorke Leec3cf9822014-10-02 09:38:39 -0700471 isIncoming,
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700472 false /* isUnknownCall */,
473 null /*Session.info*/);
Andrew Lee100e2932014-09-08 15:34:24 -0700474 connection.registerCallback(new RemoteConnection.Callback() {
Ihab Awad8aecfed2014-08-08 17:06:11 -0700475 @Override
476 public void onDestroyed(RemoteConnection connection) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700477 mConnectionById.remove(id);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700478 maybeDisconnectAdapter();
Ihab Awad8aecfed2014-08-08 17:06:11 -0700479 }
480 });
Ihab Awad5d0410f2014-07-30 10:07:40 -0700481 return connection;
482 } catch (RemoteException e) {
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700483 return RemoteConnection.failure(
484 new DisconnectCause(DisconnectCause.ERROR, e.toString()));
Santos Cordon52d8a152014-06-17 19:08:45 -0700485 }
486 }
487
Ihab Awad50e35062014-09-30 09:17:03 -0700488 private boolean hasConnection(String callId) {
mike dooley879142b2014-10-08 13:39:28 -0700489 return mConnectionById.containsKey(callId);
Ihab Awad50e35062014-09-30 09:17:03 -0700490 }
491
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700492 private RemoteConnection findConnectionForAction(
493 String callId, String action) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700494 if (mConnectionById.containsKey(callId)) {
495 return mConnectionById.get(callId);
496 }
497 Log.w(this, "%s - Cannot find Connection %s", action, callId);
498 return NULL_CONNECTION;
Santos Cordon52d8a152014-06-17 19:08:45 -0700499 }
Ihab Awadb8e85c72014-08-23 20:34:57 -0700500
501 private RemoteConference findConferenceForAction(
502 String callId, String action) {
503 if (mConferenceById.containsKey(callId)) {
504 return mConferenceById.get(callId);
505 }
506 Log.w(this, "%s - Cannot find Conference %s", action, callId);
507 return NULL_CONFERENCE;
508 }
509
510 private void maybeDisconnectAdapter() {
511 if (mConnectionById.isEmpty() && mConferenceById.isEmpty()) {
512 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700513 mOutgoingConnectionServiceRpc.removeConnectionServiceAdapter(mServant.getStub(),
514 null /*Session.info*/);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700515 } catch (RemoteException e) {
516 }
517 }
518 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700519}