blob: dc756727aacdc2d14b010a47dc433301e68d824f [file] [log] [blame]
Ihab Awad542e0ea2014-05-16 10:22:16 -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
14 * limitations under the License.
15 */
16
Tyler Gunnef9f6f92014-09-12 22:16:17 -070017package android.telecom;
Ihab Awad542e0ea2014-05-16 10:22:16 -070018
Santos Cordon5c6fa952014-07-20 17:47:12 -070019import android.annotation.SdkConstant;
Sailesh Nepal2a46b902014-07-04 17:21:07 -070020import android.app.Service;
Santos Cordon52d8a152014-06-17 19:08:45 -070021import android.content.ComponentName;
Santos Cordon5c6fa952014-07-20 17:47:12 -070022import android.content.Intent;
Ihab Awad542e0ea2014-05-16 10:22:16 -070023import android.net.Uri;
Santos Cordon6b7f9552015-05-27 17:21:45 -070024import android.os.Bundle;
Santos Cordon52d8a152014-06-17 19:08:45 -070025import android.os.Handler;
26import android.os.IBinder;
27import android.os.Looper;
Sailesh Nepal2a46b902014-07-04 17:21:07 -070028import android.os.Message;
Hall Liub64ac4c2017-02-06 10:49:48 -080029import android.os.ParcelFileDescriptor;
30import android.os.RemoteException;
Brad Ebingerb32d4f82016-10-24 16:40:49 -070031import android.telecom.Logging.Session;
Andrew Lee14185762014-07-25 09:41:56 -070032
Sailesh Nepal2a46b902014-07-04 17:21:07 -070033import com.android.internal.os.SomeArgs;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070034import com.android.internal.telecom.IConnectionService;
35import com.android.internal.telecom.IConnectionServiceAdapter;
36import com.android.internal.telecom.RemoteServiceCallback;
Santos Cordon52d8a152014-06-17 19:08:45 -070037
Ihab Awad5d0410f2014-07-30 10:07:40 -070038import java.util.ArrayList;
Santos Cordonb6939982014-06-04 20:20:58 -070039import java.util.Collection;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070040import java.util.Collections;
Santos Cordon52d8a152014-06-17 19:08:45 -070041import java.util.List;
Ihab Awad542e0ea2014-05-16 10:22:16 -070042import java.util.Map;
Santos Cordon823fd3c2014-08-07 18:35:18 -070043import java.util.UUID;
mike dooley95e80702014-09-18 14:07:52 -070044import java.util.concurrent.ConcurrentHashMap;
Ihab Awad542e0ea2014-05-16 10:22:16 -070045
46/**
Tyler Gunnf5035432017-01-09 09:43:12 -080047 * An abstract service that should be implemented by any apps which either:
48 * <ol>
49 * <li>Can make phone calls (VoIP or otherwise) and want those calls to be integrated into the
50 * built-in phone app. Referred to as a <b>system managed</b> {@link ConnectionService}.</li>
51 * <li>Are a standalone calling app and don't want their calls to be integrated into the
52 * built-in phone app. Referred to as a <b>self managed</b> {@link ConnectionService}.</li>
53 * </ol>
54 * Once implemented, the {@link ConnectionService} needs to take the following steps so that Telecom
55 * will bind to it:
Santos Cordona663f862014-10-29 13:49:58 -070056 * <p>
57 * 1. <i>Registration in AndroidManifest.xml</i>
58 * <br/>
59 * <pre>
60 * &lt;service android:name="com.example.package.MyConnectionService"
61 * android:label="@string/some_label_for_my_connection_service"
Yorke Lee249c12e2015-05-13 15:59:29 -070062 * android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"&gt;
Santos Cordona663f862014-10-29 13:49:58 -070063 * &lt;intent-filter&gt;
64 * &lt;action android:name="android.telecom.ConnectionService" /&gt;
65 * &lt;/intent-filter&gt;
66 * &lt;/service&gt;
67 * </pre>
68 * <p>
69 * 2. <i> Registration of {@link PhoneAccount} with {@link TelecomManager}.</i>
70 * <br/>
71 * See {@link PhoneAccount} and {@link TelecomManager#registerPhoneAccount} for more information.
72 * <p>
Tyler Gunnf5035432017-01-09 09:43:12 -080073 * System managed {@link ConnectionService}s must be enabled by the user in the phone app settings
74 * before Telecom will bind to them. Self-manged {@link ConnectionService}s must be granted the
75 * appropriate permission before Telecom will bind to them.
76 * <p>
77 * Once registered and enabled by the user in the phone app settings or granted permission, telecom
78 * will bind to a {@link ConnectionService} implementation when it wants that
79 * {@link ConnectionService} to place a call or the service has indicated that is has an incoming
80 * call through {@link TelecomManager#addNewIncomingCall}. The {@link ConnectionService} can then
81 * expect a call to {@link #onCreateIncomingConnection} or {@link #onCreateOutgoingConnection}
82 * wherein it should provide a new instance of a {@link Connection} object. It is through this
83 * {@link Connection} object that telecom receives state updates and the {@link ConnectionService}
Santos Cordona663f862014-10-29 13:49:58 -070084 * receives call-commands such as answer, reject, hold and disconnect.
85 * <p>
Tyler Gunnf5035432017-01-09 09:43:12 -080086 * When there are no more live calls, telecom will unbind from the {@link ConnectionService}.
Ihab Awad542e0ea2014-05-16 10:22:16 -070087 */
Sailesh Nepal2a46b902014-07-04 17:21:07 -070088public abstract class ConnectionService extends Service {
Santos Cordon5c6fa952014-07-20 17:47:12 -070089 /**
90 * The {@link Intent} that must be declared as handled by the service.
91 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -070092 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
Tyler Gunnef9f6f92014-09-12 22:16:17 -070093 public static final String SERVICE_INTERFACE = "android.telecom.ConnectionService";
Santos Cordon5c6fa952014-07-20 17:47:12 -070094
Tyler Gunn8bf76572017-04-06 15:30:08 -070095 /**
96 * Boolean extra used by Telecom to inform a {@link ConnectionService} that the purpose of it
97 * being asked to create a new outgoing {@link Connection} is to perform a handover of an
98 * ongoing call on the device from another {@link PhoneAccount}/{@link ConnectionService}. Will
99 * be specified in the {@link ConnectionRequest#getExtras()} passed by Telecom when
100 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)} is called.
101 * <p>
Tyler Gunn727c6bd2017-04-11 09:51:40 -0700102 * When your {@link ConnectionService} receives this extra, it should communicate the fact that
103 * this is a handover to the other device's matching {@link ConnectionService}. That
Tyler Gunn8bf76572017-04-06 15:30:08 -0700104 * {@link ConnectionService} will continue the handover using
105 * {@link TelecomManager#addNewIncomingCall(PhoneAccountHandle, Bundle)}, specifying
Tyler Gunn727c6bd2017-04-11 09:51:40 -0700106 * {@link TelecomManager#EXTRA_IS_HANDOVER}. Telecom will match the phone numbers of the
107 * handover call on the other device with ongoing calls for {@link ConnectionService}s which
108 * support {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700109 * @hide
110 */
111 public static final String EXTRA_IS_HANDOVER = TelecomManager.EXTRA_IS_HANDOVER;
112
Ihab Awad542e0ea2014-05-16 10:22:16 -0700113 // Flag controlling whether PII is emitted into the logs
Ihab Awad60ac30b2014-05-20 22:32:12 -0700114 private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700115
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700116 // Session Definitions
117 private static final String SESSION_HANDLER = "H.";
118 private static final String SESSION_ADD_CS_ADAPTER = "CS.aCSA";
119 private static final String SESSION_REMOVE_CS_ADAPTER = "CS.rCSA";
120 private static final String SESSION_CREATE_CONN = "CS.crCo";
Tyler Gunn44e01912017-01-31 10:49:05 -0800121 private static final String SESSION_CREATE_CONN_FAILED = "CS.crCoF";
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700122 private static final String SESSION_ABORT = "CS.ab";
123 private static final String SESSION_ANSWER = "CS.an";
124 private static final String SESSION_ANSWER_VIDEO = "CS.anV";
125 private static final String SESSION_REJECT = "CS.r";
126 private static final String SESSION_REJECT_MESSAGE = "CS.rWM";
127 private static final String SESSION_SILENCE = "CS.s";
128 private static final String SESSION_DISCONNECT = "CS.d";
129 private static final String SESSION_HOLD = "CS.h";
130 private static final String SESSION_UNHOLD = "CS.u";
131 private static final String SESSION_CALL_AUDIO_SC = "CS.cASC";
132 private static final String SESSION_PLAY_DTMF = "CS.pDT";
133 private static final String SESSION_STOP_DTMF = "CS.sDT";
134 private static final String SESSION_CONFERENCE = "CS.c";
135 private static final String SESSION_SPLIT_CONFERENCE = "CS.sFC";
136 private static final String SESSION_MERGE_CONFERENCE = "CS.mC";
137 private static final String SESSION_SWAP_CONFERENCE = "CS.sC";
138 private static final String SESSION_POST_DIAL_CONT = "CS.oPDC";
139 private static final String SESSION_PULL_EXTERNAL_CALL = "CS.pEC";
140 private static final String SESSION_SEND_CALL_EVENT = "CS.sCE";
141 private static final String SESSION_EXTRAS_CHANGED = "CS.oEC";
Hall Liub64ac4c2017-02-06 10:49:48 -0800142 private static final String SESSION_START_RTT = "CS.+RTT";
143 private static final String SESSION_STOP_RTT = "CS.-RTT";
144 private static final String SESSION_RTT_UPGRADE_RESPONSE = "CS.rTRUR";
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700145
Ihab Awad8aecfed2014-08-08 17:06:11 -0700146 private static final int MSG_ADD_CONNECTION_SERVICE_ADAPTER = 1;
Sailesh Nepalc5b01572014-07-14 16:29:44 -0700147 private static final int MSG_CREATE_CONNECTION = 2;
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700148 private static final int MSG_ABORT = 3;
Sailesh Nepalc5b01572014-07-14 16:29:44 -0700149 private static final int MSG_ANSWER = 4;
150 private static final int MSG_REJECT = 5;
151 private static final int MSG_DISCONNECT = 6;
152 private static final int MSG_HOLD = 7;
153 private static final int MSG_UNHOLD = 8;
Yorke Lee4af59352015-05-13 14:14:54 -0700154 private static final int MSG_ON_CALL_AUDIO_STATE_CHANGED = 9;
Sailesh Nepalc5b01572014-07-14 16:29:44 -0700155 private static final int MSG_PLAY_DTMF_TONE = 10;
156 private static final int MSG_STOP_DTMF_TONE = 11;
157 private static final int MSG_CONFERENCE = 12;
158 private static final int MSG_SPLIT_FROM_CONFERENCE = 13;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700159 private static final int MSG_ON_POST_DIAL_CONTINUE = 14;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700160 private static final int MSG_REMOVE_CONNECTION_SERVICE_ADAPTER = 16;
Tyler Gunnbe74de02014-08-29 14:51:48 -0700161 private static final int MSG_ANSWER_VIDEO = 17;
Santos Cordona4868042014-09-04 17:39:22 -0700162 private static final int MSG_MERGE_CONFERENCE = 18;
163 private static final int MSG_SWAP_CONFERENCE = 19;
Bryce Lee81901682015-08-28 16:38:02 -0700164 private static final int MSG_REJECT_WITH_MESSAGE = 20;
Bryce Leecac50772015-11-17 15:13:29 -0800165 private static final int MSG_SILENCE = 21;
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700166 private static final int MSG_PULL_EXTERNAL_CALL = 22;
167 private static final int MSG_SEND_CALL_EVENT = 23;
Tyler Gunndee56a82016-03-23 16:06:34 -0700168 private static final int MSG_ON_EXTRAS_CHANGED = 24;
Tyler Gunn44e01912017-01-31 10:49:05 -0800169 private static final int MSG_CREATE_CONNECTION_FAILED = 25;
Hall Liub64ac4c2017-02-06 10:49:48 -0800170 private static final int MSG_ON_START_RTT = 26;
171 private static final int MSG_ON_STOP_RTT = 27;
172 private static final int MSG_RTT_UPGRADE_RESPONSE = 28;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700173
Sailesh Nepalcf7020b2014-08-20 10:07:19 -0700174 private static Connection sNullConnection;
175
mike dooley95e80702014-09-18 14:07:52 -0700176 private final Map<String, Connection> mConnectionById = new ConcurrentHashMap<>();
177 private final Map<Connection, String> mIdByConnection = new ConcurrentHashMap<>();
178 private final Map<String, Conference> mConferenceById = new ConcurrentHashMap<>();
179 private final Map<Conference, String> mIdByConference = new ConcurrentHashMap<>();
Ihab Awadb8e85c72014-08-23 20:34:57 -0700180 private final RemoteConnectionManager mRemoteConnectionManager =
181 new RemoteConnectionManager(this);
Ihab Awad5d0410f2014-07-30 10:07:40 -0700182 private final List<Runnable> mPreInitializationConnectionRequests = new ArrayList<>();
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700183 private final ConnectionServiceAdapter mAdapter = new ConnectionServiceAdapter();
Ihab Awad542e0ea2014-05-16 10:22:16 -0700184
Santos Cordon823fd3c2014-08-07 18:35:18 -0700185 private boolean mAreAccountsInitialized = false;
Santos Cordon0159ac02014-08-21 14:28:11 -0700186 private Conference sNullConference;
Tyler Gunnf0500bd2015-09-01 10:59:48 -0700187 private Object mIdSyncRoot = new Object();
188 private int mId = 0;
Santos Cordon823fd3c2014-08-07 18:35:18 -0700189
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700190 private final IBinder mBinder = new IConnectionService.Stub() {
191 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700192 public void addConnectionServiceAdapter(IConnectionServiceAdapter adapter,
193 Session.Info sessionInfo) {
194 Log.startSession(sessionInfo, SESSION_ADD_CS_ADAPTER);
195 try {
196 SomeArgs args = SomeArgs.obtain();
197 args.arg1 = adapter;
198 args.arg2 = Log.createSubsession();
199 mHandler.obtainMessage(MSG_ADD_CONNECTION_SERVICE_ADAPTER, args).sendToTarget();
200 } finally {
201 Log.endSession();
202 }
Ihab Awad8aecfed2014-08-08 17:06:11 -0700203 }
204
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700205 public void removeConnectionServiceAdapter(IConnectionServiceAdapter adapter,
206 Session.Info sessionInfo) {
207 Log.startSession(sessionInfo, SESSION_REMOVE_CS_ADAPTER);
208 try {
209 SomeArgs args = SomeArgs.obtain();
210 args.arg1 = adapter;
211 args.arg2 = Log.createSubsession();
212 mHandler.obtainMessage(MSG_REMOVE_CONNECTION_SERVICE_ADAPTER, args).sendToTarget();
213 } finally {
214 Log.endSession();
215 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700216 }
217
218 @Override
Ihab Awadf8b69882014-07-25 15:14:01 -0700219 public void createConnection(
220 PhoneAccountHandle connectionManagerPhoneAccount,
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700221 String id,
Ihab Awadf8b69882014-07-25 15:14:01 -0700222 ConnectionRequest request,
Yorke Leec3cf9822014-10-02 09:38:39 -0700223 boolean isIncoming,
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700224 boolean isUnknown,
225 Session.Info sessionInfo) {
226 Log.startSession(sessionInfo, SESSION_CREATE_CONN);
227 try {
228 SomeArgs args = SomeArgs.obtain();
229 args.arg1 = connectionManagerPhoneAccount;
230 args.arg2 = id;
231 args.arg3 = request;
232 args.arg4 = Log.createSubsession();
233 args.argi1 = isIncoming ? 1 : 0;
234 args.argi2 = isUnknown ? 1 : 0;
235 mHandler.obtainMessage(MSG_CREATE_CONNECTION, args).sendToTarget();
236 } finally {
237 Log.endSession();
238 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700239 }
240
241 @Override
Tyler Gunn44e01912017-01-31 10:49:05 -0800242 public void createConnectionFailed(
Tyler Gunn159f35c2017-03-02 09:28:37 -0800243 PhoneAccountHandle connectionManagerPhoneAccount,
Tyler Gunn44e01912017-01-31 10:49:05 -0800244 String callId,
245 ConnectionRequest request,
246 boolean isIncoming,
247 Session.Info sessionInfo) {
248 Log.startSession(sessionInfo, SESSION_CREATE_CONN_FAILED);
249 try {
250 SomeArgs args = SomeArgs.obtain();
251 args.arg1 = callId;
252 args.arg2 = request;
253 args.arg3 = Log.createSubsession();
Tyler Gunn159f35c2017-03-02 09:28:37 -0800254 args.arg4 = connectionManagerPhoneAccount;
Tyler Gunn44e01912017-01-31 10:49:05 -0800255 args.argi1 = isIncoming ? 1 : 0;
256 mHandler.obtainMessage(MSG_CREATE_CONNECTION_FAILED, args).sendToTarget();
257 } finally {
258 Log.endSession();
259 }
260 }
261
262 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700263 public void abort(String callId, Session.Info sessionInfo) {
264 Log.startSession(sessionInfo, SESSION_ABORT);
265 try {
266 SomeArgs args = SomeArgs.obtain();
267 args.arg1 = callId;
268 args.arg2 = Log.createSubsession();
269 mHandler.obtainMessage(MSG_ABORT, args).sendToTarget();
270 } finally {
271 Log.endSession();
272 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700273 }
274
275 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700276 public void answerVideo(String callId, int videoState, Session.Info sessionInfo) {
277 Log.startSession(sessionInfo, SESSION_ANSWER_VIDEO);
278 try {
279 SomeArgs args = SomeArgs.obtain();
280 args.arg1 = callId;
281 args.arg2 = Log.createSubsession();
282 args.argi1 = videoState;
283 mHandler.obtainMessage(MSG_ANSWER_VIDEO, args).sendToTarget();
284 } finally {
285 Log.endSession();
286 }
Tyler Gunnbe74de02014-08-29 14:51:48 -0700287 }
288
289 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700290 public void answer(String callId, Session.Info sessionInfo) {
291 Log.startSession(sessionInfo, SESSION_ANSWER);
292 try {
293 SomeArgs args = SomeArgs.obtain();
294 args.arg1 = callId;
295 args.arg2 = Log.createSubsession();
296 mHandler.obtainMessage(MSG_ANSWER, args).sendToTarget();
297 } finally {
298 Log.endSession();
299 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700300 }
301
302 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700303 public void reject(String callId, Session.Info sessionInfo) {
304 Log.startSession(sessionInfo, SESSION_REJECT);
305 try {
306 SomeArgs args = SomeArgs.obtain();
307 args.arg1 = callId;
308 args.arg2 = Log.createSubsession();
309 mHandler.obtainMessage(MSG_REJECT, args).sendToTarget();
310 } finally {
311 Log.endSession();
312 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700313 }
314
315 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700316 public void rejectWithMessage(String callId, String message, Session.Info sessionInfo) {
317 Log.startSession(sessionInfo, SESSION_REJECT_MESSAGE);
318 try {
319 SomeArgs args = SomeArgs.obtain();
320 args.arg1 = callId;
321 args.arg2 = message;
322 args.arg3 = Log.createSubsession();
323 mHandler.obtainMessage(MSG_REJECT_WITH_MESSAGE, args).sendToTarget();
324 } finally {
325 Log.endSession();
326 }
Bryce Lee81901682015-08-28 16:38:02 -0700327 }
328
329 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700330 public void silence(String callId, Session.Info sessionInfo) {
331 Log.startSession(sessionInfo, SESSION_SILENCE);
332 try {
333 SomeArgs args = SomeArgs.obtain();
334 args.arg1 = callId;
335 args.arg2 = Log.createSubsession();
336 mHandler.obtainMessage(MSG_SILENCE, args).sendToTarget();
337 } finally {
338 Log.endSession();
339 }
Bryce Leecac50772015-11-17 15:13:29 -0800340 }
341
342 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700343 public void disconnect(String callId, Session.Info sessionInfo) {
344 Log.startSession(sessionInfo, SESSION_DISCONNECT);
345 try {
346 SomeArgs args = SomeArgs.obtain();
347 args.arg1 = callId;
348 args.arg2 = Log.createSubsession();
349 mHandler.obtainMessage(MSG_DISCONNECT, args).sendToTarget();
350 } finally {
351 Log.endSession();
352 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700353 }
354
355 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700356 public void hold(String callId, Session.Info sessionInfo) {
357 Log.startSession(sessionInfo, SESSION_HOLD);
358 try {
359 SomeArgs args = SomeArgs.obtain();
360 args.arg1 = callId;
361 args.arg2 = Log.createSubsession();
362 mHandler.obtainMessage(MSG_HOLD, args).sendToTarget();
363 } finally {
364 Log.endSession();
365 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700366 }
367
368 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700369 public void unhold(String callId, Session.Info sessionInfo) {
370 Log.startSession(sessionInfo, SESSION_UNHOLD);
371 try {
372 SomeArgs args = SomeArgs.obtain();
373 args.arg1 = callId;
374 args.arg2 = Log.createSubsession();
375 mHandler.obtainMessage(MSG_UNHOLD, args).sendToTarget();
376 } finally {
377 Log.endSession();
378 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700379 }
380
381 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700382 public void onCallAudioStateChanged(String callId, CallAudioState callAudioState,
383 Session.Info sessionInfo) {
384 Log.startSession(sessionInfo, SESSION_CALL_AUDIO_SC);
385 try {
386 SomeArgs args = SomeArgs.obtain();
387 args.arg1 = callId;
388 args.arg2 = callAudioState;
389 args.arg3 = Log.createSubsession();
390 mHandler.obtainMessage(MSG_ON_CALL_AUDIO_STATE_CHANGED, args).sendToTarget();
391 } finally {
392 Log.endSession();
393 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700394 }
395
396 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700397 public void playDtmfTone(String callId, char digit, Session.Info sessionInfo) {
398 Log.startSession(sessionInfo, SESSION_PLAY_DTMF);
399 try {
400 SomeArgs args = SomeArgs.obtain();
401 args.arg1 = digit;
402 args.arg2 = callId;
403 args.arg3 = Log.createSubsession();
404 mHandler.obtainMessage(MSG_PLAY_DTMF_TONE, args).sendToTarget();
405 } finally {
406 Log.endSession();
407 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700408 }
409
410 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700411 public void stopDtmfTone(String callId, Session.Info sessionInfo) {
412 Log.startSession(sessionInfo, SESSION_STOP_DTMF);
413 try {
414 SomeArgs args = SomeArgs.obtain();
415 args.arg1 = callId;
416 args.arg2 = Log.createSubsession();
417 mHandler.obtainMessage(MSG_STOP_DTMF_TONE, args).sendToTarget();
418 } finally {
419 Log.endSession();
420 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700421 }
422
423 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700424 public void conference(String callId1, String callId2, Session.Info sessionInfo) {
425 Log.startSession(sessionInfo, SESSION_CONFERENCE);
426 try {
427 SomeArgs args = SomeArgs.obtain();
428 args.arg1 = callId1;
429 args.arg2 = callId2;
430 args.arg3 = Log.createSubsession();
431 mHandler.obtainMessage(MSG_CONFERENCE, args).sendToTarget();
432 } finally {
433 Log.endSession();
434 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700435 }
436
437 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700438 public void splitFromConference(String callId, Session.Info sessionInfo) {
439 Log.startSession(sessionInfo, SESSION_SPLIT_CONFERENCE);
440 try {
441 SomeArgs args = SomeArgs.obtain();
442 args.arg1 = callId;
443 args.arg2 = Log.createSubsession();
444 mHandler.obtainMessage(MSG_SPLIT_FROM_CONFERENCE, args).sendToTarget();
445 } finally {
446 Log.endSession();
447 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700448 }
449
450 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700451 public void mergeConference(String callId, Session.Info sessionInfo) {
452 Log.startSession(sessionInfo, SESSION_MERGE_CONFERENCE);
453 try {
454 SomeArgs args = SomeArgs.obtain();
455 args.arg1 = callId;
456 args.arg2 = Log.createSubsession();
457 mHandler.obtainMessage(MSG_MERGE_CONFERENCE, args).sendToTarget();
458 } finally {
459 Log.endSession();
460 }
Santos Cordona4868042014-09-04 17:39:22 -0700461 }
462
463 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700464 public void swapConference(String callId, Session.Info sessionInfo) {
465 Log.startSession(sessionInfo, SESSION_SWAP_CONFERENCE);
466 try {
467 SomeArgs args = SomeArgs.obtain();
468 args.arg1 = callId;
469 args.arg2 = Log.createSubsession();
470 mHandler.obtainMessage(MSG_SWAP_CONFERENCE, args).sendToTarget();
471 } finally {
472 Log.endSession();
473 }
Santos Cordona4868042014-09-04 17:39:22 -0700474 }
475
476 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700477 public void onPostDialContinue(String callId, boolean proceed, Session.Info sessionInfo) {
478 Log.startSession(sessionInfo, SESSION_POST_DIAL_CONT);
479 try {
480 SomeArgs args = SomeArgs.obtain();
481 args.arg1 = callId;
482 args.arg2 = Log.createSubsession();
483 args.argi1 = proceed ? 1 : 0;
484 mHandler.obtainMessage(MSG_ON_POST_DIAL_CONTINUE, args).sendToTarget();
485 } finally {
486 Log.endSession();
487 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700488 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700489
490 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700491 public void pullExternalCall(String callId, Session.Info sessionInfo) {
492 Log.startSession(sessionInfo, SESSION_PULL_EXTERNAL_CALL);
493 try {
494 SomeArgs args = SomeArgs.obtain();
495 args.arg1 = callId;
496 args.arg2 = Log.createSubsession();
497 mHandler.obtainMessage(MSG_PULL_EXTERNAL_CALL, args).sendToTarget();
498 } finally {
499 Log.endSession();
500 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700501 }
502
503 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700504 public void sendCallEvent(String callId, String event, Bundle extras,
505 Session.Info sessionInfo) {
506 Log.startSession(sessionInfo, SESSION_SEND_CALL_EVENT);
507 try {
508 SomeArgs args = SomeArgs.obtain();
509 args.arg1 = callId;
510 args.arg2 = event;
511 args.arg3 = extras;
512 args.arg4 = Log.createSubsession();
513 mHandler.obtainMessage(MSG_SEND_CALL_EVENT, args).sendToTarget();
514 } finally {
515 Log.endSession();
516 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700517 }
Tyler Gunndee56a82016-03-23 16:06:34 -0700518
519 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700520 public void onExtrasChanged(String callId, Bundle extras, Session.Info sessionInfo) {
521 Log.startSession(sessionInfo, SESSION_EXTRAS_CHANGED);
522 try {
523 SomeArgs args = SomeArgs.obtain();
524 args.arg1 = callId;
525 args.arg2 = extras;
526 args.arg3 = Log.createSubsession();
527 mHandler.obtainMessage(MSG_ON_EXTRAS_CHANGED, args).sendToTarget();
528 } finally {
529 Log.endSession();
530 }
Tyler Gunndee56a82016-03-23 16:06:34 -0700531 }
Hall Liub64ac4c2017-02-06 10:49:48 -0800532
533 @Override
534 public void startRtt(String callId, ParcelFileDescriptor fromInCall,
535 ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException {
536 Log.startSession(sessionInfo, SESSION_START_RTT);
537 try {
538 SomeArgs args = SomeArgs.obtain();
539 args.arg1 = callId;
540 args.arg2 = new Connection.RttTextStream(toInCall, fromInCall);
541 args.arg3 = Log.createSubsession();
542 mHandler.obtainMessage(MSG_ON_START_RTT, args).sendToTarget();
543 } finally {
544 Log.endSession();
545 }
546 }
547
548 @Override
549 public void stopRtt(String callId, Session.Info sessionInfo) throws RemoteException {
550 Log.startSession(sessionInfo, SESSION_STOP_RTT);
551 try {
552 SomeArgs args = SomeArgs.obtain();
553 args.arg1 = callId;
554 args.arg2 = Log.createSubsession();
555 mHandler.obtainMessage(MSG_ON_STOP_RTT, args).sendToTarget();
556 } finally {
557 Log.endSession();
558 }
559 }
560
561 @Override
562 public void respondToRttUpgradeRequest(String callId, ParcelFileDescriptor fromInCall,
563 ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException {
564 Log.startSession(sessionInfo, SESSION_RTT_UPGRADE_RESPONSE);
565 try {
566 SomeArgs args = SomeArgs.obtain();
567 args.arg1 = callId;
568 if (toInCall == null || fromInCall == null) {
569 args.arg2 = null;
570 } else {
571 args.arg2 = new Connection.RttTextStream(toInCall, fromInCall);
572 }
573 args.arg3 = Log.createSubsession();
574 mHandler.obtainMessage(MSG_RTT_UPGRADE_RESPONSE, args).sendToTarget();
575 } finally {
576 Log.endSession();
577 }
578 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700579 };
580
581 private final Handler mHandler = new Handler(Looper.getMainLooper()) {
582 @Override
583 public void handleMessage(Message msg) {
584 switch (msg.what) {
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700585 case MSG_ADD_CONNECTION_SERVICE_ADAPTER: {
586 SomeArgs args = (SomeArgs) msg.obj;
587 try {
588 IConnectionServiceAdapter adapter = (IConnectionServiceAdapter) args.arg1;
589 Log.continueSession((Session) args.arg2,
590 SESSION_HANDLER + SESSION_ADD_CS_ADAPTER);
591 mAdapter.addAdapter(adapter);
592 onAdapterAttached();
593 } finally {
594 args.recycle();
595 Log.endSession();
596 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700597 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700598 }
599 case MSG_REMOVE_CONNECTION_SERVICE_ADAPTER: {
600 SomeArgs args = (SomeArgs) msg.obj;
601 try {
602 Log.continueSession((Session) args.arg2,
603 SESSION_HANDLER + SESSION_REMOVE_CS_ADAPTER);
604 mAdapter.removeAdapter((IConnectionServiceAdapter) args.arg1);
605 } finally {
606 args.recycle();
607 Log.endSession();
608 }
Ihab Awad8aecfed2014-08-08 17:06:11 -0700609 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700610 }
Ihab Awadf8b69882014-07-25 15:14:01 -0700611 case MSG_CREATE_CONNECTION: {
612 SomeArgs args = (SomeArgs) msg.obj;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700613 Log.continueSession((Session) args.arg4, SESSION_HANDLER + SESSION_CREATE_CONN);
Ihab Awadf8b69882014-07-25 15:14:01 -0700614 try {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700615 final PhoneAccountHandle connectionManagerPhoneAccount =
Ihab Awadf8b69882014-07-25 15:14:01 -0700616 (PhoneAccountHandle) args.arg1;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700617 final String id = (String) args.arg2;
618 final ConnectionRequest request = (ConnectionRequest) args.arg3;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700619 final boolean isIncoming = args.argi1 == 1;
Yorke Leec3cf9822014-10-02 09:38:39 -0700620 final boolean isUnknown = args.argi2 == 1;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700621 if (!mAreAccountsInitialized) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700622 Log.d(this, "Enqueueing pre-init request %s", id);
Brad Ebinger0c3541b2016-11-01 14:11:38 -0700623 mPreInitializationConnectionRequests.add(
624 new android.telecom.Logging.Runnable(
625 SESSION_HANDLER + SESSION_CREATE_CONN + ".pICR",
626 null /*lock*/) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700627 @Override
Brad Ebinger0c3541b2016-11-01 14:11:38 -0700628 public void loggedRun() {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700629 createConnection(
630 connectionManagerPhoneAccount,
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700631 id,
Ihab Awad5d0410f2014-07-30 10:07:40 -0700632 request,
Yorke Leec3cf9822014-10-02 09:38:39 -0700633 isIncoming,
634 isUnknown);
Ihab Awad5d0410f2014-07-30 10:07:40 -0700635 }
Brad Ebinger0c3541b2016-11-01 14:11:38 -0700636 }.prepare());
Ihab Awad5d0410f2014-07-30 10:07:40 -0700637 } else {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700638 createConnection(
639 connectionManagerPhoneAccount,
640 id,
641 request,
Yorke Leec3cf9822014-10-02 09:38:39 -0700642 isIncoming,
643 isUnknown);
Ihab Awad5d0410f2014-07-30 10:07:40 -0700644 }
Ihab Awadf8b69882014-07-25 15:14:01 -0700645 } finally {
646 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700647 Log.endSession();
Ihab Awadf8b69882014-07-25 15:14:01 -0700648 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700649 break;
Ihab Awadf8b69882014-07-25 15:14:01 -0700650 }
Tyler Gunn44e01912017-01-31 10:49:05 -0800651 case MSG_CREATE_CONNECTION_FAILED: {
652 SomeArgs args = (SomeArgs) msg.obj;
653 Log.continueSession((Session) args.arg3, SESSION_HANDLER +
654 SESSION_CREATE_CONN_FAILED);
655 try {
656 final String id = (String) args.arg1;
657 final ConnectionRequest request = (ConnectionRequest) args.arg2;
658 final boolean isIncoming = args.argi1 == 1;
Tyler Gunn159f35c2017-03-02 09:28:37 -0800659 final PhoneAccountHandle connectionMgrPhoneAccount =
660 (PhoneAccountHandle) args.arg4;
Tyler Gunn44e01912017-01-31 10:49:05 -0800661 if (!mAreAccountsInitialized) {
662 Log.d(this, "Enqueueing pre-init request %s", id);
663 mPreInitializationConnectionRequests.add(
664 new android.telecom.Logging.Runnable(
665 SESSION_HANDLER + SESSION_CREATE_CONN_FAILED + ".pICR",
666 null /*lock*/) {
667 @Override
668 public void loggedRun() {
Tyler Gunn159f35c2017-03-02 09:28:37 -0800669 createConnectionFailed(connectionMgrPhoneAccount, id,
670 request, isIncoming);
Tyler Gunn44e01912017-01-31 10:49:05 -0800671 }
672 }.prepare());
673 } else {
674 Log.i(this, "createConnectionFailed %s", id);
Tyler Gunn159f35c2017-03-02 09:28:37 -0800675 createConnectionFailed(connectionMgrPhoneAccount, id, request,
676 isIncoming);
Tyler Gunn44e01912017-01-31 10:49:05 -0800677 }
678 } finally {
679 args.recycle();
680 Log.endSession();
681 }
682 break;
683 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700684 case MSG_ABORT: {
685 SomeArgs args = (SomeArgs) msg.obj;
686 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_ABORT);
687 try {
688 abort((String) args.arg1);
689 } finally {
690 args.recycle();
691 Log.endSession();
692 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700693 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700694 }
695 case MSG_ANSWER: {
696 SomeArgs args = (SomeArgs) msg.obj;
697 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_ANSWER);
698 try {
699 answer((String) args.arg1);
700 } finally {
701 args.recycle();
702 Log.endSession();
703 }
Tyler Gunnbe74de02014-08-29 14:51:48 -0700704 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700705 }
Tyler Gunnbe74de02014-08-29 14:51:48 -0700706 case MSG_ANSWER_VIDEO: {
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700707 SomeArgs args = (SomeArgs) msg.obj;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700708 Log.continueSession((Session) args.arg2,
709 SESSION_HANDLER + SESSION_ANSWER_VIDEO);
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700710 try {
711 String callId = (String) args.arg1;
Evan Charltonbf11f982014-07-20 22:06:28 -0700712 int videoState = args.argi1;
Tyler Gunnbe74de02014-08-29 14:51:48 -0700713 answerVideo(callId, videoState);
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700714 } finally {
715 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700716 Log.endSession();
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700717 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700718 break;
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700719 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700720 case MSG_REJECT: {
721 SomeArgs args = (SomeArgs) msg.obj;
722 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_REJECT);
723 try {
724 reject((String) args.arg1);
725 } finally {
726 args.recycle();
727 Log.endSession();
728 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700729 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700730 }
Bryce Lee81901682015-08-28 16:38:02 -0700731 case MSG_REJECT_WITH_MESSAGE: {
732 SomeArgs args = (SomeArgs) msg.obj;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700733 Log.continueSession((Session) args.arg3,
734 SESSION_HANDLER + SESSION_REJECT_MESSAGE);
Bryce Lee81901682015-08-28 16:38:02 -0700735 try {
736 reject((String) args.arg1, (String) args.arg2);
737 } finally {
738 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700739 Log.endSession();
Bryce Lee81901682015-08-28 16:38:02 -0700740 }
741 break;
742 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700743 case MSG_DISCONNECT: {
744 SomeArgs args = (SomeArgs) msg.obj;
745 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_DISCONNECT);
746 try {
747 disconnect((String) args.arg1);
748 } finally {
749 args.recycle();
750 Log.endSession();
751 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700752 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700753 }
754 case MSG_SILENCE: {
755 SomeArgs args = (SomeArgs) msg.obj;
756 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_SILENCE);
757 try {
758 silence((String) args.arg1);
759 } finally {
760 args.recycle();
761 Log.endSession();
762 }
Bryce Leecac50772015-11-17 15:13:29 -0800763 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700764 }
765 case MSG_HOLD: {
766 SomeArgs args = (SomeArgs) msg.obj;
767 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_REJECT);
768 try {
769 hold((String) args.arg1);
770 } finally {
771 args.recycle();
772 Log.endSession();
773 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700774 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700775 }
776 case MSG_UNHOLD: {
777 SomeArgs args = (SomeArgs) msg.obj;
778 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_UNHOLD);
779 try {
780 unhold((String) args.arg1);
781 } finally {
782 args.recycle();
783 Log.endSession();
784 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700785 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700786 }
Yorke Lee4af59352015-05-13 14:14:54 -0700787 case MSG_ON_CALL_AUDIO_STATE_CHANGED: {
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700788 SomeArgs args = (SomeArgs) msg.obj;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700789 Log.continueSession((Session) args.arg3,
790 SESSION_HANDLER + SESSION_CALL_AUDIO_SC);
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700791 try {
792 String callId = (String) args.arg1;
Yorke Lee4af59352015-05-13 14:14:54 -0700793 CallAudioState audioState = (CallAudioState) args.arg2;
794 onCallAudioStateChanged(callId, new CallAudioState(audioState));
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700795 } finally {
796 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700797 Log.endSession();
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700798 }
799 break;
800 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700801 case MSG_PLAY_DTMF_TONE: {
802 SomeArgs args = (SomeArgs) msg.obj;
803 try {
804 Log.continueSession((Session) args.arg3,
805 SESSION_HANDLER + SESSION_PLAY_DTMF);
806 playDtmfTone((String) args.arg2, (char) args.arg1);
807 } finally {
808 args.recycle();
809 Log.endSession();
810 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700811 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700812 }
813 case MSG_STOP_DTMF_TONE: {
814 SomeArgs args = (SomeArgs) msg.obj;
815 try {
816 Log.continueSession((Session) args.arg2,
817 SESSION_HANDLER + SESSION_STOP_DTMF);
818 stopDtmfTone((String) args.arg1);
819 } finally {
820 args.recycle();
821 Log.endSession();
822 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700823 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700824 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700825 case MSG_CONFERENCE: {
826 SomeArgs args = (SomeArgs) msg.obj;
827 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700828 Log.continueSession((Session) args.arg3,
829 SESSION_HANDLER + SESSION_CONFERENCE);
Santos Cordon823fd3c2014-08-07 18:35:18 -0700830 String callId1 = (String) args.arg1;
831 String callId2 = (String) args.arg2;
832 conference(callId1, callId2);
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700833 } finally {
834 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700835 Log.endSession();
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700836 }
837 break;
838 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700839 case MSG_SPLIT_FROM_CONFERENCE: {
840 SomeArgs args = (SomeArgs) msg.obj;
841 try {
842 Log.continueSession((Session) args.arg2,
843 SESSION_HANDLER + SESSION_SPLIT_CONFERENCE);
844 splitFromConference((String) args.arg1);
845 } finally {
846 args.recycle();
847 Log.endSession();
848 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700849 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700850 }
851 case MSG_MERGE_CONFERENCE: {
852 SomeArgs args = (SomeArgs) msg.obj;
853 try {
854 Log.continueSession((Session) args.arg2,
855 SESSION_HANDLER + SESSION_MERGE_CONFERENCE);
856 mergeConference((String) args.arg1);
857 } finally {
858 args.recycle();
859 Log.endSession();
860 }
Santos Cordona4868042014-09-04 17:39:22 -0700861 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700862 }
863 case MSG_SWAP_CONFERENCE: {
864 SomeArgs args = (SomeArgs) msg.obj;
865 try {
866 Log.continueSession((Session) args.arg2,
867 SESSION_HANDLER + SESSION_SWAP_CONFERENCE);
868 swapConference((String) args.arg1);
869 } finally {
870 args.recycle();
871 Log.endSession();
872 }
Santos Cordona4868042014-09-04 17:39:22 -0700873 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700874 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700875 case MSG_ON_POST_DIAL_CONTINUE: {
876 SomeArgs args = (SomeArgs) msg.obj;
877 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700878 Log.continueSession((Session) args.arg2,
879 SESSION_HANDLER + SESSION_POST_DIAL_CONT);
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700880 String callId = (String) args.arg1;
881 boolean proceed = (args.argi1 == 1);
882 onPostDialContinue(callId, proceed);
883 } finally {
884 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700885 Log.endSession();
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700886 }
887 break;
888 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700889 case MSG_PULL_EXTERNAL_CALL: {
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700890 SomeArgs args = (SomeArgs) msg.obj;
891 try {
892 Log.continueSession((Session) args.arg2,
893 SESSION_HANDLER + SESSION_PULL_EXTERNAL_CALL);
894 pullExternalCall((String) args.arg1);
895 } finally {
896 args.recycle();
897 Log.endSession();
898 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700899 break;
900 }
901 case MSG_SEND_CALL_EVENT: {
902 SomeArgs args = (SomeArgs) msg.obj;
903 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700904 Log.continueSession((Session) args.arg4,
905 SESSION_HANDLER + SESSION_SEND_CALL_EVENT);
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700906 String callId = (String) args.arg1;
907 String event = (String) args.arg2;
908 Bundle extras = (Bundle) args.arg3;
909 sendCallEvent(callId, event, extras);
910 } finally {
911 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700912 Log.endSession();
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700913 }
914 break;
915 }
Tyler Gunndee56a82016-03-23 16:06:34 -0700916 case MSG_ON_EXTRAS_CHANGED: {
917 SomeArgs args = (SomeArgs) msg.obj;
918 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700919 Log.continueSession((Session) args.arg3,
920 SESSION_HANDLER + SESSION_EXTRAS_CHANGED);
Tyler Gunndee56a82016-03-23 16:06:34 -0700921 String callId = (String) args.arg1;
922 Bundle extras = (Bundle) args.arg2;
923 handleExtrasChanged(callId, extras);
924 } finally {
925 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700926 Log.endSession();
Tyler Gunndee56a82016-03-23 16:06:34 -0700927 }
928 break;
929 }
Hall Liub64ac4c2017-02-06 10:49:48 -0800930 case MSG_ON_START_RTT: {
931 SomeArgs args = (SomeArgs) msg.obj;
932 try {
933 Log.continueSession((Session) args.arg3,
934 SESSION_HANDLER + SESSION_START_RTT);
935 String callId = (String) args.arg1;
936 Connection.RttTextStream rttTextStream =
937 (Connection.RttTextStream) args.arg2;
938 startRtt(callId, rttTextStream);
939 } finally {
940 args.recycle();
941 Log.endSession();
942 }
943 break;
944 }
945 case MSG_ON_STOP_RTT: {
946 SomeArgs args = (SomeArgs) msg.obj;
947 try {
948 Log.continueSession((Session) args.arg2,
949 SESSION_HANDLER + SESSION_STOP_RTT);
950 String callId = (String) args.arg1;
951 stopRtt(callId);
952 } finally {
953 args.recycle();
954 Log.endSession();
955 }
956 break;
957 }
958 case MSG_RTT_UPGRADE_RESPONSE: {
959 SomeArgs args = (SomeArgs) msg.obj;
960 try {
961 Log.continueSession((Session) args.arg3,
962 SESSION_HANDLER + SESSION_RTT_UPGRADE_RESPONSE);
963 String callId = (String) args.arg1;
964 Connection.RttTextStream rttTextStream =
965 (Connection.RttTextStream) args.arg2;
966 handleRttUpgradeResponse(callId, rttTextStream);
967 } finally {
968 args.recycle();
969 Log.endSession();
970 }
971 break;
972 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700973 default:
974 break;
975 }
976 }
977 };
978
Santos Cordon823fd3c2014-08-07 18:35:18 -0700979 private final Conference.Listener mConferenceListener = new Conference.Listener() {
980 @Override
981 public void onStateChanged(Conference conference, int oldState, int newState) {
982 String id = mIdByConference.get(conference);
983 switch (newState) {
984 case Connection.STATE_ACTIVE:
985 mAdapter.setActive(id);
986 break;
987 case Connection.STATE_HOLDING:
988 mAdapter.setOnHold(id);
989 break;
990 case Connection.STATE_DISCONNECTED:
991 // handled by onDisconnected
992 break;
993 }
994 }
995
996 @Override
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700997 public void onDisconnected(Conference conference, DisconnectCause disconnectCause) {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700998 String id = mIdByConference.get(conference);
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700999 mAdapter.setDisconnected(id, disconnectCause);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001000 }
1001
1002 @Override
1003 public void onConnectionAdded(Conference conference, Connection connection) {
1004 }
1005
1006 @Override
1007 public void onConnectionRemoved(Conference conference, Connection connection) {
1008 }
1009
1010 @Override
Ihab Awad50e35062014-09-30 09:17:03 -07001011 public void onConferenceableConnectionsChanged(
1012 Conference conference, List<Connection> conferenceableConnections) {
1013 mAdapter.setConferenceableConnections(
1014 mIdByConference.get(conference),
1015 createConnectionIdList(conferenceableConnections));
1016 }
1017
1018 @Override
Santos Cordon823fd3c2014-08-07 18:35:18 -07001019 public void onDestroyed(Conference conference) {
1020 removeConference(conference);
1021 }
1022
1023 @Override
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001024 public void onConnectionCapabilitiesChanged(
1025 Conference conference,
1026 int connectionCapabilities) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001027 String id = mIdByConference.get(conference);
1028 Log.d(this, "call capabilities: conference: %s",
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001029 Connection.capabilitiesToString(connectionCapabilities));
1030 mAdapter.setConnectionCapabilities(id, connectionCapabilities);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001031 }
Rekha Kumar07366812015-03-24 16:42:31 -07001032
1033 @Override
Tyler Gunn720c6642016-03-22 09:02:47 -07001034 public void onConnectionPropertiesChanged(
1035 Conference conference,
1036 int connectionProperties) {
1037 String id = mIdByConference.get(conference);
1038 Log.d(this, "call capabilities: conference: %s",
1039 Connection.propertiesToString(connectionProperties));
1040 mAdapter.setConnectionProperties(id, connectionProperties);
1041 }
1042
1043 @Override
Rekha Kumar07366812015-03-24 16:42:31 -07001044 public void onVideoStateChanged(Conference c, int videoState) {
1045 String id = mIdByConference.get(c);
1046 Log.d(this, "onVideoStateChanged set video state %d", videoState);
1047 mAdapter.setVideoState(id, videoState);
1048 }
1049
1050 @Override
1051 public void onVideoProviderChanged(Conference c, Connection.VideoProvider videoProvider) {
1052 String id = mIdByConference.get(c);
1053 Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c,
1054 videoProvider);
1055 mAdapter.setVideoProvider(id, videoProvider);
1056 }
Andrew Lee0f51da32015-04-16 13:11:55 -07001057
1058 @Override
Andrew Leeedc625f2015-04-14 13:38:12 -07001059 public void onStatusHintsChanged(Conference conference, StatusHints statusHints) {
1060 String id = mIdByConference.get(conference);
Tyler Gunndee56a82016-03-23 16:06:34 -07001061 if (id != null) {
1062 mAdapter.setStatusHints(id, statusHints);
1063 }
Andrew Leeedc625f2015-04-14 13:38:12 -07001064 }
Santos Cordon6b7f9552015-05-27 17:21:45 -07001065
1066 @Override
Tyler Gunndee56a82016-03-23 16:06:34 -07001067 public void onExtrasChanged(Conference c, Bundle extras) {
1068 String id = mIdByConference.get(c);
1069 if (id != null) {
1070 mAdapter.putExtras(id, extras);
1071 }
1072 }
1073
1074 @Override
1075 public void onExtrasRemoved(Conference c, List<String> keys) {
1076 String id = mIdByConference.get(c);
1077 if (id != null) {
1078 mAdapter.removeExtras(id, keys);
1079 }
Santos Cordon6b7f9552015-05-27 17:21:45 -07001080 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07001081 };
1082
Ihab Awad542e0ea2014-05-16 10:22:16 -07001083 private final Connection.Listener mConnectionListener = new Connection.Listener() {
1084 @Override
1085 public void onStateChanged(Connection c, int state) {
1086 String id = mIdByConnection.get(c);
Ihab Awad42b30e12014-05-22 09:49:34 -07001087 Log.d(this, "Adapter set state %s %s", id, Connection.stateToString(state));
Ihab Awad542e0ea2014-05-16 10:22:16 -07001088 switch (state) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001089 case Connection.STATE_ACTIVE:
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001090 mAdapter.setActive(id);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001091 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001092 case Connection.STATE_DIALING:
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001093 mAdapter.setDialing(id);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001094 break;
Tyler Gunnc96b5e02016-07-07 22:53:57 -07001095 case Connection.STATE_PULLING_CALL:
1096 mAdapter.setPulling(id);
1097 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001098 case Connection.STATE_DISCONNECTED:
Ihab Awad542e0ea2014-05-16 10:22:16 -07001099 // Handled in onDisconnected()
1100 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001101 case Connection.STATE_HOLDING:
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001102 mAdapter.setOnHold(id);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001103 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001104 case Connection.STATE_NEW:
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001105 // Nothing to tell Telecom
Ihab Awad542e0ea2014-05-16 10:22:16 -07001106 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001107 case Connection.STATE_RINGING:
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001108 mAdapter.setRinging(id);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001109 break;
1110 }
1111 }
1112
1113 @Override
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001114 public void onDisconnected(Connection c, DisconnectCause disconnectCause) {
Ihab Awad542e0ea2014-05-16 10:22:16 -07001115 String id = mIdByConnection.get(c);
Andrew Lee26786392014-09-16 18:14:59 -07001116 Log.d(this, "Adapter set disconnected %s", disconnectCause);
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001117 mAdapter.setDisconnected(id, disconnectCause);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001118 }
1119
1120 @Override
Tyler Gunnaa07df82014-07-17 07:50:22 -07001121 public void onVideoStateChanged(Connection c, int videoState) {
1122 String id = mIdByConnection.get(c);
1123 Log.d(this, "Adapter set video state %d", videoState);
1124 mAdapter.setVideoState(id, videoState);
1125 }
1126
1127 @Override
Andrew Lee100e2932014-09-08 15:34:24 -07001128 public void onAddressChanged(Connection c, Uri address, int presentation) {
Sailesh Nepal61203862014-07-11 14:50:13 -07001129 String id = mIdByConnection.get(c);
Andrew Lee100e2932014-09-08 15:34:24 -07001130 mAdapter.setAddress(id, address, presentation);
Sailesh Nepal61203862014-07-11 14:50:13 -07001131 }
1132
1133 @Override
1134 public void onCallerDisplayNameChanged(
1135 Connection c, String callerDisplayName, int presentation) {
1136 String id = mIdByConnection.get(c);
1137 mAdapter.setCallerDisplayName(id, callerDisplayName, presentation);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001138 }
1139
1140 @Override
Ihab Awad542e0ea2014-05-16 10:22:16 -07001141 public void onDestroyed(Connection c) {
1142 removeConnection(c);
1143 }
Ihab Awadf8358972014-05-28 16:46:42 -07001144
1145 @Override
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001146 public void onPostDialWait(Connection c, String remaining) {
Sailesh Nepal091768c2014-06-30 15:15:23 -07001147 String id = mIdByConnection.get(c);
1148 Log.d(this, "Adapter onPostDialWait %s, %s", c, remaining);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001149 mAdapter.onPostDialWait(id, remaining);
Sailesh Nepal091768c2014-06-30 15:15:23 -07001150 }
1151
1152 @Override
Nancy Chen27d1c2d2014-12-15 16:12:50 -08001153 public void onPostDialChar(Connection c, char nextChar) {
1154 String id = mIdByConnection.get(c);
1155 Log.d(this, "Adapter onPostDialChar %s, %s", c, nextChar);
1156 mAdapter.onPostDialChar(id, nextChar);
1157 }
1158
1159 @Override
Andrew Lee100e2932014-09-08 15:34:24 -07001160 public void onRingbackRequested(Connection c, boolean ringback) {
Ihab Awadf8358972014-05-28 16:46:42 -07001161 String id = mIdByConnection.get(c);
1162 Log.d(this, "Adapter onRingback %b", ringback);
Andrew Lee100e2932014-09-08 15:34:24 -07001163 mAdapter.setRingbackRequested(id, ringback);
Ihab Awadf8358972014-05-28 16:46:42 -07001164 }
Santos Cordonb6939982014-06-04 20:20:58 -07001165
1166 @Override
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001167 public void onConnectionCapabilitiesChanged(Connection c, int capabilities) {
Santos Cordonb6939982014-06-04 20:20:58 -07001168 String id = mIdByConnection.get(c);
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001169 Log.d(this, "capabilities: parcelableconnection: %s",
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001170 Connection.capabilitiesToString(capabilities));
1171 mAdapter.setConnectionCapabilities(id, capabilities);
Santos Cordonb6939982014-06-04 20:20:58 -07001172 }
1173
Santos Cordonb6939982014-06-04 20:20:58 -07001174 @Override
Tyler Gunn720c6642016-03-22 09:02:47 -07001175 public void onConnectionPropertiesChanged(Connection c, int properties) {
1176 String id = mIdByConnection.get(c);
1177 Log.d(this, "properties: parcelableconnection: %s",
1178 Connection.propertiesToString(properties));
1179 mAdapter.setConnectionProperties(id, properties);
1180 }
1181
1182 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001183 public void onVideoProviderChanged(Connection c, Connection.VideoProvider videoProvider) {
Andrew Lee5ffbe8b82014-06-20 16:29:33 -07001184 String id = mIdByConnection.get(c);
Rekha Kumar07366812015-03-24 16:42:31 -07001185 Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c,
1186 videoProvider);
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001187 mAdapter.setVideoProvider(id, videoProvider);
Andrew Lee5ffbe8b82014-06-20 16:29:33 -07001188 }
Sailesh Nepal33aaae42014-07-07 22:49:44 -07001189
1190 @Override
Sailesh Nepal001bbbb2014-07-15 14:40:39 -07001191 public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {
Sailesh Nepal33aaae42014-07-07 22:49:44 -07001192 String id = mIdByConnection.get(c);
Andrew Lee100e2932014-09-08 15:34:24 -07001193 mAdapter.setIsVoipAudioMode(id, isVoip);
Sailesh Nepal33aaae42014-07-07 22:49:44 -07001194 }
Sailesh Nepale7ef59a2014-07-08 21:48:22 -07001195
1196 @Override
Sailesh Nepal001bbbb2014-07-15 14:40:39 -07001197 public void onStatusHintsChanged(Connection c, StatusHints statusHints) {
Sailesh Nepale7ef59a2014-07-08 21:48:22 -07001198 String id = mIdByConnection.get(c);
1199 mAdapter.setStatusHints(id, statusHints);
1200 }
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07001201
1202 @Override
Tyler Gunn6d76ca02014-11-17 15:49:51 -08001203 public void onConferenceablesChanged(
Tyler Gunndf2cbc82015-04-20 09:13:01 -07001204 Connection connection, List<Conferenceable> conferenceables) {
Ihab Awadb8e85c72014-08-23 20:34:57 -07001205 mAdapter.setConferenceableConnections(
1206 mIdByConnection.get(connection),
Tyler Gunn6d76ca02014-11-17 15:49:51 -08001207 createIdList(conferenceables));
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001208 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07001209
1210 @Override
1211 public void onConferenceChanged(Connection connection, Conference conference) {
1212 String id = mIdByConnection.get(connection);
1213 if (id != null) {
1214 String conferenceId = null;
1215 if (conference != null) {
1216 conferenceId = mIdByConference.get(conference);
1217 }
1218 mAdapter.setIsConferenced(id, conferenceId);
1219 }
1220 }
Anthony Lee17455a32015-04-24 15:25:29 -07001221
1222 @Override
1223 public void onConferenceMergeFailed(Connection connection) {
1224 String id = mIdByConnection.get(connection);
1225 if (id != null) {
1226 mAdapter.onConferenceMergeFailed(id);
1227 }
1228 }
Santos Cordon6b7f9552015-05-27 17:21:45 -07001229
1230 @Override
Tyler Gunndee56a82016-03-23 16:06:34 -07001231 public void onExtrasChanged(Connection c, Bundle extras) {
1232 String id = mIdByConnection.get(c);
Santos Cordon6b7f9552015-05-27 17:21:45 -07001233 if (id != null) {
Tyler Gunndee56a82016-03-23 16:06:34 -07001234 mAdapter.putExtras(id, extras);
Santos Cordon6b7f9552015-05-27 17:21:45 -07001235 }
1236 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001237
Tyler Gunnf5035432017-01-09 09:43:12 -08001238 @Override
Tyler Gunndee56a82016-03-23 16:06:34 -07001239 public void onExtrasRemoved(Connection c, List<String> keys) {
1240 String id = mIdByConnection.get(c);
1241 if (id != null) {
1242 mAdapter.removeExtras(id, keys);
1243 }
1244 }
1245
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -08001246 @Override
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001247 public void onConnectionEvent(Connection connection, String event, Bundle extras) {
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -08001248 String id = mIdByConnection.get(connection);
1249 if (id != null) {
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001250 mAdapter.onConnectionEvent(id, event, extras);
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -08001251 }
1252 }
Tyler Gunnf5035432017-01-09 09:43:12 -08001253
1254 @Override
1255 public void onAudioRouteChanged(Connection c, int audioRoute) {
1256 String id = mIdByConnection.get(c);
1257 if (id != null) {
1258 mAdapter.setAudioRoute(id, audioRoute);
1259 }
1260 }
Hall Liub64ac4c2017-02-06 10:49:48 -08001261
1262 @Override
1263 public void onRttInitiationSuccess(Connection c) {
1264 String id = mIdByConnection.get(c);
1265 if (id != null) {
1266 mAdapter.onRttInitiationSuccess(id);
1267 }
1268 }
1269
1270 @Override
1271 public void onRttInitiationFailure(Connection c, int reason) {
1272 String id = mIdByConnection.get(c);
1273 if (id != null) {
1274 mAdapter.onRttInitiationFailure(id, reason);
1275 }
1276 }
1277
1278 @Override
1279 public void onRttSessionRemotelyTerminated(Connection c) {
1280 String id = mIdByConnection.get(c);
1281 if (id != null) {
1282 mAdapter.onRttSessionRemotelyTerminated(id);
1283 }
1284 }
1285
1286 @Override
1287 public void onRemoteRttRequest(Connection c) {
1288 String id = mIdByConnection.get(c);
1289 if (id != null) {
1290 mAdapter.onRemoteRttRequest(id);
1291 }
1292 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07001293 };
1294
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001295 /** {@inheritDoc} */
Ihab Awad542e0ea2014-05-16 10:22:16 -07001296 @Override
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001297 public final IBinder onBind(Intent intent) {
1298 return mBinder;
1299 }
1300
Santos Cordon29f2f2e2014-09-11 19:50:24 -07001301 /** {@inheritDoc} */
1302 @Override
1303 public boolean onUnbind(Intent intent) {
1304 endAllConnections();
1305 return super.onUnbind(intent);
1306 }
1307
Sailesh Nepalc5b01572014-07-14 16:29:44 -07001308 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001309 * This can be used by telecom to either create a new outgoing call or attach to an existing
1310 * incoming call. In either case, telecom will cycle through a set of services and call
Sailesh Nepalc5b01572014-07-14 16:29:44 -07001311 * createConnection util a connection service cancels the process or completes it successfully.
1312 */
Ihab Awadf8b69882014-07-25 15:14:01 -07001313 private void createConnection(
1314 final PhoneAccountHandle callManagerAccount,
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001315 final String callId,
Ihab Awadf8b69882014-07-25 15:14:01 -07001316 final ConnectionRequest request,
Yorke Leec3cf9822014-10-02 09:38:39 -07001317 boolean isIncoming,
1318 boolean isUnknown) {
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001319 Log.d(this, "createConnection, callManagerAccount: %s, callId: %s, request: %s, " +
Tyler Gunnf0500bd2015-09-01 10:59:48 -07001320 "isIncoming: %b, isUnknown: %b", callManagerAccount, callId, request,
1321 isIncoming,
Yorke Leec3cf9822014-10-02 09:38:39 -07001322 isUnknown);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001323
Yorke Leec3cf9822014-10-02 09:38:39 -07001324 Connection connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
1325 : isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
Ihab Awad6107bab2014-08-18 09:23:25 -07001326 : onCreateOutgoingConnection(callManagerAccount, request);
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001327 Log.d(this, "createConnection, connection: %s", connection);
1328 if (connection == null) {
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001329 connection = Connection.createFailedConnection(
1330 new DisconnectCause(DisconnectCause.ERROR));
Sailesh Nepalc5b01572014-07-14 16:29:44 -07001331 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07001332
Tyler Gunnf0500bd2015-09-01 10:59:48 -07001333 connection.setTelecomCallId(callId);
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001334 if (connection.getState() != Connection.STATE_DISCONNECTED) {
Ihab Awad6107bab2014-08-18 09:23:25 -07001335 addConnection(callId, connection);
1336 }
1337
Andrew Lee100e2932014-09-08 15:34:24 -07001338 Uri address = connection.getAddress();
1339 String number = address == null ? "null" : address.getSchemeSpecificPart();
Tyler Gunn720c6642016-03-22 09:02:47 -07001340 Log.v(this, "createConnection, number: %s, state: %s, capabilities: %s, properties: %s",
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001341 Connection.toLogSafePhoneNumber(number),
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001342 Connection.stateToString(connection.getState()),
Tyler Gunn720c6642016-03-22 09:02:47 -07001343 Connection.capabilitiesToString(connection.getConnectionCapabilities()),
1344 Connection.propertiesToString(connection.getConnectionProperties()));
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001345
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001346 Log.d(this, "createConnection, calling handleCreateConnectionSuccessful %s", callId);
Ihab Awad6107bab2014-08-18 09:23:25 -07001347 mAdapter.handleCreateConnectionComplete(
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001348 callId,
Evan Charltonbf11f982014-07-20 22:06:28 -07001349 request,
1350 new ParcelableConnection(
1351 request.getAccountHandle(),
1352 connection.getState(),
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001353 connection.getConnectionCapabilities(),
Tyler Gunn720c6642016-03-22 09:02:47 -07001354 connection.getConnectionProperties(),
Christine Hallstrom2830ce92016-11-30 16:06:42 -08001355 connection.getSupportedAudioRoutes(),
Andrew Lee100e2932014-09-08 15:34:24 -07001356 connection.getAddress(),
1357 connection.getAddressPresentation(),
Evan Charltonbf11f982014-07-20 22:06:28 -07001358 connection.getCallerDisplayName(),
1359 connection.getCallerDisplayNamePresentation(),
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001360 connection.getVideoProvider() == null ?
1361 null : connection.getVideoProvider().getInterface(),
Sailesh Nepal8b9d3ca2014-08-14 17:39:34 -07001362 connection.getVideoState(),
Andrew Lee100e2932014-09-08 15:34:24 -07001363 connection.isRingbackRequested(),
Sailesh Nepal8b9d3ca2014-08-14 17:39:34 -07001364 connection.getAudioModeIsVoip(),
Roshan Piuse927ec02015-07-15 15:47:21 -07001365 connection.getConnectTimeMillis(),
Ihab Awad6107bab2014-08-18 09:23:25 -07001366 connection.getStatusHints(),
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001367 connection.getDisconnectCause(),
Santos Cordon6b7f9552015-05-27 17:21:45 -07001368 createIdList(connection.getConferenceables()),
1369 connection.getExtras()));
Tyler Gunnf5035432017-01-09 09:43:12 -08001370
1371 if (isIncoming && request.shouldShowIncomingCallUi() &&
1372 (connection.getConnectionProperties() & Connection.PROPERTY_SELF_MANAGED) ==
1373 Connection.PROPERTY_SELF_MANAGED) {
1374 // Tell ConnectionService to show its incoming call UX.
1375 connection.onShowIncomingCallUi();
1376 }
Shriram Ganesh6bf35ac2014-12-11 17:53:38 -08001377 if (isUnknown) {
1378 triggerConferenceRecalculate();
1379 }
Evan Charltonbf11f982014-07-20 22:06:28 -07001380 }
1381
Tyler Gunn159f35c2017-03-02 09:28:37 -08001382 private void createConnectionFailed(final PhoneAccountHandle callManagerAccount,
1383 final String callId, final ConnectionRequest request,
1384 boolean isIncoming) {
Tyler Gunn44e01912017-01-31 10:49:05 -08001385
1386 Log.i(this, "createConnectionFailed %s", callId);
1387 if (isIncoming) {
Tyler Gunn159f35c2017-03-02 09:28:37 -08001388 onCreateIncomingConnectionFailed(callManagerAccount, request);
Tyler Gunn44e01912017-01-31 10:49:05 -08001389 } else {
Tyler Gunn159f35c2017-03-02 09:28:37 -08001390 onCreateOutgoingConnectionFailed(callManagerAccount, request);
Tyler Gunn44e01912017-01-31 10:49:05 -08001391 }
1392 }
1393
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001394 private void abort(String callId) {
Ihab Awad60ac30b2014-05-20 22:32:12 -07001395 Log.d(this, "abort %s", callId);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001396 findConnectionForAction(callId, "abort").onAbort();
Ihab Awad542e0ea2014-05-16 10:22:16 -07001397 }
1398
Tyler Gunnbe74de02014-08-29 14:51:48 -07001399 private void answerVideo(String callId, int videoState) {
1400 Log.d(this, "answerVideo %s", callId);
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001401 findConnectionForAction(callId, "answer").onAnswer(videoState);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001402 }
1403
Tyler Gunnbe74de02014-08-29 14:51:48 -07001404 private void answer(String callId) {
1405 Log.d(this, "answer %s", callId);
1406 findConnectionForAction(callId, "answer").onAnswer();
1407 }
1408
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001409 private void reject(String callId) {
Ihab Awad60ac30b2014-05-20 22:32:12 -07001410 Log.d(this, "reject %s", callId);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001411 findConnectionForAction(callId, "reject").onReject();
Ihab Awad542e0ea2014-05-16 10:22:16 -07001412 }
1413
Bryce Lee81901682015-08-28 16:38:02 -07001414 private void reject(String callId, String rejectWithMessage) {
1415 Log.d(this, "reject %s with message", callId);
1416 findConnectionForAction(callId, "reject").onReject(rejectWithMessage);
1417 }
1418
Bryce Leecac50772015-11-17 15:13:29 -08001419 private void silence(String callId) {
1420 Log.d(this, "silence %s", callId);
1421 findConnectionForAction(callId, "silence").onSilence();
1422 }
1423
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001424 private void disconnect(String callId) {
Ihab Awad60ac30b2014-05-20 22:32:12 -07001425 Log.d(this, "disconnect %s", callId);
Santos Cordon0159ac02014-08-21 14:28:11 -07001426 if (mConnectionById.containsKey(callId)) {
1427 findConnectionForAction(callId, "disconnect").onDisconnect();
1428 } else {
1429 findConferenceForAction(callId, "disconnect").onDisconnect();
1430 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07001431 }
1432
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001433 private void hold(String callId) {
Ihab Awad60ac30b2014-05-20 22:32:12 -07001434 Log.d(this, "hold %s", callId);
Santos Cordon0159ac02014-08-21 14:28:11 -07001435 if (mConnectionById.containsKey(callId)) {
1436 findConnectionForAction(callId, "hold").onHold();
1437 } else {
1438 findConferenceForAction(callId, "hold").onHold();
1439 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07001440 }
1441
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001442 private void unhold(String callId) {
Ihab Awad60ac30b2014-05-20 22:32:12 -07001443 Log.d(this, "unhold %s", callId);
Santos Cordon0159ac02014-08-21 14:28:11 -07001444 if (mConnectionById.containsKey(callId)) {
1445 findConnectionForAction(callId, "unhold").onUnhold();
1446 } else {
1447 findConferenceForAction(callId, "unhold").onUnhold();
1448 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07001449 }
1450
Yorke Lee4af59352015-05-13 14:14:54 -07001451 private void onCallAudioStateChanged(String callId, CallAudioState callAudioState) {
1452 Log.d(this, "onAudioStateChanged %s %s", callId, callAudioState);
Yorke Leea0d3ca92014-09-15 19:18:13 -07001453 if (mConnectionById.containsKey(callId)) {
Yorke Lee4af59352015-05-13 14:14:54 -07001454 findConnectionForAction(callId, "onCallAudioStateChanged").setCallAudioState(
1455 callAudioState);
Yorke Leea0d3ca92014-09-15 19:18:13 -07001456 } else {
Yorke Lee4af59352015-05-13 14:14:54 -07001457 findConferenceForAction(callId, "onCallAudioStateChanged").setCallAudioState(
1458 callAudioState);
Yorke Leea0d3ca92014-09-15 19:18:13 -07001459 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07001460 }
1461
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001462 private void playDtmfTone(String callId, char digit) {
1463 Log.d(this, "playDtmfTone %s %c", callId, digit);
Yorke Leea0d3ca92014-09-15 19:18:13 -07001464 if (mConnectionById.containsKey(callId)) {
1465 findConnectionForAction(callId, "playDtmfTone").onPlayDtmfTone(digit);
1466 } else {
1467 findConferenceForAction(callId, "playDtmfTone").onPlayDtmfTone(digit);
1468 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001469 }
1470
1471 private void stopDtmfTone(String callId) {
1472 Log.d(this, "stopDtmfTone %s", callId);
Yorke Leea0d3ca92014-09-15 19:18:13 -07001473 if (mConnectionById.containsKey(callId)) {
1474 findConnectionForAction(callId, "stopDtmfTone").onStopDtmfTone();
1475 } else {
1476 findConferenceForAction(callId, "stopDtmfTone").onStopDtmfTone();
1477 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001478 }
1479
Santos Cordon823fd3c2014-08-07 18:35:18 -07001480 private void conference(String callId1, String callId2) {
1481 Log.d(this, "conference %s, %s", callId1, callId2);
Santos Cordon980acb92014-05-31 10:31:19 -07001482
Tyler Gunn6d76ca02014-11-17 15:49:51 -08001483 // Attempt to get second connection or conference.
Santos Cordon823fd3c2014-08-07 18:35:18 -07001484 Connection connection2 = findConnectionForAction(callId2, "conference");
Tyler Gunn6d76ca02014-11-17 15:49:51 -08001485 Conference conference2 = getNullConference();
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001486 if (connection2 == getNullConnection()) {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08001487 conference2 = findConferenceForAction(callId2, "conference");
1488 if (conference2 == getNullConference()) {
1489 Log.w(this, "Connection2 or Conference2 missing in conference request %s.",
1490 callId2);
1491 return;
1492 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07001493 }
Santos Cordonb6939982014-06-04 20:20:58 -07001494
Tyler Gunn6d76ca02014-11-17 15:49:51 -08001495 // Attempt to get first connection or conference and perform merge.
Ihab Awad50e35062014-09-30 09:17:03 -07001496 Connection connection1 = findConnectionForAction(callId1, "conference");
1497 if (connection1 == getNullConnection()) {
1498 Conference conference1 = findConferenceForAction(callId1, "addConnection");
1499 if (conference1 == getNullConference()) {
1500 Log.w(this,
1501 "Connection1 or Conference1 missing in conference request %s.",
1502 callId1);
1503 } else {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08001504 // Call 1 is a conference.
1505 if (connection2 != getNullConnection()) {
1506 // Call 2 is a connection so merge via call 1 (conference).
1507 conference1.onMerge(connection2);
1508 } else {
1509 // Call 2 is ALSO a conference; this should never happen.
1510 Log.wtf(this, "There can only be one conference and an attempt was made to " +
1511 "merge two conferences.");
1512 return;
1513 }
Ihab Awad50e35062014-09-30 09:17:03 -07001514 }
1515 } else {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08001516 // Call 1 is a connection.
1517 if (conference2 != getNullConference()) {
1518 // Call 2 is a conference, so merge via call 2.
1519 conference2.onMerge(connection1);
1520 } else {
1521 // Call 2 is a connection, so merge together.
1522 onConference(connection1, connection2);
1523 }
Ihab Awad50e35062014-09-30 09:17:03 -07001524 }
Santos Cordon980acb92014-05-31 10:31:19 -07001525 }
1526
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001527 private void splitFromConference(String callId) {
Santos Cordonb6939982014-06-04 20:20:58 -07001528 Log.d(this, "splitFromConference(%s)", callId);
Santos Cordon980acb92014-05-31 10:31:19 -07001529
1530 Connection connection = findConnectionForAction(callId, "splitFromConference");
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001531 if (connection == getNullConnection()) {
Santos Cordon980acb92014-05-31 10:31:19 -07001532 Log.w(this, "Connection missing in conference request %s.", callId);
1533 return;
1534 }
1535
Santos Cordon0159ac02014-08-21 14:28:11 -07001536 Conference conference = connection.getConference();
1537 if (conference != null) {
1538 conference.onSeparate(connection);
1539 }
Santos Cordon980acb92014-05-31 10:31:19 -07001540 }
1541
Santos Cordona4868042014-09-04 17:39:22 -07001542 private void mergeConference(String callId) {
1543 Log.d(this, "mergeConference(%s)", callId);
1544 Conference conference = findConferenceForAction(callId, "mergeConference");
1545 if (conference != null) {
1546 conference.onMerge();
1547 }
1548 }
1549
1550 private void swapConference(String callId) {
1551 Log.d(this, "swapConference(%s)", callId);
1552 Conference conference = findConferenceForAction(callId, "swapConference");
1553 if (conference != null) {
1554 conference.onSwap();
1555 }
1556 }
1557
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001558 /**
1559 * Notifies a {@link Connection} of a request to pull an external call.
1560 *
1561 * See {@link Call#pullExternalCall()}.
1562 *
1563 * @param callId The ID of the call to pull.
1564 */
1565 private void pullExternalCall(String callId) {
1566 Log.d(this, "pullExternalCall(%s)", callId);
1567 Connection connection = findConnectionForAction(callId, "pullExternalCall");
1568 if (connection != null) {
1569 connection.onPullExternalCall();
1570 }
1571 }
1572
1573 /**
1574 * Notifies a {@link Connection} of a call event.
1575 *
1576 * See {@link Call#sendCallEvent(String, Bundle)}.
1577 *
1578 * @param callId The ID of the call receiving the event.
1579 * @param event The event.
1580 * @param extras Extras associated with the event.
1581 */
1582 private void sendCallEvent(String callId, String event, Bundle extras) {
1583 Log.d(this, "sendCallEvent(%s, %s)", callId, event);
1584 Connection connection = findConnectionForAction(callId, "sendCallEvent");
1585 if (connection != null) {
1586 connection.onCallEvent(event, extras);
1587 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001588 }
1589
Tyler Gunndee56a82016-03-23 16:06:34 -07001590 /**
1591 * Notifies a {@link Connection} or {@link Conference} of a change to the extras from Telecom.
1592 * <p>
1593 * These extra changes can originate from Telecom itself, or from an {@link InCallService} via
1594 * the {@link android.telecom.Call#putExtra(String, boolean)},
1595 * {@link android.telecom.Call#putExtra(String, int)},
1596 * {@link android.telecom.Call#putExtra(String, String)},
1597 * {@link Call#removeExtras(List)}.
1598 *
1599 * @param callId The ID of the call receiving the event.
1600 * @param extras The new extras bundle.
1601 */
1602 private void handleExtrasChanged(String callId, Bundle extras) {
1603 Log.d(this, "handleExtrasChanged(%s, %s)", callId, extras);
1604 if (mConnectionById.containsKey(callId)) {
1605 findConnectionForAction(callId, "handleExtrasChanged").handleExtrasChanged(extras);
1606 } else if (mConferenceById.containsKey(callId)) {
1607 findConferenceForAction(callId, "handleExtrasChanged").handleExtrasChanged(extras);
1608 }
1609 }
1610
Hall Liub64ac4c2017-02-06 10:49:48 -08001611 private void startRtt(String callId, Connection.RttTextStream rttTextStream) {
1612 Log.d(this, "startRtt(%s)", callId);
1613 if (mConnectionById.containsKey(callId)) {
1614 findConnectionForAction(callId, "startRtt").onStartRtt(rttTextStream);
1615 } else if (mConferenceById.containsKey(callId)) {
1616 Log.w(this, "startRtt called on a conference.");
1617 }
1618 }
1619
1620 private void stopRtt(String callId) {
1621 Log.d(this, "stopRtt(%s)", callId);
1622 if (mConnectionById.containsKey(callId)) {
1623 findConnectionForAction(callId, "stopRtt").onStopRtt();
Hall Liuffa4a812017-03-02 16:11:00 -08001624 findConnectionForAction(callId, "stopRtt").unsetRttProperty();
Hall Liub64ac4c2017-02-06 10:49:48 -08001625 } else if (mConferenceById.containsKey(callId)) {
1626 Log.w(this, "stopRtt called on a conference.");
1627 }
1628 }
1629
1630 private void handleRttUpgradeResponse(String callId, Connection.RttTextStream rttTextStream) {
1631 Log.d(this, "handleRttUpgradeResponse(%s, %s)", callId, rttTextStream == null);
1632 if (mConnectionById.containsKey(callId)) {
1633 findConnectionForAction(callId, "handleRttUpgradeResponse")
1634 .handleRttUpgradeResponse(rttTextStream);
1635 } else if (mConferenceById.containsKey(callId)) {
1636 Log.w(this, "handleRttUpgradeResponse called on a conference.");
1637 }
1638 }
1639
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001640 private void onPostDialContinue(String callId, boolean proceed) {
Evan Charlton6dea4ac2014-06-03 14:07:13 -07001641 Log.d(this, "onPostDialContinue(%s)", callId);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001642 findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
Evan Charlton6dea4ac2014-06-03 14:07:13 -07001643 }
1644
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001645 private void onAdapterAttached() {
Ihab Awad9c3f1882014-06-30 21:17:13 -07001646 if (mAreAccountsInitialized) {
Santos Cordon52d8a152014-06-17 19:08:45 -07001647 // No need to query again if we already did it.
1648 return;
1649 }
1650
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001651 mAdapter.queryRemoteConnectionServices(new RemoteServiceCallback.Stub() {
Santos Cordon52d8a152014-06-17 19:08:45 -07001652 @Override
1653 public void onResult(
1654 final List<ComponentName> componentNames,
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001655 final List<IBinder> services) {
Brad Ebinger0c3541b2016-11-01 14:11:38 -07001656 mHandler.post(new android.telecom.Logging.Runnable("oAA.qRCS.oR", null /*lock*/) {
Ihab Awad6107bab2014-08-18 09:23:25 -07001657 @Override
Brad Ebinger0c3541b2016-11-01 14:11:38 -07001658 public void loggedRun() {
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001659 for (int i = 0; i < componentNames.size() && i < services.size(); i++) {
Santos Cordon52d8a152014-06-17 19:08:45 -07001660 mRemoteConnectionManager.addConnectionService(
1661 componentNames.get(i),
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001662 IConnectionService.Stub.asInterface(services.get(i)));
Santos Cordon52d8a152014-06-17 19:08:45 -07001663 }
Ihab Awad5d0410f2014-07-30 10:07:40 -07001664 onAccountsInitialized();
Sailesh Nepalc5b01572014-07-14 16:29:44 -07001665 Log.d(this, "remote connection services found: " + services);
Santos Cordon52d8a152014-06-17 19:08:45 -07001666 }
Brad Ebinger0c3541b2016-11-01 14:11:38 -07001667 }.prepare());
Santos Cordon52d8a152014-06-17 19:08:45 -07001668 }
1669
1670 @Override
1671 public void onError() {
Brad Ebinger0c3541b2016-11-01 14:11:38 -07001672 mHandler.post(new android.telecom.Logging.Runnable("oAA.qRCS.oE", null /*lock*/) {
Ihab Awad6107bab2014-08-18 09:23:25 -07001673 @Override
Brad Ebinger0c3541b2016-11-01 14:11:38 -07001674 public void loggedRun() {
Ihab Awad9c3f1882014-06-30 21:17:13 -07001675 mAreAccountsInitialized = true;
Santos Cordon52d8a152014-06-17 19:08:45 -07001676 }
Brad Ebinger0c3541b2016-11-01 14:11:38 -07001677 }.prepare());
Santos Cordon52d8a152014-06-17 19:08:45 -07001678 }
1679 });
1680 }
1681
Ihab Awadf8b69882014-07-25 15:14:01 -07001682 /**
1683 * Ask some other {@code ConnectionService} to create a {@code RemoteConnection} given an
Santos Cordona663f862014-10-29 13:49:58 -07001684 * incoming request. This is used by {@code ConnectionService}s that are registered with
1685 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} and want to be able to manage
1686 * SIM-based incoming calls.
Ihab Awadf8b69882014-07-25 15:14:01 -07001687 *
1688 * @param connectionManagerPhoneAccount See description at
1689 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
1690 * @param request Details about the incoming call.
1691 * @return The {@code Connection} object to satisfy this call, or {@code null} to
1692 * not handle the call.
1693 */
1694 public final RemoteConnection createRemoteIncomingConnection(
1695 PhoneAccountHandle connectionManagerPhoneAccount,
1696 ConnectionRequest request) {
1697 return mRemoteConnectionManager.createRemoteConnection(
1698 connectionManagerPhoneAccount, request, true);
Santos Cordon52d8a152014-06-17 19:08:45 -07001699 }
1700
1701 /**
Ihab Awadf8b69882014-07-25 15:14:01 -07001702 * Ask some other {@code ConnectionService} to create a {@code RemoteConnection} given an
Santos Cordona663f862014-10-29 13:49:58 -07001703 * outgoing request. This is used by {@code ConnectionService}s that are registered with
1704 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} and want to be able to use the
1705 * SIM-based {@code ConnectionService} to place its outgoing calls.
Ihab Awadf8b69882014-07-25 15:14:01 -07001706 *
1707 * @param connectionManagerPhoneAccount See description at
1708 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
Cuihtlauac ALVARADO0b3b2a52016-09-13 14:49:41 +02001709 * @param request Details about the outgoing call.
Ihab Awadf8b69882014-07-25 15:14:01 -07001710 * @return The {@code Connection} object to satisfy this call, or {@code null} to
1711 * not handle the call.
1712 */
1713 public final RemoteConnection createRemoteOutgoingConnection(
1714 PhoneAccountHandle connectionManagerPhoneAccount,
1715 ConnectionRequest request) {
1716 return mRemoteConnectionManager.createRemoteConnection(
1717 connectionManagerPhoneAccount, request, false);
1718 }
1719
1720 /**
Santos Cordona663f862014-10-29 13:49:58 -07001721 * Indicates to the relevant {@code RemoteConnectionService} that the specified
1722 * {@link RemoteConnection}s should be merged into a conference call.
1723 * <p>
1724 * If the conference request is successful, the method {@link #onRemoteConferenceAdded} will
1725 * be invoked.
1726 *
1727 * @param remoteConnection1 The first of the remote connections to conference.
1728 * @param remoteConnection2 The second of the remote connections to conference.
Ihab Awadb8e85c72014-08-23 20:34:57 -07001729 */
1730 public final void conferenceRemoteConnections(
Santos Cordona663f862014-10-29 13:49:58 -07001731 RemoteConnection remoteConnection1,
1732 RemoteConnection remoteConnection2) {
1733 mRemoteConnectionManager.conferenceRemoteConnections(remoteConnection1, remoteConnection2);
Ihab Awadb8e85c72014-08-23 20:34:57 -07001734 }
1735
1736 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -07001737 * Adds a new conference call. When a conference call is created either as a result of an
1738 * explicit request via {@link #onConference} or otherwise, the connection service should supply
1739 * an instance of {@link Conference} by invoking this method. A conference call provided by this
1740 * method will persist until {@link Conference#destroy} is invoked on the conference instance.
1741 *
1742 * @param conference The new conference object.
1743 */
1744 public final void addConference(Conference conference) {
Rekha Kumar07366812015-03-24 16:42:31 -07001745 Log.d(this, "addConference: conference=%s", conference);
1746
Santos Cordon823fd3c2014-08-07 18:35:18 -07001747 String id = addConferenceInternal(conference);
1748 if (id != null) {
1749 List<String> connectionIds = new ArrayList<>(2);
1750 for (Connection connection : conference.getConnections()) {
1751 if (mIdByConnection.containsKey(connection)) {
1752 connectionIds.add(mIdByConnection.get(connection));
1753 }
1754 }
Tyler Gunnf0500bd2015-09-01 10:59:48 -07001755 conference.setTelecomCallId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001756 ParcelableConference parcelableConference = new ParcelableConference(
Nancy Chenea38cca2014-09-05 16:38:49 -07001757 conference.getPhoneAccountHandle(),
Santos Cordon823fd3c2014-08-07 18:35:18 -07001758 conference.getState(),
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001759 conference.getConnectionCapabilities(),
Tyler Gunn720c6642016-03-22 09:02:47 -07001760 conference.getConnectionProperties(),
Tyler Gunncd5d33c2015-01-12 09:02:01 -08001761 connectionIds,
Rekha Kumar07366812015-03-24 16:42:31 -07001762 conference.getVideoProvider() == null ?
1763 null : conference.getVideoProvider().getInterface(),
1764 conference.getVideoState(),
Andrew Lee3e3e2f22015-04-16 13:48:43 -07001765 conference.getConnectTimeMillis(),
Santos Cordon6b7f9552015-05-27 17:21:45 -07001766 conference.getStatusHints(),
1767 conference.getExtras());
Andrew Lee0f51da32015-04-16 13:11:55 -07001768
Santos Cordon823fd3c2014-08-07 18:35:18 -07001769 mAdapter.addConferenceCall(id, parcelableConference);
Rekha Kumar07366812015-03-24 16:42:31 -07001770 mAdapter.setVideoProvider(id, conference.getVideoProvider());
1771 mAdapter.setVideoState(id, conference.getVideoState());
Santos Cordon823fd3c2014-08-07 18:35:18 -07001772
1773 // Go through any child calls and set the parent.
1774 for (Connection connection : conference.getConnections()) {
1775 String connectionId = mIdByConnection.get(connection);
1776 if (connectionId != null) {
1777 mAdapter.setIsConferenced(connectionId, id);
1778 }
1779 }
1780 }
1781 }
1782
1783 /**
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07001784 * Adds a connection created by the {@link ConnectionService} and informs telecom of the new
1785 * connection.
1786 *
1787 * @param phoneAccountHandle The phone account handle for the connection.
1788 * @param connection The connection to add.
1789 */
1790 public final void addExistingConnection(PhoneAccountHandle phoneAccountHandle,
1791 Connection connection) {
1792
Tyler Gunnf0500bd2015-09-01 10:59:48 -07001793 String id = addExistingConnectionInternal(phoneAccountHandle, connection);
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07001794 if (id != null) {
1795 List<String> emptyList = new ArrayList<>(0);
1796
1797 ParcelableConnection parcelableConnection = new ParcelableConnection(
1798 phoneAccountHandle,
1799 connection.getState(),
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001800 connection.getConnectionCapabilities(),
Tyler Gunn720c6642016-03-22 09:02:47 -07001801 connection.getConnectionProperties(),
Christine Hallstrom2830ce92016-11-30 16:06:42 -08001802 connection.getSupportedAudioRoutes(),
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07001803 connection.getAddress(),
1804 connection.getAddressPresentation(),
1805 connection.getCallerDisplayName(),
1806 connection.getCallerDisplayNamePresentation(),
1807 connection.getVideoProvider() == null ?
1808 null : connection.getVideoProvider().getInterface(),
1809 connection.getVideoState(),
1810 connection.isRingbackRequested(),
1811 connection.getAudioModeIsVoip(),
Roshan Piuse927ec02015-07-15 15:47:21 -07001812 connection.getConnectTimeMillis(),
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07001813 connection.getStatusHints(),
1814 connection.getDisconnectCause(),
Santos Cordon6b7f9552015-05-27 17:21:45 -07001815 emptyList,
1816 connection.getExtras());
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07001817 mAdapter.addExistingConnection(id, parcelableConnection);
1818 }
1819 }
1820
1821 /**
Ihab Awadf8b69882014-07-25 15:14:01 -07001822 * Returns all the active {@code Connection}s for which this {@code ConnectionService}
1823 * has taken responsibility.
1824 *
1825 * @return A collection of {@code Connection}s created by this {@code ConnectionService}.
Santos Cordonb6939982014-06-04 20:20:58 -07001826 */
Sailesh Nepal091768c2014-06-30 15:15:23 -07001827 public final Collection<Connection> getAllConnections() {
Santos Cordonb6939982014-06-04 20:20:58 -07001828 return mConnectionById.values();
1829 }
1830
1831 /**
Santos Cordona6018b92016-02-16 14:23:12 -08001832 * Returns all the active {@code Conference}s for which this {@code ConnectionService}
1833 * has taken responsibility.
1834 *
1835 * @return A collection of {@code Conference}s created by this {@code ConnectionService}.
1836 */
1837 public final Collection<Conference> getAllConferences() {
1838 return mConferenceById.values();
1839 }
1840
1841 /**
Ihab Awadf8b69882014-07-25 15:14:01 -07001842 * Create a {@code Connection} given an incoming request. This is used to attach to existing
1843 * incoming calls.
Evan Charltonbf11f982014-07-20 22:06:28 -07001844 *
Ihab Awadf8b69882014-07-25 15:14:01 -07001845 * @param connectionManagerPhoneAccount See description at
1846 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
1847 * @param request Details about the incoming call.
1848 * @return The {@code Connection} object to satisfy this call, or {@code null} to
1849 * not handle the call.
Ihab Awad542e0ea2014-05-16 10:22:16 -07001850 */
Ihab Awadf8b69882014-07-25 15:14:01 -07001851 public Connection onCreateIncomingConnection(
1852 PhoneAccountHandle connectionManagerPhoneAccount,
1853 ConnectionRequest request) {
1854 return null;
1855 }
Sailesh Nepalc5b01572014-07-14 16:29:44 -07001856
1857 /**
Tyler Gunnf5035432017-01-09 09:43:12 -08001858 * Called by Telecom to inform the {@link ConnectionService} that its request to create a new
1859 * incoming {@link Connection} was denied.
1860 * <p>
1861 * Used when a self-managed {@link ConnectionService} attempts to create a new incoming
1862 * {@link Connection}, but Telecom has determined that the call cannot be allowed at this time.
1863 * The {@link ConnectionService} is responsible for silently rejecting the new incoming
1864 * {@link Connection}.
1865 * <p>
1866 * See {@link TelecomManager#isIncomingCallPermitted(PhoneAccountHandle)} for more information.
1867 *
Tyler Gunn159f35c2017-03-02 09:28:37 -08001868 * @param connectionManagerPhoneAccount See description at
1869 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
Tyler Gunnf5035432017-01-09 09:43:12 -08001870 * @param request The incoming connection request.
1871 */
Tyler Gunn159f35c2017-03-02 09:28:37 -08001872 public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount,
1873 ConnectionRequest request) {
Tyler Gunnf5035432017-01-09 09:43:12 -08001874 }
1875
1876 /**
1877 * Called by Telecom to inform the {@link ConnectionService} that its request to create a new
1878 * outgoing {@link Connection} was denied.
1879 * <p>
1880 * Used when a self-managed {@link ConnectionService} attempts to create a new outgoing
1881 * {@link Connection}, but Telecom has determined that the call cannot be placed at this time.
1882 * The {@link ConnectionService} is responisible for informing the user that the
1883 * {@link Connection} cannot be made at this time.
1884 * <p>
1885 * See {@link TelecomManager#isOutgoingCallPermitted(PhoneAccountHandle)} for more information.
1886 *
Tyler Gunn159f35c2017-03-02 09:28:37 -08001887 * @param connectionManagerPhoneAccount See description at
1888 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
Tyler Gunnf5035432017-01-09 09:43:12 -08001889 * @param request The outgoing connection request.
1890 */
Tyler Gunn159f35c2017-03-02 09:28:37 -08001891 public void onCreateOutgoingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount,
1892 ConnectionRequest request) {
Tyler Gunnf5035432017-01-09 09:43:12 -08001893 }
1894
1895 /**
Shriram Ganesh6bf35ac2014-12-11 17:53:38 -08001896 * Trigger recalculate functinality for conference calls. This is used when a Telephony
1897 * Connection is part of a conference controller but is not yet added to Connection
1898 * Service and hence cannot be added to the conference call.
1899 *
1900 * @hide
1901 */
1902 public void triggerConferenceRecalculate() {
1903 }
1904
1905 /**
Ihab Awadf8b69882014-07-25 15:14:01 -07001906 * Create a {@code Connection} given an outgoing request. This is used to initiate new
1907 * outgoing calls.
Sailesh Nepalc5b01572014-07-14 16:29:44 -07001908 *
Ihab Awadf8b69882014-07-25 15:14:01 -07001909 * @param connectionManagerPhoneAccount The connection manager account to use for managing
1910 * this call.
1911 * <p>
1912 * If this parameter is not {@code null}, it means that this {@code ConnectionService}
1913 * has registered one or more {@code PhoneAccount}s having
1914 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}. This parameter will contain
1915 * one of these {@code PhoneAccount}s, while the {@code request} will contain another
1916 * (usually but not always distinct) {@code PhoneAccount} to be used for actually
1917 * making the connection.
1918 * <p>
1919 * If this parameter is {@code null}, it means that this {@code ConnectionService} is
1920 * being asked to make a direct connection. The
1921 * {@link ConnectionRequest#getAccountHandle()} of parameter {@code request} will be
1922 * a {@code PhoneAccount} registered by this {@code ConnectionService} to use for
1923 * making the connection.
1924 * @param request Details about the outgoing call.
1925 * @return The {@code Connection} object to satisfy this call, or the result of an invocation
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001926 * of {@link Connection#createFailedConnection(DisconnectCause)} to not handle the call.
Sailesh Nepalc5b01572014-07-14 16:29:44 -07001927 */
Ihab Awadf8b69882014-07-25 15:14:01 -07001928 public Connection onCreateOutgoingConnection(
1929 PhoneAccountHandle connectionManagerPhoneAccount,
1930 ConnectionRequest request) {
1931 return null;
1932 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07001933
1934 /**
Yorke Leec3cf9822014-10-02 09:38:39 -07001935 * Create a {@code Connection} for a new unknown call. An unknown call is a call originating
1936 * from the ConnectionService that was neither a user-initiated outgoing call, nor an incoming
1937 * call created using
1938 * {@code TelecomManager#addNewIncomingCall(PhoneAccountHandle, android.os.Bundle)}.
1939 *
Yorke Lee770ed6e2014-10-06 18:58:52 -07001940 * @hide
Yorke Leec3cf9822014-10-02 09:38:39 -07001941 */
1942 public Connection onCreateUnknownConnection(PhoneAccountHandle connectionManagerPhoneAccount,
1943 ConnectionRequest request) {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001944 return null;
Yorke Leec3cf9822014-10-02 09:38:39 -07001945 }
1946
1947 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -07001948 * Conference two specified connections. Invoked when the user has made a request to merge the
1949 * specified connections into a conference call. In response, the connection service should
1950 * create an instance of {@link Conference} and pass it into {@link #addConference}.
Santos Cordonb6939982014-06-04 20:20:58 -07001951 *
Santos Cordon823fd3c2014-08-07 18:35:18 -07001952 * @param connection1 A connection to merge into a conference call.
1953 * @param connection2 A connection to merge into a conference call.
Santos Cordonb6939982014-06-04 20:20:58 -07001954 */
Santos Cordon823fd3c2014-08-07 18:35:18 -07001955 public void onConference(Connection connection1, Connection connection2) {}
Santos Cordonb6939982014-06-04 20:20:58 -07001956
Santos Cordona663f862014-10-29 13:49:58 -07001957 /**
1958 * Indicates that a remote conference has been created for existing {@link RemoteConnection}s.
1959 * When this method is invoked, this {@link ConnectionService} should create its own
1960 * representation of the conference call and send it to telecom using {@link #addConference}.
1961 * <p>
1962 * This is only relevant to {@link ConnectionService}s which are registered with
1963 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}.
1964 *
1965 * @param conference The remote conference call.
1966 */
Ihab Awadb8e85c72014-08-23 20:34:57 -07001967 public void onRemoteConferenceAdded(RemoteConference conference) {}
1968
Santos Cordon823fd3c2014-08-07 18:35:18 -07001969 /**
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07001970 * Called when an existing connection is added remotely.
1971 * @param connection The existing connection which was added.
1972 */
1973 public void onRemoteExistingConnectionAdded(RemoteConnection connection) {}
1974
1975 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -07001976 * @hide
1977 */
1978 public boolean containsConference(Conference conference) {
1979 return mIdByConference.containsKey(conference);
1980 }
1981
Ihab Awadb8e85c72014-08-23 20:34:57 -07001982 /** {@hide} */
1983 void addRemoteConference(RemoteConference remoteConference) {
1984 onRemoteConferenceAdded(remoteConference);
1985 }
1986
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07001987 /** {@hide} */
1988 void addRemoteExistingConnection(RemoteConnection remoteConnection) {
1989 onRemoteExistingConnectionAdded(remoteConnection);
1990 }
1991
Ihab Awad5d0410f2014-07-30 10:07:40 -07001992 private void onAccountsInitialized() {
1993 mAreAccountsInitialized = true;
1994 for (Runnable r : mPreInitializationConnectionRequests) {
1995 r.run();
1996 }
1997 mPreInitializationConnectionRequests.clear();
1998 }
1999
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002000 /**
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002001 * Adds an existing connection to the list of connections, identified by a new call ID unique
2002 * to this connection service.
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002003 *
2004 * @param connection The connection.
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002005 * @return The ID of the connection (e.g. the call-id).
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002006 */
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002007 private String addExistingConnectionInternal(PhoneAccountHandle handle, Connection connection) {
2008 String id;
Tyler Gunncd6ccfd2016-10-17 15:48:19 -07002009
2010 if (connection.getExtras() != null && connection.getExtras()
2011 .containsKey(Connection.EXTRA_ORIGINAL_CONNECTION_ID)) {
2012 id = connection.getExtras().getString(Connection.EXTRA_ORIGINAL_CONNECTION_ID);
2013 Log.d(this, "addExistingConnectionInternal - conn %s reusing original id %s",
2014 connection.getTelecomCallId(), id);
2015 } else if (handle == null) {
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002016 // If no phone account handle was provided, we cannot be sure the call ID is unique,
2017 // so just use a random UUID.
2018 id = UUID.randomUUID().toString();
2019 } else {
2020 // Phone account handle was provided, so use the ConnectionService class name as a
2021 // prefix for a unique incremental call ID.
2022 id = handle.getComponentName().getClassName() + "@" + getNextCallId();
2023 }
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002024 addConnection(id, connection);
2025 return id;
2026 }
2027
Ihab Awad542e0ea2014-05-16 10:22:16 -07002028 private void addConnection(String callId, Connection connection) {
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002029 connection.setTelecomCallId(callId);
Ihab Awad542e0ea2014-05-16 10:22:16 -07002030 mConnectionById.put(callId, connection);
2031 mIdByConnection.put(connection, callId);
2032 connection.addConnectionListener(mConnectionListener);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002033 connection.setConnectionService(this);
Ihab Awad542e0ea2014-05-16 10:22:16 -07002034 }
2035
Anthony Lee30e65842014-11-06 16:30:53 -08002036 /** {@hide} */
2037 protected void removeConnection(Connection connection) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002038 connection.unsetConnectionService(this);
Ihab Awad542e0ea2014-05-16 10:22:16 -07002039 connection.removeConnectionListener(mConnectionListener);
Chenjie Luoe370b532016-05-12 16:59:43 -07002040 String id = mIdByConnection.get(connection);
2041 if (id != null) {
2042 mConnectionById.remove(id);
2043 mIdByConnection.remove(connection);
2044 mAdapter.removeCall(id);
2045 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002046 }
2047
Santos Cordon823fd3c2014-08-07 18:35:18 -07002048 private String addConferenceInternal(Conference conference) {
Tyler Gunncd6ccfd2016-10-17 15:48:19 -07002049 String originalId = null;
2050 if (conference.getExtras() != null && conference.getExtras()
2051 .containsKey(Connection.EXTRA_ORIGINAL_CONNECTION_ID)) {
2052 originalId = conference.getExtras().getString(Connection.EXTRA_ORIGINAL_CONNECTION_ID);
2053 Log.d(this, "addConferenceInternal: conf %s reusing original id %s",
2054 conference.getTelecomCallId(),
2055 originalId);
2056 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002057 if (mIdByConference.containsKey(conference)) {
2058 Log.w(this, "Re-adding an existing conference: %s.", conference);
2059 } else if (conference != null) {
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002060 // Conferences do not (yet) have a PhoneAccountHandle associated with them, so we
2061 // cannot determine a ConnectionService class name to associate with the ID, so use
2062 // a unique UUID (for now).
Tyler Gunncd6ccfd2016-10-17 15:48:19 -07002063 String id = originalId == null ? UUID.randomUUID().toString() : originalId;
Santos Cordon823fd3c2014-08-07 18:35:18 -07002064 mConferenceById.put(id, conference);
2065 mIdByConference.put(conference, id);
2066 conference.addListener(mConferenceListener);
2067 return id;
2068 }
2069
2070 return null;
2071 }
2072
2073 private void removeConference(Conference conference) {
2074 if (mIdByConference.containsKey(conference)) {
2075 conference.removeListener(mConferenceListener);
2076
2077 String id = mIdByConference.get(conference);
2078 mConferenceById.remove(id);
2079 mIdByConference.remove(conference);
2080 mAdapter.removeCall(id);
2081 }
2082 }
2083
Ihab Awad542e0ea2014-05-16 10:22:16 -07002084 private Connection findConnectionForAction(String callId, String action) {
2085 if (mConnectionById.containsKey(callId)) {
2086 return mConnectionById.get(callId);
2087 }
Ihab Awad60ac30b2014-05-20 22:32:12 -07002088 Log.w(this, "%s - Cannot find Connection %s", action, callId);
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07002089 return getNullConnection();
2090 }
2091
2092 static synchronized Connection getNullConnection() {
2093 if (sNullConnection == null) {
2094 sNullConnection = new Connection() {};
2095 }
2096 return sNullConnection;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002097 }
Santos Cordon0159ac02014-08-21 14:28:11 -07002098
2099 private Conference findConferenceForAction(String conferenceId, String action) {
2100 if (mConferenceById.containsKey(conferenceId)) {
2101 return mConferenceById.get(conferenceId);
2102 }
2103 Log.w(this, "%s - Cannot find conference %s", action, conferenceId);
2104 return getNullConference();
2105 }
2106
Ihab Awadb8e85c72014-08-23 20:34:57 -07002107 private List<String> createConnectionIdList(List<Connection> connections) {
2108 List<String> ids = new ArrayList<>();
2109 for (Connection c : connections) {
2110 if (mIdByConnection.containsKey(c)) {
2111 ids.add(mIdByConnection.get(c));
2112 }
2113 }
2114 Collections.sort(ids);
2115 return ids;
2116 }
2117
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002118 /**
2119 * Builds a list of {@link Connection} and {@link Conference} IDs based on the list of
Tyler Gunndf2cbc82015-04-20 09:13:01 -07002120 * {@link Conferenceable}s passed in.
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002121 *
Tyler Gunndf2cbc82015-04-20 09:13:01 -07002122 * @param conferenceables The {@link Conferenceable} connections and conferences.
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002123 * @return List of string conference and call Ids.
2124 */
Tyler Gunndf2cbc82015-04-20 09:13:01 -07002125 private List<String> createIdList(List<Conferenceable> conferenceables) {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002126 List<String> ids = new ArrayList<>();
Tyler Gunndf2cbc82015-04-20 09:13:01 -07002127 for (Conferenceable c : conferenceables) {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002128 // Only allow Connection and Conference conferenceables.
2129 if (c instanceof Connection) {
2130 Connection connection = (Connection) c;
2131 if (mIdByConnection.containsKey(connection)) {
2132 ids.add(mIdByConnection.get(connection));
2133 }
2134 } else if (c instanceof Conference) {
2135 Conference conference = (Conference) c;
2136 if (mIdByConference.containsKey(conference)) {
2137 ids.add(mIdByConference.get(conference));
2138 }
2139 }
2140 }
2141 Collections.sort(ids);
2142 return ids;
2143 }
2144
Santos Cordon0159ac02014-08-21 14:28:11 -07002145 private Conference getNullConference() {
2146 if (sNullConference == null) {
2147 sNullConference = new Conference(null) {};
2148 }
2149 return sNullConference;
2150 }
Santos Cordon29f2f2e2014-09-11 19:50:24 -07002151
2152 private void endAllConnections() {
2153 // Unbound from telecomm. We should end all connections and conferences.
2154 for (Connection connection : mIdByConnection.keySet()) {
2155 // only operate on top-level calls. Conference calls will be removed on their own.
2156 if (connection.getConference() == null) {
2157 connection.onDisconnect();
2158 }
2159 }
2160 for (Conference conference : mIdByConference.keySet()) {
2161 conference.onDisconnect();
2162 }
2163 }
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002164
2165 /**
2166 * Retrieves the next call ID as maintainted by the connection service.
2167 *
2168 * @return The call ID.
2169 */
2170 private int getNextCallId() {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07002171 synchronized (mIdSyncRoot) {
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002172 return ++mId;
2173 }
2174 }
Santos Cordon980acb92014-05-31 10:31:19 -07002175}