blob: 2fc6a22261b6447fddf0a93285abe8d85aa58316 [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;
Junhoedf3d822022-11-24 09:26:37 +000024import android.os.ResultReceiver;
Brad Ebinger4d75bee2016-10-28 12:29:55 -070025import android.telecom.Logging.Session;
Santos Cordon52d8a152014-06-17 19:08:45 -070026
Tyler Gunnef9f6f92014-09-12 22:16:17 -070027import com.android.internal.telecom.IConnectionService;
28import com.android.internal.telecom.IConnectionServiceAdapter;
29import com.android.internal.telecom.IVideoProvider;
30import com.android.internal.telecom.RemoteServiceCallback;
Santos Cordon52d8a152014-06-17 19:08:45 -070031
Ihab Awadb8e85c72014-08-23 20:34:57 -070032import java.util.ArrayList;
Ihab Awad5d0410f2014-07-30 10:07:40 -070033import java.util.HashMap;
34import java.util.HashSet;
Grace Jia9a09c672020-08-04 12:52:09 -070035import java.util.List;
Ihab Awad5d0410f2014-07-30 10:07:40 -070036import java.util.Map;
37import java.util.Set;
Santos Cordon52d8a152014-06-17 19:08:45 -070038import java.util.UUID;
39
40/**
41 * Remote connection service which other connection services can use to place calls on their behalf.
Sailesh Nepal091768c2014-06-30 15:15:23 -070042 *
43 * @hide
Santos Cordon52d8a152014-06-17 19:08:45 -070044 */
Ihab Awad5d0410f2014-07-30 10:07:40 -070045final class RemoteConnectionService {
Sailesh Nepal48031592014-07-18 14:21:23 -070046
Tyler Gunn4a57b9b2014-10-30 14:27:48 -070047 // Note: Casting null to avoid ambiguous constructor reference.
Ihab Awadb8e85c72014-08-23 20:34:57 -070048 private static final RemoteConnection NULL_CONNECTION =
Tyler Gunn4a57b9b2014-10-30 14:27:48 -070049 new RemoteConnection("NULL", null, (ConnectionRequest) null);
Ihab Awadb8e85c72014-08-23 20:34:57 -070050
51 private static final RemoteConference NULL_CONFERENCE =
52 new RemoteConference("NULL", null);
Santos Cordon52d8a152014-06-17 19:08:45 -070053
Ihab Awad5d0410f2014-07-30 10:07:40 -070054 private final IConnectionServiceAdapter mServantDelegate = new IConnectionServiceAdapter() {
Sailesh Nepal48031592014-07-18 14:21:23 -070055 @Override
Ihab Awad6107bab2014-08-18 09:23:25 -070056 public void handleCreateConnectionComplete(
Ihab Awadb19a0bc2014-08-07 19:46:01 -070057 String id,
58 ConnectionRequest request,
Brad Ebinger4d75bee2016-10-28 12:29:55 -070059 ParcelableConnection parcel,
60 Session.Info info) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -070061 RemoteConnection connection =
62 findConnectionForAction(id, "handleCreateConnectionSuccessful");
Ihab Awad5d0410f2014-07-30 10:07:40 -070063 if (connection != NULL_CONNECTION && mPendingConnections.contains(connection)) {
64 mPendingConnections.remove(connection);
Ihab Awad6107bab2014-08-18 09:23:25 -070065 // Unconditionally initialize the connection ...
Ihab Awad5c9c86e2014-11-12 13:41:16 -080066 connection.setConnectionCapabilities(parcel.getConnectionCapabilities());
Tyler Gunn720c6642016-03-22 09:02:47 -070067 connection.setConnectionProperties(parcel.getConnectionProperties());
Sailesh Nepal2d3ced72015-01-31 20:17:35 -080068 if (parcel.getHandle() != null
69 || parcel.getState() != Connection.STATE_DISCONNECTED) {
70 connection.setAddress(parcel.getHandle(), parcel.getHandlePresentation());
71 }
72 if (parcel.getCallerDisplayName() != null
73 || parcel.getState() != Connection.STATE_DISCONNECTED) {
74 connection.setCallerDisplayName(
75 parcel.getCallerDisplayName(),
76 parcel.getCallerDisplayNamePresentation());
77 }
Sailesh Nepal70638f12014-09-09 21:49:14 -070078 // Set state after handle so that the client can identify the connection.
Sailesh Nepalc2a978d2014-09-20 18:23:05 -070079 if (parcel.getState() == Connection.STATE_DISCONNECTED) {
80 connection.setDisconnected(parcel.getDisconnectCause());
81 } else {
82 connection.setState(parcel.getState());
83 }
Ihab Awadb8e85c72014-08-23 20:34:57 -070084 List<RemoteConnection> conferenceable = new ArrayList<>();
85 for (String confId : parcel.getConferenceableConnectionIds()) {
86 if (mConnectionById.containsKey(confId)) {
87 conferenceable.add(mConnectionById.get(confId));
88 }
89 }
90 connection.setConferenceableConnections(conferenceable);
Ihab Awada64627c2014-08-20 09:36:40 -070091 connection.setVideoState(parcel.getVideoState());
Ihab Awad6107bab2014-08-18 09:23:25 -070092 if (connection.getState() == Connection.STATE_DISCONNECTED) {
93 // ... then, if it was created in a disconnected state, that indicates
94 // failure on the providing end, so immediately mark it destroyed
95 connection.setDestroyed();
96 }
Tyler Gunn31f0e0b2018-02-13 08:39:45 -080097 connection.setStatusHints(parcel.getStatusHints());
98 connection.setIsVoipAudioMode(parcel.getIsVoipAudioMode());
99 connection.setRingbackRequested(parcel.isRingbackRequested());
100 connection.putExtras(parcel.getExtras());
Sailesh Nepal48031592014-07-18 14:21:23 -0700101 }
102 }
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -0700103
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700104 @Override
Ravi Paluri80aa2142019-12-02 11:57:37 +0530105 public void handleCreateConferenceComplete(
106 String id,
107 ConnectionRequest request,
108 ParcelableConference parcel,
109 Session.Info info) {
110 }
111
112 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700113 public void setActive(String callId, Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700114 if (mConnectionById.containsKey(callId)) {
115 findConnectionForAction(callId, "setActive")
116 .setState(Connection.STATE_ACTIVE);
117 } else {
118 findConferenceForAction(callId, "setActive")
119 .setState(Connection.STATE_ACTIVE);
120 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700121 }
122
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700123 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700124 public void setRinging(String callId, Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700125 findConnectionForAction(callId, "setRinging")
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700126 .setState(Connection.STATE_RINGING);
Andrew Lee5ffbe8b82014-06-20 16:29:33 -0700127 }
128
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700129 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700130 public void setDialing(String callId, Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700131 findConnectionForAction(callId, "setDialing")
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700132 .setState(Connection.STATE_DIALING);
Santos Cordon52d8a152014-06-17 19:08:45 -0700133 }
134
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700135 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700136 public void setPulling(String callId, Session.Info sessionInfo) {
Tyler Gunnc96b5e02016-07-07 22:53:57 -0700137 findConnectionForAction(callId, "setPulling")
138 .setState(Connection.STATE_PULLING_CALL);
139 }
140
141 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700142 public void setDisconnected(String callId, DisconnectCause disconnectCause,
143 Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700144 if (mConnectionById.containsKey(callId)) {
145 findConnectionForAction(callId, "setDisconnected")
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700146 .setDisconnected(disconnectCause);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700147 } else {
148 findConferenceForAction(callId, "setDisconnected")
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700149 .setDisconnected(disconnectCause);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700150 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700151 }
152
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700153 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700154 public void setOnHold(String callId, Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700155 if (mConnectionById.containsKey(callId)) {
156 findConnectionForAction(callId, "setOnHold")
157 .setState(Connection.STATE_HOLDING);
158 } else {
159 findConferenceForAction(callId, "setOnHold")
160 .setState(Connection.STATE_HOLDING);
161 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700162 }
163
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700164 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700165 public void setRingbackRequested(String callId, boolean ringing, Session.Info sessionInfo) {
Andrew Lee100e2932014-09-08 15:34:24 -0700166 findConnectionForAction(callId, "setRingbackRequested")
167 .setRingbackRequested(ringing);
Santos Cordon52d8a152014-06-17 19:08:45 -0700168 }
169
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700170 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700171 public void setConnectionCapabilities(String callId, int connectionCapabilities,
172 Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700173 if (mConnectionById.containsKey(callId)) {
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800174 findConnectionForAction(callId, "setConnectionCapabilities")
175 .setConnectionCapabilities(connectionCapabilities);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700176 } else {
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800177 findConferenceForAction(callId, "setConnectionCapabilities")
178 .setConnectionCapabilities(connectionCapabilities);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700179 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700180 }
181
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700182 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700183 public void setConnectionProperties(String callId, int connectionProperties,
184 Session.Info sessionInfo) {
Tyler Gunn720c6642016-03-22 09:02:47 -0700185 if (mConnectionById.containsKey(callId)) {
186 findConnectionForAction(callId, "setConnectionProperties")
187 .setConnectionProperties(connectionProperties);
188 } else {
189 findConferenceForAction(callId, "setConnectionProperties")
190 .setConnectionProperties(connectionProperties);
191 }
192 }
193
194 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700195 public void setIsConferenced(String callId, String conferenceCallId,
196 Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700197 // Note: callId should not be null; conferenceCallId may be null
198 RemoteConnection connection =
199 findConnectionForAction(callId, "setIsConferenced");
200 if (connection != NULL_CONNECTION) {
201 if (conferenceCallId == null) {
202 // 'connection' is being split from its conference
203 if (connection.getConference() != null) {
204 connection.getConference().removeConnection(connection);
205 }
206 } else {
207 RemoteConference conference =
208 findConferenceForAction(conferenceCallId, "setIsConferenced");
209 if (conference != NULL_CONFERENCE) {
210 conference.addConnection(connection);
211 }
212 }
213 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700214 }
215
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700216 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700217 public void setConferenceMergeFailed(String callId, Session.Info sessionInfo) {
Anthony Lee17455a32015-04-24 15:25:29 -0700218 // Nothing to do here.
219 // The event has already been handled and there is no state to update
220 // in the underlying connection or conference objects
221 }
222
223 @Override
Srikanth Chintalafcb15012017-05-04 20:58:34 +0530224 public void onPhoneAccountChanged(String callId, PhoneAccountHandle pHandle,
225 Session.Info sessionInfo) {
226 }
227
228 @Override
Pengquan Meng63d25a52017-11-21 18:01:13 -0800229 public void onConnectionServiceFocusReleased(Session.Info sessionInfo) {}
230
231 @Override
Ihab Awadb8e85c72014-08-23 20:34:57 -0700232 public void addConferenceCall(
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700233 final String callId, ParcelableConference parcel, Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700234 RemoteConference conference = new RemoteConference(callId,
235 mOutgoingConnectionServiceRpc);
236
237 for (String id : parcel.getConnectionIds()) {
238 RemoteConnection c = mConnectionById.get(id);
239 if (c != null) {
240 conference.addConnection(c);
241 }
242 }
Tyler Gunn2d4fcc12021-06-24 11:25:07 -0700243 // We used to skip adding empty conferences; however in the world of IMS conference
244 // calls we need to add them to the remote connection service because they will always
245 // start with no participants.
Ihab Awadb8e85c72014-08-23 20:34:57 -0700246
247 conference.setState(parcel.getState());
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800248 conference.setConnectionCapabilities(parcel.getConnectionCapabilities());
Tyler Gunn04ce7572016-08-15 10:56:12 -0700249 conference.setConnectionProperties(parcel.getConnectionProperties());
Tyler Gunncd6ccfd2016-10-17 15:48:19 -0700250 conference.putExtras(parcel.getExtras());
Ihab Awadb8e85c72014-08-23 20:34:57 -0700251 mConferenceById.put(callId, conference);
Tyler Gunncd6ccfd2016-10-17 15:48:19 -0700252
253 // Stash the original connection ID as it exists in the source ConnectionService.
254 // Telecom will use this to avoid adding duplicates later.
255 // See comments on Connection.EXTRA_ORIGINAL_CONNECTION_ID for more information.
256 Bundle newExtras = new Bundle();
257 newExtras.putString(Connection.EXTRA_ORIGINAL_CONNECTION_ID, callId);
Tyler Gunnc59fd0c2020-04-17 14:03:35 -0700258 // Track the fact this request was relayed through the remote connection service.
259 newExtras.putParcelable(Connection.EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE,
260 parcel.getPhoneAccount());
Tyler Gunncd6ccfd2016-10-17 15:48:19 -0700261 conference.putExtras(newExtras);
262
Andrew Lee100e2932014-09-08 15:34:24 -0700263 conference.registerCallback(new RemoteConference.Callback() {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700264 @Override
265 public void onDestroyed(RemoteConference c) {
266 mConferenceById.remove(callId);
267 maybeDisconnectAdapter();
268 }
269 });
270
271 mOurConnectionServiceImpl.addRemoteConference(conference);
Santos Cordon52d8a152014-06-17 19:08:45 -0700272 }
273
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700274 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700275 public void removeCall(String callId, Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700276 if (mConnectionById.containsKey(callId)) {
277 findConnectionForAction(callId, "removeCall")
278 .setDestroyed();
279 } else {
280 findConferenceForAction(callId, "removeCall")
281 .setDestroyed();
282 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700283 }
284
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700285 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700286 public void onPostDialWait(String callId, String remaining, Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700287 findConnectionForAction(callId, "onPostDialWait")
288 .setPostDialWait(remaining);
Santos Cordon52d8a152014-06-17 19:08:45 -0700289 }
290
Santos Cordon52d8a152014-06-17 19:08:45 -0700291 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700292 public void onPostDialChar(String callId, char nextChar, Session.Info sessionInfo) {
Nancy Chen27d1c2d2014-12-15 16:12:50 -0800293 findConnectionForAction(callId, "onPostDialChar")
294 .onPostDialChar(nextChar);
295 }
296
297 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700298 public void queryRemoteConnectionServices(RemoteServiceCallback callback,
Tyler Gunn4c69fb32019-05-17 10:49:16 -0700299 String callingPackage, Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700300 // Not supported from remote connection service.
Santos Cordon52d8a152014-06-17 19:08:45 -0700301 }
Tyler Gunn8d83fa92014-07-01 11:31:21 -0700302
Sailesh Nepal33aaae42014-07-07 22:49:44 -0700303 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700304 public void setVideoProvider(String callId, IVideoProvider videoProvider,
305 Session.Info sessionInfo) {
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800306
307 String callingPackage = mOurConnectionServiceImpl.getApplicationContext()
308 .getOpPackageName();
Tyler Gunn159f35c2017-03-02 09:28:37 -0800309 int targetSdkVersion = mOurConnectionServiceImpl.getApplicationInfo().targetSdkVersion;
Sailesh Nepal11aeae52015-01-28 16:54:09 -0800310 RemoteConnection.VideoProvider remoteVideoProvider = null;
311 if (videoProvider != null) {
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800312 remoteVideoProvider = new RemoteConnection.VideoProvider(videoProvider,
Tyler Gunn159f35c2017-03-02 09:28:37 -0800313 callingPackage, targetSdkVersion);
Sailesh Nepal11aeae52015-01-28 16:54:09 -0800314 }
Ihab Awada64627c2014-08-20 09:36:40 -0700315 findConnectionForAction(callId, "setVideoProvider")
Sailesh Nepal11aeae52015-01-28 16:54:09 -0800316 .setVideoProvider(remoteVideoProvider);
Tyler Gunnaa07df82014-07-17 07:50:22 -0700317 }
318
319 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700320 public void setVideoState(String callId, int videoState, Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700321 findConnectionForAction(callId, "setVideoState")
322 .setVideoState(videoState);
Sailesh Nepal33aaae42014-07-07 22:49:44 -0700323 }
Sailesh Nepale7ef59a2014-07-08 21:48:22 -0700324
Sailesh Nepale7ef59a2014-07-08 21:48:22 -0700325 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700326 public void setIsVoipAudioMode(String callId, boolean isVoip, Session.Info sessionInfo) {
Andrew Lee100e2932014-09-08 15:34:24 -0700327 findConnectionForAction(callId, "setIsVoipAudioMode")
328 .setIsVoipAudioMode(isVoip);
Sailesh Nepale7ef59a2014-07-08 21:48:22 -0700329 }
Sailesh Nepal61203862014-07-11 14:50:13 -0700330
331 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700332 public void setStatusHints(String callId, StatusHints statusHints,
333 Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700334 findConnectionForAction(callId, "setStatusHints")
335 .setStatusHints(statusHints);
Sailesh Nepal61203862014-07-11 14:50:13 -0700336 }
337
338 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700339 public void setAddress(String callId, Uri address, int presentation,
340 Session.Info sessionInfo) {
Andrew Lee100e2932014-09-08 15:34:24 -0700341 findConnectionForAction(callId, "setAddress")
342 .setAddress(address, presentation);
Sailesh Nepal61203862014-07-11 14:50:13 -0700343 }
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -0700344
345 @Override
Ihab Awad5d0410f2014-07-30 10:07:40 -0700346 public void setCallerDisplayName(String callId, String callerDisplayName,
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700347 int presentation, Session.Info sessionInfo) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700348 findConnectionForAction(callId, "setCallerDisplayName")
349 .setCallerDisplayName(callerDisplayName, presentation);
350 }
351
352 @Override
Ihab Awad5d0410f2014-07-30 10:07:40 -0700353 public IBinder asBinder() {
354 throw new UnsupportedOperationException();
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -0700355 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700356
357 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700358 public final void setConferenceableConnections(String callId,
359 List<String> conferenceableConnectionIds, Session.Info sessionInfo) {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700360 List<RemoteConnection> conferenceable = new ArrayList<>();
361 for (String id : conferenceableConnectionIds) {
362 if (mConnectionById.containsKey(id)) {
363 conferenceable.add(mConnectionById.get(id));
364 }
365 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700366
Ihab Awad50e35062014-09-30 09:17:03 -0700367 if (hasConnection(callId)) {
368 findConnectionForAction(callId, "setConferenceableConnections")
369 .setConferenceableConnections(conferenceable);
370 } else {
371 findConferenceForAction(callId, "setConferenceableConnections")
372 .setConferenceableConnections(conferenceable);
373 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700374 }
Tyler Gunn4a57b9b2014-10-30 14:27:48 -0700375
376 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700377 public void addExistingConnection(String callId, ParcelableConnection connection,
378 Session.Info sessionInfo) {
Tyler Gunn2d4fcc12021-06-24 11:25:07 -0700379 Log.i(RemoteConnectionService.this, "addExistingConnection: callId=%s, conn=%s", callId,
380 connection);
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800381 String callingPackage = mOurConnectionServiceImpl.getApplicationContext().
382 getOpPackageName();
Tyler Gunn159f35c2017-03-02 09:28:37 -0800383 int callingTargetSdkVersion = mOurConnectionServiceImpl.getApplicationInfo()
384 .targetSdkVersion;
Tyler Gunncd6ccfd2016-10-17 15:48:19 -0700385 RemoteConnection remoteConnection = new RemoteConnection(callId,
Tyler Gunn159f35c2017-03-02 09:28:37 -0800386 mOutgoingConnectionServiceRpc, connection, callingPackage,
387 callingTargetSdkVersion);
Tyler Gunnc59fd0c2020-04-17 14:03:35 -0700388 // Track that it is via a remote connection.
389 Bundle newExtras = new Bundle();
390 newExtras.putParcelable(Connection.EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE,
391 connection.getPhoneAccount());
Tyler Gunn2d4fcc12021-06-24 11:25:07 -0700392 if (connection.getParentCallId() != null) {
393 RemoteConference parentConf = mConferenceById.get(connection.getParentCallId());
394 // If there is a parent being set, we need to stash the conference ID here.
395 // Telephony can add an existing connection while specifying a parent conference.
396 // There is no equivalent version of that operation as part of the remote connection
397 // API, so we will stash the pre-defined parent's ID in the extras. When the
398 // connectionmanager copies over the extras from the remote connection to the
399 // actual one, it'll get passed to Telecom so that it can make the association.
400 if (parentConf != null) {
401 newExtras.putString(Connection.EXTRA_ADD_TO_CONFERENCE_ID, parentConf.getId());
402 Log.i(this, "addExistingConnection: stash parent of %s as %s",
403 connection.getParentCallId(), parentConf.getId());
404 }
405 }
Tyler Gunnc59fd0c2020-04-17 14:03:35 -0700406 remoteConnection.putExtras(newExtras);
Tyler Gunncd6ccfd2016-10-17 15:48:19 -0700407 mConnectionById.put(callId, remoteConnection);
408 remoteConnection.registerCallback(new RemoteConnection.Callback() {
409 @Override
410 public void onDestroyed(RemoteConnection connection) {
411 mConnectionById.remove(callId);
412 maybeDisconnectAdapter();
413 }
414 });
415 mOurConnectionServiceImpl.addRemoteExistingConnection(remoteConnection);
Tyler Gunn4a57b9b2014-10-30 14:27:48 -0700416 }
Santos Cordon6b7f9552015-05-27 17:21:45 -0700417
418 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700419 public void putExtras(String callId, Bundle extras, Session.Info sessionInfo) {
Tyler Gunndee56a82016-03-23 16:06:34 -0700420 if (hasConnection(callId)) {
421 findConnectionForAction(callId, "putExtras").putExtras(extras);
Santos Cordon6b7f9552015-05-27 17:21:45 -0700422 } else {
Tyler Gunndee56a82016-03-23 16:06:34 -0700423 findConferenceForAction(callId, "putExtras").putExtras(extras);
424 }
425 }
426
427 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700428 public void removeExtras(String callId, List<String> keys, Session.Info sessionInfo) {
Tyler Gunndee56a82016-03-23 16:06:34 -0700429 if (hasConnection(callId)) {
430 findConnectionForAction(callId, "removeExtra").removeExtras(keys);
431 } else {
432 findConferenceForAction(callId, "removeExtra").removeExtras(keys);
Santos Cordon6b7f9552015-05-27 17:21:45 -0700433 }
434 }
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -0800435
436 @Override
Hall Liua98f58b52017-11-07 17:59:28 -0800437 public void setAudioRoute(String callId, int audioRoute, String bluetoothAddress,
438 Session.Info sessionInfo) {
Tyler Gunnf5035432017-01-09 09:43:12 -0800439 if (hasConnection(callId)) {
440 // TODO(3pcalls): handle this for remote connections.
441 // Likely we don't want to do anything since it doesn't make sense for self-managed
442 // connections to go through a connection mgr.
443 }
444 }
445
446 @Override
Brad Ebinger4d75bee2016-10-28 12:29:55 -0700447 public void onConnectionEvent(String callId, String event, Bundle extras,
448 Session.Info sessionInfo) {
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -0800449 if (mConnectionById.containsKey(callId)) {
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700450 findConnectionForAction(callId, "onConnectionEvent").onConnectionEvent(event,
451 extras);
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -0800452 }
453 }
Hall Liu57006aa2017-02-06 10:49:48 -0800454
455 @Override
456 public void onRttInitiationSuccess(String callId, Session.Info sessionInfo)
457 throws RemoteException {
458 if (hasConnection(callId)) {
459 findConnectionForAction(callId, "onRttInitiationSuccess")
460 .onRttInitiationSuccess();
461 } else {
462 Log.w(this, "onRttInitiationSuccess called on a remote conference");
463 }
464 }
465
466 @Override
467 public void onRttInitiationFailure(String callId, int reason, Session.Info sessionInfo)
468 throws RemoteException {
469 if (hasConnection(callId)) {
470 findConnectionForAction(callId, "onRttInitiationFailure")
471 .onRttInitiationFailure(reason);
472 } else {
473 Log.w(this, "onRttInitiationFailure called on a remote conference");
474 }
475 }
476
477 @Override
478 public void onRttSessionRemotelyTerminated(String callId, Session.Info sessionInfo)
479 throws RemoteException {
480 if (hasConnection(callId)) {
481 findConnectionForAction(callId, "onRttSessionRemotelyTerminated")
482 .onRttSessionRemotelyTerminated();
483 } else {
484 Log.w(this, "onRttSessionRemotelyTerminated called on a remote conference");
485 }
486 }
487
488 @Override
489 public void onRemoteRttRequest(String callId, Session.Info sessionInfo)
490 throws RemoteException {
491 if (hasConnection(callId)) {
492 findConnectionForAction(callId, "onRemoteRttRequest")
493 .onRemoteRttRequest();
494 } else {
495 Log.w(this, "onRemoteRttRequest called on a remote conference");
496 }
497 }
Mengjun Leng25707742017-07-04 11:10:37 +0800498
499 @Override
500 public void resetConnectionTime(String callId, Session.Info sessionInfo) {
501 // Do nothing
502 }
Tyler Gunn68a73a42018-10-03 15:38:57 -0700503
504 @Override
505 public void setConferenceState(String callId, boolean isConference,
506 Session.Info sessionInfo) {
507 // Do nothing
508 }
Brad Ebingere0c12f42020-04-08 16:25:12 -0700509
510 @Override
511 public void setCallDirection(String callId, int direction, Session.Info sessionInfo) {
512 // Do nothing
513 }
Junhoedf3d822022-11-24 09:26:37 +0000514
515 @Override
516 public void requestCallEndpointChange(String callId, CallEndpoint endpoint,
517 ResultReceiver callback, Session.Info sessionInfo) {
518 // Do nothing
519 }
yongnamcha8ec56242022-11-28 06:23:02 +0000520
521 @Override
522 public void queryLocation(String callId, long timeoutMillis, String provider,
523 ResultReceiver callback, Session.Info sessionInfo) {
524 // Do nothing
525 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700526 };
527
Ihab Awad5d0410f2014-07-30 10:07:40 -0700528 private final ConnectionServiceAdapterServant mServant =
529 new ConnectionServiceAdapterServant(mServantDelegate);
Santos Cordon52d8a152014-06-17 19:08:45 -0700530
Ihab Awad5d0410f2014-07-30 10:07:40 -0700531 private final DeathRecipient mDeathRecipient = new DeathRecipient() {
532 @Override
533 public void binderDied() {
534 for (RemoteConnection c : mConnectionById.values()) {
535 c.setDestroyed();
536 }
Ihab Awadb8e85c72014-08-23 20:34:57 -0700537 for (RemoteConference c : mConferenceById.values()) {
538 c.setDestroyed();
539 }
Ihab Awad5d0410f2014-07-30 10:07:40 -0700540 mConnectionById.clear();
Ihab Awadb8e85c72014-08-23 20:34:57 -0700541 mConferenceById.clear();
Ihab Awad5d0410f2014-07-30 10:07:40 -0700542 mPendingConnections.clear();
Ihab Awadb8e85c72014-08-23 20:34:57 -0700543 mOutgoingConnectionServiceRpc.asBinder().unlinkToDeath(mDeathRecipient, 0);
Ihab Awad5d0410f2014-07-30 10:07:40 -0700544 }
545 };
546
Ihab Awadb8e85c72014-08-23 20:34:57 -0700547 private final IConnectionService mOutgoingConnectionServiceRpc;
548 private final ConnectionService mOurConnectionServiceImpl;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700549 private final Map<String, RemoteConnection> mConnectionById = new HashMap<>();
Ihab Awadb8e85c72014-08-23 20:34:57 -0700550 private final Map<String, RemoteConference> mConferenceById = new HashMap<>();
Ihab Awad5d0410f2014-07-30 10:07:40 -0700551 private final Set<RemoteConnection> mPendingConnections = new HashSet<>();
552
Ihab Awadb8e85c72014-08-23 20:34:57 -0700553 RemoteConnectionService(
554 IConnectionService outgoingConnectionServiceRpc,
555 ConnectionService ourConnectionServiceImpl) throws RemoteException {
556 mOutgoingConnectionServiceRpc = outgoingConnectionServiceRpc;
557 mOutgoingConnectionServiceRpc.asBinder().linkToDeath(mDeathRecipient, 0);
558 mOurConnectionServiceImpl = ourConnectionServiceImpl;
Santos Cordon52d8a152014-06-17 19:08:45 -0700559 }
560
561 @Override
562 public String toString() {
Ihab Awadb8e85c72014-08-23 20:34:57 -0700563 return "[RemoteCS - " + mOutgoingConnectionServiceRpc.asBinder().toString() + "]";
Santos Cordon52d8a152014-06-17 19:08:45 -0700564 }
565
Ihab Awadf8b69882014-07-25 15:14:01 -0700566 final RemoteConnection createRemoteConnection(
567 PhoneAccountHandle connectionManagerPhoneAccount,
568 ConnectionRequest request,
569 boolean isIncoming) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700570 final String id = UUID.randomUUID().toString();
Tyler Gunnc59fd0c2020-04-17 14:03:35 -0700571 Bundle extras = new Bundle();
572 if (request.getExtras() != null) {
573 extras.putAll(request.getExtras());
574 }
575 // We will set the package name for the originator of the remote request; this lets the
576 // receiving ConnectionService know that the request originated from a remote connection
577 // service so that it can provide tracking information for Telecom.
578 extras.putString(Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME,
579 mOurConnectionServiceImpl.getApplicationContext().getOpPackageName());
580
Hall Liu95d55872017-01-25 17:12:49 -0800581 final ConnectionRequest newRequest = new ConnectionRequest.Builder()
582 .setAccountHandle(request.getAccountHandle())
583 .setAddress(request.getAddress())
Tyler Gunnc59fd0c2020-04-17 14:03:35 -0700584 .setExtras(extras)
Hall Liu95d55872017-01-25 17:12:49 -0800585 .setVideoState(request.getVideoState())
586 .setRttPipeFromInCall(request.getRttPipeFromInCall())
587 .setRttPipeToInCall(request.getRttPipeToInCall())
588 .build();
Ihab Awad5d0410f2014-07-30 10:07:40 -0700589 try {
Ihab Awad8aecfed2014-08-08 17:06:11 -0700590 if (mConnectionById.isEmpty()) {
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700591 mOutgoingConnectionServiceRpc.addConnectionServiceAdapter(mServant.getStub(),
592 null /*Session.Info*/);
Ihab Awad8aecfed2014-08-08 17:06:11 -0700593 }
594 RemoteConnection connection =
Ihab Awadb8e85c72014-08-23 20:34:57 -0700595 new RemoteConnection(id, mOutgoingConnectionServiceRpc, newRequest);
Ihab Awad8aecfed2014-08-08 17:06:11 -0700596 mPendingConnections.add(connection);
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700597 mConnectionById.put(id, connection);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700598 mOutgoingConnectionServiceRpc.createConnection(
Ihab Awad5d0410f2014-07-30 10:07:40 -0700599 connectionManagerPhoneAccount,
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700600 id,
Ihab Awad5d0410f2014-07-30 10:07:40 -0700601 newRequest,
Yorke Leec3cf9822014-10-02 09:38:39 -0700602 isIncoming,
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700603 false /* isUnknownCall */,
604 null /*Session.info*/);
Andrew Lee100e2932014-09-08 15:34:24 -0700605 connection.registerCallback(new RemoteConnection.Callback() {
Ihab Awad8aecfed2014-08-08 17:06:11 -0700606 @Override
607 public void onDestroyed(RemoteConnection connection) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700608 mConnectionById.remove(id);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700609 maybeDisconnectAdapter();
Ihab Awad8aecfed2014-08-08 17:06:11 -0700610 }
611 });
Ihab Awad5d0410f2014-07-30 10:07:40 -0700612 return connection;
613 } catch (RemoteException e) {
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700614 return RemoteConnection.failure(
615 new DisconnectCause(DisconnectCause.ERROR, e.toString()));
Santos Cordon52d8a152014-06-17 19:08:45 -0700616 }
617 }
618
Grace Jia9a09c672020-08-04 12:52:09 -0700619 RemoteConference createRemoteConference(
620 PhoneAccountHandle connectionManagerPhoneAccount,
621 ConnectionRequest request,
622 boolean isIncoming) {
623 final String id = UUID.randomUUID().toString();
624 try {
625 if (mConferenceById.isEmpty()) {
626 mOutgoingConnectionServiceRpc.addConnectionServiceAdapter(mServant.getStub(),
627 null /*Session.Info*/);
628 }
629 RemoteConference conference = new RemoteConference(id, mOutgoingConnectionServiceRpc);
630 mOutgoingConnectionServiceRpc.createConference(connectionManagerPhoneAccount,
631 id,
632 request,
633 isIncoming,
634 false /* isUnknownCall */,
635 null /*Session.info*/);
636 conference.registerCallback(new RemoteConference.Callback() {
637 @Override
638 public void onDestroyed(RemoteConference conference) {
639 mConferenceById.remove(id);
640 maybeDisconnectAdapter();
641 }
642 });
643 conference.putExtras(request.getExtras());
644 return conference;
645 } catch (RemoteException e) {
646 return RemoteConference.failure(
647 new DisconnectCause(DisconnectCause.ERROR, e.toString()));
648 }
649 }
650
Ihab Awad50e35062014-09-30 09:17:03 -0700651 private boolean hasConnection(String callId) {
mike dooley879142b2014-10-08 13:39:28 -0700652 return mConnectionById.containsKey(callId);
Ihab Awad50e35062014-09-30 09:17:03 -0700653 }
654
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700655 private RemoteConnection findConnectionForAction(
656 String callId, String action) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700657 if (mConnectionById.containsKey(callId)) {
658 return mConnectionById.get(callId);
659 }
660 Log.w(this, "%s - Cannot find Connection %s", action, callId);
661 return NULL_CONNECTION;
Santos Cordon52d8a152014-06-17 19:08:45 -0700662 }
Ihab Awadb8e85c72014-08-23 20:34:57 -0700663
664 private RemoteConference findConferenceForAction(
665 String callId, String action) {
666 if (mConferenceById.containsKey(callId)) {
667 return mConferenceById.get(callId);
668 }
669 Log.w(this, "%s - Cannot find Conference %s", action, callId);
670 return NULL_CONFERENCE;
671 }
672
673 private void maybeDisconnectAdapter() {
674 if (mConnectionById.isEmpty() && mConferenceById.isEmpty()) {
675 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700676 mOutgoingConnectionServiceRpc.removeConnectionServiceAdapter(mServant.getStub(),
677 null /*Session.info*/);
Ihab Awadb8e85c72014-08-23 20:34:57 -0700678 } catch (RemoteException e) {
679 }
680 }
681 }
Santos Cordon52d8a152014-06-17 19:08:45 -0700682}