blob: 440f044fdcf7880af90f0d2e0bda620ab2200670 [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
Tyler Gunn5567d742019-10-31 13:04:37 -070019import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.annotation.RequiresPermission;
Santos Cordon5c6fa952014-07-20 17:47:12 -070022import android.annotation.SdkConstant;
Tyler Gunn5567d742019-10-31 13:04:37 -070023import android.annotation.SystemApi;
Sailesh Nepal2a46b902014-07-04 17:21:07 -070024import android.app.Service;
Santos Cordon52d8a152014-06-17 19:08:45 -070025import android.content.ComponentName;
Santos Cordon5c6fa952014-07-20 17:47:12 -070026import android.content.Intent;
Ihab Awad542e0ea2014-05-16 10:22:16 -070027import android.net.Uri;
Santos Cordon6b7f9552015-05-27 17:21:45 -070028import android.os.Bundle;
Santos Cordon52d8a152014-06-17 19:08:45 -070029import android.os.Handler;
30import android.os.IBinder;
31import android.os.Looper;
Sailesh Nepal2a46b902014-07-04 17:21:07 -070032import android.os.Message;
Hall Liub64ac4c2017-02-06 10:49:48 -080033import android.os.ParcelFileDescriptor;
34import android.os.RemoteException;
Brad Ebingerb32d4f82016-10-24 16:40:49 -070035import android.telecom.Logging.Session;
Andrew Lee14185762014-07-25 09:41:56 -070036
Brad Ebinger99f17ce2019-09-11 18:06:51 -070037import com.android.internal.annotations.VisibleForTesting;
Sailesh Nepal2a46b902014-07-04 17:21:07 -070038import com.android.internal.os.SomeArgs;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070039import com.android.internal.telecom.IConnectionService;
40import com.android.internal.telecom.IConnectionServiceAdapter;
41import com.android.internal.telecom.RemoteServiceCallback;
Santos Cordon52d8a152014-06-17 19:08:45 -070042
Ihab Awad5d0410f2014-07-30 10:07:40 -070043import java.util.ArrayList;
Santos Cordonb6939982014-06-04 20:20:58 -070044import java.util.Collection;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070045import java.util.Collections;
Santos Cordon52d8a152014-06-17 19:08:45 -070046import java.util.List;
Ihab Awad542e0ea2014-05-16 10:22:16 -070047import java.util.Map;
Santos Cordon823fd3c2014-08-07 18:35:18 -070048import java.util.UUID;
mike dooley95e80702014-09-18 14:07:52 -070049import java.util.concurrent.ConcurrentHashMap;
Ihab Awad542e0ea2014-05-16 10:22:16 -070050
51/**
Tyler Gunnf5035432017-01-09 09:43:12 -080052 * An abstract service that should be implemented by any apps which either:
53 * <ol>
54 * <li>Can make phone calls (VoIP or otherwise) and want those calls to be integrated into the
55 * built-in phone app. Referred to as a <b>system managed</b> {@link ConnectionService}.</li>
56 * <li>Are a standalone calling app and don't want their calls to be integrated into the
57 * built-in phone app. Referred to as a <b>self managed</b> {@link ConnectionService}.</li>
58 * </ol>
59 * Once implemented, the {@link ConnectionService} needs to take the following steps so that Telecom
60 * will bind to it:
Santos Cordona663f862014-10-29 13:49:58 -070061 * <p>
62 * 1. <i>Registration in AndroidManifest.xml</i>
63 * <br/>
64 * <pre>
65 * &lt;service android:name="com.example.package.MyConnectionService"
66 * android:label="@string/some_label_for_my_connection_service"
Yorke Lee249c12e2015-05-13 15:59:29 -070067 * android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"&gt;
Santos Cordona663f862014-10-29 13:49:58 -070068 * &lt;intent-filter&gt;
69 * &lt;action android:name="android.telecom.ConnectionService" /&gt;
70 * &lt;/intent-filter&gt;
71 * &lt;/service&gt;
72 * </pre>
73 * <p>
74 * 2. <i> Registration of {@link PhoneAccount} with {@link TelecomManager}.</i>
75 * <br/>
76 * See {@link PhoneAccount} and {@link TelecomManager#registerPhoneAccount} for more information.
77 * <p>
Tyler Gunnf5035432017-01-09 09:43:12 -080078 * System managed {@link ConnectionService}s must be enabled by the user in the phone app settings
kopriva82c591b2018-10-08 15:57:00 -070079 * before Telecom will bind to them. Self-managed {@link ConnectionService}s must be granted the
Tyler Gunnf5035432017-01-09 09:43:12 -080080 * appropriate permission before Telecom will bind to them.
81 * <p>
82 * Once registered and enabled by the user in the phone app settings or granted permission, telecom
83 * will bind to a {@link ConnectionService} implementation when it wants that
84 * {@link ConnectionService} to place a call or the service has indicated that is has an incoming
85 * call through {@link TelecomManager#addNewIncomingCall}. The {@link ConnectionService} can then
86 * expect a call to {@link #onCreateIncomingConnection} or {@link #onCreateOutgoingConnection}
87 * wherein it should provide a new instance of a {@link Connection} object. It is through this
88 * {@link Connection} object that telecom receives state updates and the {@link ConnectionService}
Santos Cordona663f862014-10-29 13:49:58 -070089 * receives call-commands such as answer, reject, hold and disconnect.
90 * <p>
Tyler Gunnf5035432017-01-09 09:43:12 -080091 * When there are no more live calls, telecom will unbind from the {@link ConnectionService}.
Ihab Awad542e0ea2014-05-16 10:22:16 -070092 */
Sailesh Nepal2a46b902014-07-04 17:21:07 -070093public abstract class ConnectionService extends Service {
Santos Cordon5c6fa952014-07-20 17:47:12 -070094 /**
95 * The {@link Intent} that must be declared as handled by the service.
96 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -070097 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
Tyler Gunnef9f6f92014-09-12 22:16:17 -070098 public static final String SERVICE_INTERFACE = "android.telecom.ConnectionService";
Santos Cordon5c6fa952014-07-20 17:47:12 -070099
Tyler Gunn8bf76572017-04-06 15:30:08 -0700100 /**
101 * Boolean extra used by Telecom to inform a {@link ConnectionService} that the purpose of it
102 * being asked to create a new outgoing {@link Connection} is to perform a handover of an
103 * ongoing call on the device from another {@link PhoneAccount}/{@link ConnectionService}. Will
104 * be specified in the {@link ConnectionRequest#getExtras()} passed by Telecom when
105 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)} is called.
106 * <p>
Tyler Gunn727c6bd2017-04-11 09:51:40 -0700107 * When your {@link ConnectionService} receives this extra, it should communicate the fact that
108 * this is a handover to the other device's matching {@link ConnectionService}. That
Tyler Gunn8bf76572017-04-06 15:30:08 -0700109 * {@link ConnectionService} will continue the handover using
110 * {@link TelecomManager#addNewIncomingCall(PhoneAccountHandle, Bundle)}, specifying
Tyler Gunn727c6bd2017-04-11 09:51:40 -0700111 * {@link TelecomManager#EXTRA_IS_HANDOVER}. Telecom will match the phone numbers of the
112 * handover call on the other device with ongoing calls for {@link ConnectionService}s which
113 * support {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700114 * @hide
115 */
116 public static final String EXTRA_IS_HANDOVER = TelecomManager.EXTRA_IS_HANDOVER;
117
Ihab Awad542e0ea2014-05-16 10:22:16 -0700118 // Flag controlling whether PII is emitted into the logs
Ihab Awad60ac30b2014-05-20 22:32:12 -0700119 private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700120
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700121 // Session Definitions
122 private static final String SESSION_HANDLER = "H.";
123 private static final String SESSION_ADD_CS_ADAPTER = "CS.aCSA";
124 private static final String SESSION_REMOVE_CS_ADAPTER = "CS.rCSA";
125 private static final String SESSION_CREATE_CONN = "CS.crCo";
Tyler Gunn041a1fe2017-05-12 10:04:49 -0700126 private static final String SESSION_CREATE_CONN_COMPLETE = "CS.crCoC";
Tyler Gunn44e01912017-01-31 10:49:05 -0800127 private static final String SESSION_CREATE_CONN_FAILED = "CS.crCoF";
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700128 private static final String SESSION_ABORT = "CS.ab";
129 private static final String SESSION_ANSWER = "CS.an";
130 private static final String SESSION_ANSWER_VIDEO = "CS.anV";
Pooja Jaind34698d2017-12-28 14:15:31 +0530131 private static final String SESSION_DEFLECT = "CS.def";
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700132 private static final String SESSION_REJECT = "CS.r";
133 private static final String SESSION_REJECT_MESSAGE = "CS.rWM";
134 private static final String SESSION_SILENCE = "CS.s";
135 private static final String SESSION_DISCONNECT = "CS.d";
136 private static final String SESSION_HOLD = "CS.h";
137 private static final String SESSION_UNHOLD = "CS.u";
138 private static final String SESSION_CALL_AUDIO_SC = "CS.cASC";
139 private static final String SESSION_PLAY_DTMF = "CS.pDT";
140 private static final String SESSION_STOP_DTMF = "CS.sDT";
141 private static final String SESSION_CONFERENCE = "CS.c";
142 private static final String SESSION_SPLIT_CONFERENCE = "CS.sFC";
143 private static final String SESSION_MERGE_CONFERENCE = "CS.mC";
144 private static final String SESSION_SWAP_CONFERENCE = "CS.sC";
145 private static final String SESSION_POST_DIAL_CONT = "CS.oPDC";
146 private static final String SESSION_PULL_EXTERNAL_CALL = "CS.pEC";
147 private static final String SESSION_SEND_CALL_EVENT = "CS.sCE";
Tyler Gunn79bc1ec2018-01-22 15:17:54 -0800148 private static final String SESSION_HANDOVER_COMPLETE = "CS.hC";
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700149 private static final String SESSION_EXTRAS_CHANGED = "CS.oEC";
Hall Liub64ac4c2017-02-06 10:49:48 -0800150 private static final String SESSION_START_RTT = "CS.+RTT";
Hall Liua549fed2018-02-09 16:40:03 -0800151 private static final String SESSION_UPDATE_RTT_PIPES = "CS.uRTT";
Hall Liub64ac4c2017-02-06 10:49:48 -0800152 private static final String SESSION_STOP_RTT = "CS.-RTT";
153 private static final String SESSION_RTT_UPGRADE_RESPONSE = "CS.rTRUR";
Pengquan Meng731c1a32017-11-21 18:01:13 -0800154 private static final String SESSION_CONNECTION_SERVICE_FOCUS_LOST = "CS.cSFL";
155 private static final String SESSION_CONNECTION_SERVICE_FOCUS_GAINED = "CS.cSFG";
Sanket Padawe4cc8ed52017-12-04 16:22:20 -0800156 private static final String SESSION_HANDOVER_FAILED = "CS.haF";
Ravi Paluri80aa2142019-12-02 11:57:37 +0530157 private static final String SESSION_CREATE_CONF = "CS.crConf";
158 private static final String SESSION_CREATE_CONF_COMPLETE = "CS.crConfC";
159 private static final String SESSION_CREATE_CONF_FAILED = "CS.crConfF";
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700160
Ihab Awad8aecfed2014-08-08 17:06:11 -0700161 private static final int MSG_ADD_CONNECTION_SERVICE_ADAPTER = 1;
Sailesh Nepalc5b01572014-07-14 16:29:44 -0700162 private static final int MSG_CREATE_CONNECTION = 2;
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700163 private static final int MSG_ABORT = 3;
Sailesh Nepalc5b01572014-07-14 16:29:44 -0700164 private static final int MSG_ANSWER = 4;
165 private static final int MSG_REJECT = 5;
166 private static final int MSG_DISCONNECT = 6;
167 private static final int MSG_HOLD = 7;
168 private static final int MSG_UNHOLD = 8;
Yorke Lee4af59352015-05-13 14:14:54 -0700169 private static final int MSG_ON_CALL_AUDIO_STATE_CHANGED = 9;
Sailesh Nepalc5b01572014-07-14 16:29:44 -0700170 private static final int MSG_PLAY_DTMF_TONE = 10;
171 private static final int MSG_STOP_DTMF_TONE = 11;
172 private static final int MSG_CONFERENCE = 12;
173 private static final int MSG_SPLIT_FROM_CONFERENCE = 13;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700174 private static final int MSG_ON_POST_DIAL_CONTINUE = 14;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700175 private static final int MSG_REMOVE_CONNECTION_SERVICE_ADAPTER = 16;
Tyler Gunnbe74de02014-08-29 14:51:48 -0700176 private static final int MSG_ANSWER_VIDEO = 17;
Santos Cordona4868042014-09-04 17:39:22 -0700177 private static final int MSG_MERGE_CONFERENCE = 18;
178 private static final int MSG_SWAP_CONFERENCE = 19;
Bryce Lee81901682015-08-28 16:38:02 -0700179 private static final int MSG_REJECT_WITH_MESSAGE = 20;
Bryce Leecac50772015-11-17 15:13:29 -0800180 private static final int MSG_SILENCE = 21;
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700181 private static final int MSG_PULL_EXTERNAL_CALL = 22;
182 private static final int MSG_SEND_CALL_EVENT = 23;
Tyler Gunndee56a82016-03-23 16:06:34 -0700183 private static final int MSG_ON_EXTRAS_CHANGED = 24;
Tyler Gunn44e01912017-01-31 10:49:05 -0800184 private static final int MSG_CREATE_CONNECTION_FAILED = 25;
Hall Liub64ac4c2017-02-06 10:49:48 -0800185 private static final int MSG_ON_START_RTT = 26;
186 private static final int MSG_ON_STOP_RTT = 27;
187 private static final int MSG_RTT_UPGRADE_RESPONSE = 28;
Tyler Gunn041a1fe2017-05-12 10:04:49 -0700188 private static final int MSG_CREATE_CONNECTION_COMPLETE = 29;
Pengquan Meng731c1a32017-11-21 18:01:13 -0800189 private static final int MSG_CONNECTION_SERVICE_FOCUS_LOST = 30;
190 private static final int MSG_CONNECTION_SERVICE_FOCUS_GAINED = 31;
Sanket Padawe4cc8ed52017-12-04 16:22:20 -0800191 private static final int MSG_HANDOVER_FAILED = 32;
Tyler Gunn79bc1ec2018-01-22 15:17:54 -0800192 private static final int MSG_HANDOVER_COMPLETE = 33;
Pooja Jaind34698d2017-12-28 14:15:31 +0530193 private static final int MSG_DEFLECT = 34;
Ravi Paluri80aa2142019-12-02 11:57:37 +0530194 private static final int MSG_CREATE_CONFERENCE = 35;
195 private static final int MSG_CREATE_CONFERENCE_COMPLETE = 36;
196 private static final int MSG_CREATE_CONFERENCE_FAILED = 37;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700197
Sailesh Nepalcf7020b2014-08-20 10:07:19 -0700198 private static Connection sNullConnection;
199
mike dooley95e80702014-09-18 14:07:52 -0700200 private final Map<String, Connection> mConnectionById = new ConcurrentHashMap<>();
201 private final Map<Connection, String> mIdByConnection = new ConcurrentHashMap<>();
202 private final Map<String, Conference> mConferenceById = new ConcurrentHashMap<>();
203 private final Map<Conference, String> mIdByConference = new ConcurrentHashMap<>();
Ihab Awadb8e85c72014-08-23 20:34:57 -0700204 private final RemoteConnectionManager mRemoteConnectionManager =
205 new RemoteConnectionManager(this);
Ihab Awad5d0410f2014-07-30 10:07:40 -0700206 private final List<Runnable> mPreInitializationConnectionRequests = new ArrayList<>();
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700207 private final ConnectionServiceAdapter mAdapter = new ConnectionServiceAdapter();
Ihab Awad542e0ea2014-05-16 10:22:16 -0700208
Santos Cordon823fd3c2014-08-07 18:35:18 -0700209 private boolean mAreAccountsInitialized = false;
Santos Cordon0159ac02014-08-21 14:28:11 -0700210 private Conference sNullConference;
Tyler Gunnf0500bd2015-09-01 10:59:48 -0700211 private Object mIdSyncRoot = new Object();
212 private int mId = 0;
Santos Cordon823fd3c2014-08-07 18:35:18 -0700213
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700214 private final IBinder mBinder = new IConnectionService.Stub() {
215 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700216 public void addConnectionServiceAdapter(IConnectionServiceAdapter adapter,
217 Session.Info sessionInfo) {
218 Log.startSession(sessionInfo, SESSION_ADD_CS_ADAPTER);
219 try {
220 SomeArgs args = SomeArgs.obtain();
221 args.arg1 = adapter;
222 args.arg2 = Log.createSubsession();
223 mHandler.obtainMessage(MSG_ADD_CONNECTION_SERVICE_ADAPTER, args).sendToTarget();
224 } finally {
225 Log.endSession();
226 }
Ihab Awad8aecfed2014-08-08 17:06:11 -0700227 }
228
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700229 public void removeConnectionServiceAdapter(IConnectionServiceAdapter adapter,
230 Session.Info sessionInfo) {
231 Log.startSession(sessionInfo, SESSION_REMOVE_CS_ADAPTER);
232 try {
233 SomeArgs args = SomeArgs.obtain();
234 args.arg1 = adapter;
235 args.arg2 = Log.createSubsession();
236 mHandler.obtainMessage(MSG_REMOVE_CONNECTION_SERVICE_ADAPTER, args).sendToTarget();
237 } finally {
238 Log.endSession();
239 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700240 }
241
242 @Override
Ihab Awadf8b69882014-07-25 15:14:01 -0700243 public void createConnection(
244 PhoneAccountHandle connectionManagerPhoneAccount,
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700245 String id,
Ihab Awadf8b69882014-07-25 15:14:01 -0700246 ConnectionRequest request,
Yorke Leec3cf9822014-10-02 09:38:39 -0700247 boolean isIncoming,
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700248 boolean isUnknown,
249 Session.Info sessionInfo) {
250 Log.startSession(sessionInfo, SESSION_CREATE_CONN);
251 try {
252 SomeArgs args = SomeArgs.obtain();
253 args.arg1 = connectionManagerPhoneAccount;
254 args.arg2 = id;
255 args.arg3 = request;
256 args.arg4 = Log.createSubsession();
257 args.argi1 = isIncoming ? 1 : 0;
258 args.argi2 = isUnknown ? 1 : 0;
259 mHandler.obtainMessage(MSG_CREATE_CONNECTION, args).sendToTarget();
260 } finally {
261 Log.endSession();
262 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700263 }
264
265 @Override
Tyler Gunn041a1fe2017-05-12 10:04:49 -0700266 public void createConnectionComplete(String id, Session.Info sessionInfo) {
267 Log.startSession(sessionInfo, SESSION_CREATE_CONN_COMPLETE);
268 try {
269 SomeArgs args = SomeArgs.obtain();
270 args.arg1 = id;
271 args.arg2 = Log.createSubsession();
272 mHandler.obtainMessage(MSG_CREATE_CONNECTION_COMPLETE, args).sendToTarget();
273 } finally {
274 Log.endSession();
275 }
276 }
277
278 @Override
Tyler Gunn44e01912017-01-31 10:49:05 -0800279 public void createConnectionFailed(
Tyler Gunn159f35c2017-03-02 09:28:37 -0800280 PhoneAccountHandle connectionManagerPhoneAccount,
Tyler Gunn44e01912017-01-31 10:49:05 -0800281 String callId,
282 ConnectionRequest request,
283 boolean isIncoming,
284 Session.Info sessionInfo) {
285 Log.startSession(sessionInfo, SESSION_CREATE_CONN_FAILED);
286 try {
287 SomeArgs args = SomeArgs.obtain();
288 args.arg1 = callId;
289 args.arg2 = request;
290 args.arg3 = Log.createSubsession();
Tyler Gunn159f35c2017-03-02 09:28:37 -0800291 args.arg4 = connectionManagerPhoneAccount;
Tyler Gunn44e01912017-01-31 10:49:05 -0800292 args.argi1 = isIncoming ? 1 : 0;
293 mHandler.obtainMessage(MSG_CREATE_CONNECTION_FAILED, args).sendToTarget();
294 } finally {
295 Log.endSession();
296 }
297 }
298
299 @Override
Ravi Paluri80aa2142019-12-02 11:57:37 +0530300 public void createConference(
301 PhoneAccountHandle connectionManagerPhoneAccount,
302 String id,
303 ConnectionRequest request,
304 boolean isIncoming,
305 boolean isUnknown,
306 Session.Info sessionInfo) {
307 Log.startSession(sessionInfo, SESSION_CREATE_CONF);
308 try {
309 SomeArgs args = SomeArgs.obtain();
310 args.arg1 = connectionManagerPhoneAccount;
311 args.arg2 = id;
312 args.arg3 = request;
313 args.arg4 = Log.createSubsession();
314 args.argi1 = isIncoming ? 1 : 0;
315 args.argi2 = isUnknown ? 1 : 0;
316 mHandler.obtainMessage(MSG_CREATE_CONFERENCE, args).sendToTarget();
317 } finally {
318 Log.endSession();
319 }
320 }
321
322 @Override
323 public void createConferenceComplete(String id, Session.Info sessionInfo) {
324 Log.startSession(sessionInfo, SESSION_CREATE_CONF_COMPLETE);
325 try {
326 SomeArgs args = SomeArgs.obtain();
327 args.arg1 = id;
328 args.arg2 = Log.createSubsession();
329 mHandler.obtainMessage(MSG_CREATE_CONFERENCE_COMPLETE, args).sendToTarget();
330 } finally {
331 Log.endSession();
332 }
333 }
334
335 @Override
336 public void createConferenceFailed(
337 PhoneAccountHandle connectionManagerPhoneAccount,
338 String callId,
339 ConnectionRequest request,
340 boolean isIncoming,
341 Session.Info sessionInfo) {
342 Log.startSession(sessionInfo, SESSION_CREATE_CONF_FAILED);
343 try {
344 SomeArgs args = SomeArgs.obtain();
345 args.arg1 = callId;
346 args.arg2 = request;
347 args.arg3 = Log.createSubsession();
348 args.arg4 = connectionManagerPhoneAccount;
349 args.argi1 = isIncoming ? 1 : 0;
350 mHandler.obtainMessage(MSG_CREATE_CONFERENCE_FAILED, args).sendToTarget();
351 } finally {
352 Log.endSession();
353 }
354 }
355
356 @Override
Sanket Padawe4cc8ed52017-12-04 16:22:20 -0800357 public void handoverFailed(String callId, ConnectionRequest request, int reason,
358 Session.Info sessionInfo) {
359 Log.startSession(sessionInfo, SESSION_HANDOVER_FAILED);
360 try {
361 SomeArgs args = SomeArgs.obtain();
362 args.arg1 = callId;
363 args.arg2 = request;
364 args.arg3 = Log.createSubsession();
365 args.arg4 = reason;
366 mHandler.obtainMessage(MSG_HANDOVER_FAILED, args).sendToTarget();
367 } finally {
368 Log.endSession();
369 }
370 }
371
372 @Override
Tyler Gunn79bc1ec2018-01-22 15:17:54 -0800373 public void handoverComplete(String callId, Session.Info sessionInfo) {
374 Log.startSession(sessionInfo, SESSION_HANDOVER_COMPLETE);
375 try {
376 SomeArgs args = SomeArgs.obtain();
377 args.arg1 = callId;
378 args.arg2 = Log.createSubsession();
379 mHandler.obtainMessage(MSG_HANDOVER_COMPLETE, args).sendToTarget();
380 } finally {
381 Log.endSession();
382 }
383 }
384
385 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700386 public void abort(String callId, Session.Info sessionInfo) {
387 Log.startSession(sessionInfo, SESSION_ABORT);
388 try {
389 SomeArgs args = SomeArgs.obtain();
390 args.arg1 = callId;
391 args.arg2 = Log.createSubsession();
392 mHandler.obtainMessage(MSG_ABORT, args).sendToTarget();
393 } finally {
394 Log.endSession();
395 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700396 }
397
398 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700399 public void answerVideo(String callId, int videoState, Session.Info sessionInfo) {
400 Log.startSession(sessionInfo, SESSION_ANSWER_VIDEO);
401 try {
402 SomeArgs args = SomeArgs.obtain();
403 args.arg1 = callId;
404 args.arg2 = Log.createSubsession();
405 args.argi1 = videoState;
406 mHandler.obtainMessage(MSG_ANSWER_VIDEO, args).sendToTarget();
407 } finally {
408 Log.endSession();
409 }
Tyler Gunnbe74de02014-08-29 14:51:48 -0700410 }
411
412 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700413 public void answer(String callId, Session.Info sessionInfo) {
414 Log.startSession(sessionInfo, SESSION_ANSWER);
415 try {
416 SomeArgs args = SomeArgs.obtain();
417 args.arg1 = callId;
418 args.arg2 = Log.createSubsession();
419 mHandler.obtainMessage(MSG_ANSWER, args).sendToTarget();
420 } finally {
421 Log.endSession();
422 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700423 }
424
425 @Override
Pooja Jaind34698d2017-12-28 14:15:31 +0530426 public void deflect(String callId, Uri address, Session.Info sessionInfo) {
427 Log.startSession(sessionInfo, SESSION_DEFLECT);
428 try {
429 SomeArgs args = SomeArgs.obtain();
430 args.arg1 = callId;
431 args.arg2 = address;
432 args.arg3 = Log.createSubsession();
433 mHandler.obtainMessage(MSG_DEFLECT, args).sendToTarget();
434 } finally {
435 Log.endSession();
436 }
437 }
438
439 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700440 public void reject(String callId, Session.Info sessionInfo) {
441 Log.startSession(sessionInfo, SESSION_REJECT);
442 try {
443 SomeArgs args = SomeArgs.obtain();
444 args.arg1 = callId;
445 args.arg2 = Log.createSubsession();
446 mHandler.obtainMessage(MSG_REJECT, args).sendToTarget();
447 } finally {
448 Log.endSession();
449 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700450 }
451
452 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700453 public void rejectWithMessage(String callId, String message, Session.Info sessionInfo) {
454 Log.startSession(sessionInfo, SESSION_REJECT_MESSAGE);
455 try {
456 SomeArgs args = SomeArgs.obtain();
457 args.arg1 = callId;
458 args.arg2 = message;
459 args.arg3 = Log.createSubsession();
460 mHandler.obtainMessage(MSG_REJECT_WITH_MESSAGE, args).sendToTarget();
461 } finally {
462 Log.endSession();
463 }
Bryce Lee81901682015-08-28 16:38:02 -0700464 }
465
466 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700467 public void silence(String callId, Session.Info sessionInfo) {
468 Log.startSession(sessionInfo, SESSION_SILENCE);
469 try {
470 SomeArgs args = SomeArgs.obtain();
471 args.arg1 = callId;
472 args.arg2 = Log.createSubsession();
473 mHandler.obtainMessage(MSG_SILENCE, args).sendToTarget();
474 } finally {
475 Log.endSession();
476 }
Bryce Leecac50772015-11-17 15:13:29 -0800477 }
478
479 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700480 public void disconnect(String callId, Session.Info sessionInfo) {
481 Log.startSession(sessionInfo, SESSION_DISCONNECT);
482 try {
483 SomeArgs args = SomeArgs.obtain();
484 args.arg1 = callId;
485 args.arg2 = Log.createSubsession();
486 mHandler.obtainMessage(MSG_DISCONNECT, args).sendToTarget();
487 } finally {
488 Log.endSession();
489 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700490 }
491
492 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700493 public void hold(String callId, Session.Info sessionInfo) {
494 Log.startSession(sessionInfo, SESSION_HOLD);
495 try {
496 SomeArgs args = SomeArgs.obtain();
497 args.arg1 = callId;
498 args.arg2 = Log.createSubsession();
499 mHandler.obtainMessage(MSG_HOLD, args).sendToTarget();
500 } finally {
501 Log.endSession();
502 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700503 }
504
505 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700506 public void unhold(String callId, Session.Info sessionInfo) {
507 Log.startSession(sessionInfo, SESSION_UNHOLD);
508 try {
509 SomeArgs args = SomeArgs.obtain();
510 args.arg1 = callId;
511 args.arg2 = Log.createSubsession();
512 mHandler.obtainMessage(MSG_UNHOLD, args).sendToTarget();
513 } finally {
514 Log.endSession();
515 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700516 }
517
518 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700519 public void onCallAudioStateChanged(String callId, CallAudioState callAudioState,
520 Session.Info sessionInfo) {
521 Log.startSession(sessionInfo, SESSION_CALL_AUDIO_SC);
522 try {
523 SomeArgs args = SomeArgs.obtain();
524 args.arg1 = callId;
525 args.arg2 = callAudioState;
526 args.arg3 = Log.createSubsession();
527 mHandler.obtainMessage(MSG_ON_CALL_AUDIO_STATE_CHANGED, args).sendToTarget();
528 } finally {
529 Log.endSession();
530 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700531 }
532
533 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700534 public void playDtmfTone(String callId, char digit, Session.Info sessionInfo) {
535 Log.startSession(sessionInfo, SESSION_PLAY_DTMF);
536 try {
537 SomeArgs args = SomeArgs.obtain();
538 args.arg1 = digit;
539 args.arg2 = callId;
540 args.arg3 = Log.createSubsession();
541 mHandler.obtainMessage(MSG_PLAY_DTMF_TONE, args).sendToTarget();
542 } finally {
543 Log.endSession();
544 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700545 }
546
547 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700548 public void stopDtmfTone(String callId, Session.Info sessionInfo) {
549 Log.startSession(sessionInfo, SESSION_STOP_DTMF);
550 try {
551 SomeArgs args = SomeArgs.obtain();
552 args.arg1 = callId;
553 args.arg2 = Log.createSubsession();
554 mHandler.obtainMessage(MSG_STOP_DTMF_TONE, args).sendToTarget();
555 } finally {
556 Log.endSession();
557 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700558 }
559
560 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700561 public void conference(String callId1, String callId2, Session.Info sessionInfo) {
562 Log.startSession(sessionInfo, SESSION_CONFERENCE);
563 try {
564 SomeArgs args = SomeArgs.obtain();
565 args.arg1 = callId1;
566 args.arg2 = callId2;
567 args.arg3 = Log.createSubsession();
568 mHandler.obtainMessage(MSG_CONFERENCE, args).sendToTarget();
569 } finally {
570 Log.endSession();
571 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700572 }
573
574 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700575 public void splitFromConference(String callId, Session.Info sessionInfo) {
576 Log.startSession(sessionInfo, SESSION_SPLIT_CONFERENCE);
577 try {
578 SomeArgs args = SomeArgs.obtain();
579 args.arg1 = callId;
580 args.arg2 = Log.createSubsession();
581 mHandler.obtainMessage(MSG_SPLIT_FROM_CONFERENCE, args).sendToTarget();
582 } finally {
583 Log.endSession();
584 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700585 }
586
587 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700588 public void mergeConference(String callId, Session.Info sessionInfo) {
589 Log.startSession(sessionInfo, SESSION_MERGE_CONFERENCE);
590 try {
591 SomeArgs args = SomeArgs.obtain();
592 args.arg1 = callId;
593 args.arg2 = Log.createSubsession();
594 mHandler.obtainMessage(MSG_MERGE_CONFERENCE, args).sendToTarget();
595 } finally {
596 Log.endSession();
597 }
Santos Cordona4868042014-09-04 17:39:22 -0700598 }
599
600 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700601 public void swapConference(String callId, Session.Info sessionInfo) {
602 Log.startSession(sessionInfo, SESSION_SWAP_CONFERENCE);
603 try {
604 SomeArgs args = SomeArgs.obtain();
605 args.arg1 = callId;
606 args.arg2 = Log.createSubsession();
607 mHandler.obtainMessage(MSG_SWAP_CONFERENCE, args).sendToTarget();
608 } finally {
609 Log.endSession();
610 }
Santos Cordona4868042014-09-04 17:39:22 -0700611 }
612
613 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700614 public void onPostDialContinue(String callId, boolean proceed, Session.Info sessionInfo) {
615 Log.startSession(sessionInfo, SESSION_POST_DIAL_CONT);
616 try {
617 SomeArgs args = SomeArgs.obtain();
618 args.arg1 = callId;
619 args.arg2 = Log.createSubsession();
620 args.argi1 = proceed ? 1 : 0;
621 mHandler.obtainMessage(MSG_ON_POST_DIAL_CONTINUE, args).sendToTarget();
622 } finally {
623 Log.endSession();
624 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700625 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700626
627 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700628 public void pullExternalCall(String callId, Session.Info sessionInfo) {
629 Log.startSession(sessionInfo, SESSION_PULL_EXTERNAL_CALL);
630 try {
631 SomeArgs args = SomeArgs.obtain();
632 args.arg1 = callId;
633 args.arg2 = Log.createSubsession();
634 mHandler.obtainMessage(MSG_PULL_EXTERNAL_CALL, args).sendToTarget();
635 } finally {
636 Log.endSession();
637 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700638 }
639
640 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700641 public void sendCallEvent(String callId, String event, Bundle extras,
642 Session.Info sessionInfo) {
643 Log.startSession(sessionInfo, SESSION_SEND_CALL_EVENT);
644 try {
645 SomeArgs args = SomeArgs.obtain();
646 args.arg1 = callId;
647 args.arg2 = event;
648 args.arg3 = extras;
649 args.arg4 = Log.createSubsession();
650 mHandler.obtainMessage(MSG_SEND_CALL_EVENT, args).sendToTarget();
651 } finally {
652 Log.endSession();
653 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700654 }
Tyler Gunndee56a82016-03-23 16:06:34 -0700655
656 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700657 public void onExtrasChanged(String callId, Bundle extras, Session.Info sessionInfo) {
658 Log.startSession(sessionInfo, SESSION_EXTRAS_CHANGED);
659 try {
660 SomeArgs args = SomeArgs.obtain();
661 args.arg1 = callId;
662 args.arg2 = extras;
663 args.arg3 = Log.createSubsession();
664 mHandler.obtainMessage(MSG_ON_EXTRAS_CHANGED, args).sendToTarget();
665 } finally {
666 Log.endSession();
667 }
Tyler Gunndee56a82016-03-23 16:06:34 -0700668 }
Hall Liub64ac4c2017-02-06 10:49:48 -0800669
670 @Override
671 public void startRtt(String callId, ParcelFileDescriptor fromInCall,
672 ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException {
673 Log.startSession(sessionInfo, SESSION_START_RTT);
674 try {
675 SomeArgs args = SomeArgs.obtain();
676 args.arg1 = callId;
677 args.arg2 = new Connection.RttTextStream(toInCall, fromInCall);
678 args.arg3 = Log.createSubsession();
679 mHandler.obtainMessage(MSG_ON_START_RTT, args).sendToTarget();
680 } finally {
681 Log.endSession();
682 }
683 }
684
685 @Override
686 public void stopRtt(String callId, Session.Info sessionInfo) throws RemoteException {
687 Log.startSession(sessionInfo, SESSION_STOP_RTT);
688 try {
689 SomeArgs args = SomeArgs.obtain();
690 args.arg1 = callId;
691 args.arg2 = Log.createSubsession();
692 mHandler.obtainMessage(MSG_ON_STOP_RTT, args).sendToTarget();
693 } finally {
694 Log.endSession();
695 }
696 }
697
698 @Override
699 public void respondToRttUpgradeRequest(String callId, ParcelFileDescriptor fromInCall,
700 ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException {
701 Log.startSession(sessionInfo, SESSION_RTT_UPGRADE_RESPONSE);
702 try {
703 SomeArgs args = SomeArgs.obtain();
704 args.arg1 = callId;
705 if (toInCall == null || fromInCall == null) {
706 args.arg2 = null;
707 } else {
708 args.arg2 = new Connection.RttTextStream(toInCall, fromInCall);
709 }
710 args.arg3 = Log.createSubsession();
711 mHandler.obtainMessage(MSG_RTT_UPGRADE_RESPONSE, args).sendToTarget();
712 } finally {
713 Log.endSession();
714 }
715 }
Pengquan Meng731c1a32017-11-21 18:01:13 -0800716
717 @Override
718 public void connectionServiceFocusLost(Session.Info sessionInfo) throws RemoteException {
719 Log.startSession(sessionInfo, SESSION_CONNECTION_SERVICE_FOCUS_LOST);
720 try {
721 mHandler.obtainMessage(MSG_CONNECTION_SERVICE_FOCUS_LOST).sendToTarget();
722 } finally {
723 Log.endSession();
724 }
725 }
726
727 @Override
728 public void connectionServiceFocusGained(Session.Info sessionInfo) throws RemoteException {
729 Log.startSession(sessionInfo, SESSION_CONNECTION_SERVICE_FOCUS_GAINED);
730 try {
731 mHandler.obtainMessage(MSG_CONNECTION_SERVICE_FOCUS_GAINED).sendToTarget();
732 } finally {
733 Log.endSession();
734 }
735 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700736 };
737
738 private final Handler mHandler = new Handler(Looper.getMainLooper()) {
739 @Override
740 public void handleMessage(Message msg) {
741 switch (msg.what) {
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700742 case MSG_ADD_CONNECTION_SERVICE_ADAPTER: {
743 SomeArgs args = (SomeArgs) msg.obj;
744 try {
745 IConnectionServiceAdapter adapter = (IConnectionServiceAdapter) args.arg1;
746 Log.continueSession((Session) args.arg2,
747 SESSION_HANDLER + SESSION_ADD_CS_ADAPTER);
748 mAdapter.addAdapter(adapter);
749 onAdapterAttached();
750 } finally {
751 args.recycle();
752 Log.endSession();
753 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700754 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700755 }
756 case MSG_REMOVE_CONNECTION_SERVICE_ADAPTER: {
757 SomeArgs args = (SomeArgs) msg.obj;
758 try {
759 Log.continueSession((Session) args.arg2,
760 SESSION_HANDLER + SESSION_REMOVE_CS_ADAPTER);
761 mAdapter.removeAdapter((IConnectionServiceAdapter) args.arg1);
762 } finally {
763 args.recycle();
764 Log.endSession();
765 }
Ihab Awad8aecfed2014-08-08 17:06:11 -0700766 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700767 }
Ihab Awadf8b69882014-07-25 15:14:01 -0700768 case MSG_CREATE_CONNECTION: {
769 SomeArgs args = (SomeArgs) msg.obj;
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700770 Log.continueSession((Session) args.arg4, SESSION_HANDLER + SESSION_CREATE_CONN);
Ihab Awadf8b69882014-07-25 15:14:01 -0700771 try {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700772 final PhoneAccountHandle connectionManagerPhoneAccount =
Ihab Awadf8b69882014-07-25 15:14:01 -0700773 (PhoneAccountHandle) args.arg1;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700774 final String id = (String) args.arg2;
775 final ConnectionRequest request = (ConnectionRequest) args.arg3;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700776 final boolean isIncoming = args.argi1 == 1;
Yorke Leec3cf9822014-10-02 09:38:39 -0700777 final boolean isUnknown = args.argi2 == 1;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700778 if (!mAreAccountsInitialized) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700779 Log.d(this, "Enqueueing pre-init request %s", id);
Brad Ebinger0c3541b2016-11-01 14:11:38 -0700780 mPreInitializationConnectionRequests.add(
781 new android.telecom.Logging.Runnable(
782 SESSION_HANDLER + SESSION_CREATE_CONN + ".pICR",
783 null /*lock*/) {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700784 @Override
Brad Ebinger0c3541b2016-11-01 14:11:38 -0700785 public void loggedRun() {
Ihab Awad5d0410f2014-07-30 10:07:40 -0700786 createConnection(
787 connectionManagerPhoneAccount,
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700788 id,
Ihab Awad5d0410f2014-07-30 10:07:40 -0700789 request,
Yorke Leec3cf9822014-10-02 09:38:39 -0700790 isIncoming,
791 isUnknown);
Ihab Awad5d0410f2014-07-30 10:07:40 -0700792 }
Brad Ebinger0c3541b2016-11-01 14:11:38 -0700793 }.prepare());
Ihab Awad5d0410f2014-07-30 10:07:40 -0700794 } else {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700795 createConnection(
796 connectionManagerPhoneAccount,
797 id,
798 request,
Yorke Leec3cf9822014-10-02 09:38:39 -0700799 isIncoming,
800 isUnknown);
Ihab Awad5d0410f2014-07-30 10:07:40 -0700801 }
Ihab Awadf8b69882014-07-25 15:14:01 -0700802 } finally {
803 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700804 Log.endSession();
Ihab Awadf8b69882014-07-25 15:14:01 -0700805 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700806 break;
Ihab Awadf8b69882014-07-25 15:14:01 -0700807 }
Tyler Gunn041a1fe2017-05-12 10:04:49 -0700808 case MSG_CREATE_CONNECTION_COMPLETE: {
809 SomeArgs args = (SomeArgs) msg.obj;
810 Log.continueSession((Session) args.arg2,
811 SESSION_HANDLER + SESSION_CREATE_CONN_COMPLETE);
812 try {
813 final String id = (String) args.arg1;
814 if (!mAreAccountsInitialized) {
815 Log.d(this, "Enqueueing pre-init request %s", id);
816 mPreInitializationConnectionRequests.add(
817 new android.telecom.Logging.Runnable(
818 SESSION_HANDLER + SESSION_CREATE_CONN_COMPLETE
819 + ".pICR",
820 null /*lock*/) {
821 @Override
822 public void loggedRun() {
823 notifyCreateConnectionComplete(id);
824 }
825 }.prepare());
826 } else {
827 notifyCreateConnectionComplete(id);
828 }
829 } finally {
830 args.recycle();
831 Log.endSession();
832 }
833 break;
834 }
Tyler Gunn44e01912017-01-31 10:49:05 -0800835 case MSG_CREATE_CONNECTION_FAILED: {
836 SomeArgs args = (SomeArgs) msg.obj;
837 Log.continueSession((Session) args.arg3, SESSION_HANDLER +
838 SESSION_CREATE_CONN_FAILED);
839 try {
840 final String id = (String) args.arg1;
841 final ConnectionRequest request = (ConnectionRequest) args.arg2;
842 final boolean isIncoming = args.argi1 == 1;
Tyler Gunn159f35c2017-03-02 09:28:37 -0800843 final PhoneAccountHandle connectionMgrPhoneAccount =
844 (PhoneAccountHandle) args.arg4;
Tyler Gunn44e01912017-01-31 10:49:05 -0800845 if (!mAreAccountsInitialized) {
846 Log.d(this, "Enqueueing pre-init request %s", id);
847 mPreInitializationConnectionRequests.add(
848 new android.telecom.Logging.Runnable(
849 SESSION_HANDLER + SESSION_CREATE_CONN_FAILED + ".pICR",
850 null /*lock*/) {
851 @Override
852 public void loggedRun() {
Tyler Gunn159f35c2017-03-02 09:28:37 -0800853 createConnectionFailed(connectionMgrPhoneAccount, id,
854 request, isIncoming);
Tyler Gunn44e01912017-01-31 10:49:05 -0800855 }
856 }.prepare());
857 } else {
858 Log.i(this, "createConnectionFailed %s", id);
Tyler Gunn159f35c2017-03-02 09:28:37 -0800859 createConnectionFailed(connectionMgrPhoneAccount, id, request,
860 isIncoming);
Tyler Gunn44e01912017-01-31 10:49:05 -0800861 }
862 } finally {
863 args.recycle();
864 Log.endSession();
865 }
866 break;
867 }
Ravi Paluri80aa2142019-12-02 11:57:37 +0530868 case MSG_CREATE_CONFERENCE: {
869 SomeArgs args = (SomeArgs) msg.obj;
870 Log.continueSession((Session) args.arg4, SESSION_HANDLER + SESSION_CREATE_CONN);
871 try {
872 final PhoneAccountHandle connectionManagerPhoneAccount =
873 (PhoneAccountHandle) args.arg1;
874 final String id = (String) args.arg2;
875 final ConnectionRequest request = (ConnectionRequest) args.arg3;
876 final boolean isIncoming = args.argi1 == 1;
877 final boolean isUnknown = args.argi2 == 1;
878 if (!mAreAccountsInitialized) {
879 Log.d(this, "Enqueueing pre-initconference request %s", id);
880 mPreInitializationConnectionRequests.add(
881 new android.telecom.Logging.Runnable(
882 SESSION_HANDLER + SESSION_CREATE_CONF + ".pIConfR",
883 null /*lock*/) {
884 @Override
885 public void loggedRun() {
886 createConference(connectionManagerPhoneAccount,
887 id,
888 request,
889 isIncoming,
890 isUnknown);
891 }
892 }.prepare());
893 } else {
894 createConference(connectionManagerPhoneAccount,
895 id,
896 request,
897 isIncoming,
898 isUnknown);
899 }
900 } finally {
901 args.recycle();
902 Log.endSession();
903 }
904 break;
905 }
906 case MSG_CREATE_CONFERENCE_COMPLETE: {
907 SomeArgs args = (SomeArgs) msg.obj;
908 Log.continueSession((Session) args.arg2,
909 SESSION_HANDLER + SESSION_CREATE_CONN_COMPLETE);
910 try {
911 final String id = (String) args.arg1;
912 if (!mAreAccountsInitialized) {
913 Log.d(this, "Enqueueing pre-init conference request %s", id);
914 mPreInitializationConnectionRequests.add(
915 new android.telecom.Logging.Runnable(
916 SESSION_HANDLER + SESSION_CREATE_CONF_COMPLETE
917 + ".pIConfR",
918 null /*lock*/) {
919 @Override
920 public void loggedRun() {
921 notifyCreateConferenceComplete(id);
922 }
923 }.prepare());
924 } else {
925 notifyCreateConferenceComplete(id);
926 }
927 } finally {
928 args.recycle();
929 Log.endSession();
930 }
931 break;
932 }
933 case MSG_CREATE_CONFERENCE_FAILED: {
934 SomeArgs args = (SomeArgs) msg.obj;
935 Log.continueSession((Session) args.arg3, SESSION_HANDLER +
936 SESSION_CREATE_CONN_FAILED);
937 try {
938 final String id = (String) args.arg1;
939 final ConnectionRequest request = (ConnectionRequest) args.arg2;
940 final boolean isIncoming = args.argi1 == 1;
941 final PhoneAccountHandle connectionMgrPhoneAccount =
942 (PhoneAccountHandle) args.arg4;
943 if (!mAreAccountsInitialized) {
944 Log.d(this, "Enqueueing pre-init conference request %s", id);
945 mPreInitializationConnectionRequests.add(
946 new android.telecom.Logging.Runnable(
947 SESSION_HANDLER + SESSION_CREATE_CONF_FAILED
948 + ".pIConfR",
949 null /*lock*/) {
950 @Override
951 public void loggedRun() {
952 createConferenceFailed(connectionMgrPhoneAccount, id,
953 request, isIncoming);
954 }
955 }.prepare());
956 } else {
957 Log.i(this, "createConferenceFailed %s", id);
958 createConferenceFailed(connectionMgrPhoneAccount, id, request,
959 isIncoming);
960 }
961 } finally {
962 args.recycle();
963 Log.endSession();
964 }
965 break;
966 }
967
Sanket Padawe4cc8ed52017-12-04 16:22:20 -0800968 case MSG_HANDOVER_FAILED: {
969 SomeArgs args = (SomeArgs) msg.obj;
970 Log.continueSession((Session) args.arg3, SESSION_HANDLER +
971 SESSION_HANDOVER_FAILED);
972 try {
973 final String id = (String) args.arg1;
974 final ConnectionRequest request = (ConnectionRequest) args.arg2;
975 final int reason = (int) args.arg4;
976 if (!mAreAccountsInitialized) {
977 Log.d(this, "Enqueueing pre-init request %s", id);
978 mPreInitializationConnectionRequests.add(
979 new android.telecom.Logging.Runnable(
980 SESSION_HANDLER
981 + SESSION_HANDOVER_FAILED + ".pICR",
982 null /*lock*/) {
983 @Override
984 public void loggedRun() {
985 handoverFailed(id, request, reason);
986 }
987 }.prepare());
988 } else {
989 Log.i(this, "createConnectionFailed %s", id);
990 handoverFailed(id, request, reason);
991 }
992 } finally {
993 args.recycle();
994 Log.endSession();
995 }
996 break;
997 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700998 case MSG_ABORT: {
999 SomeArgs args = (SomeArgs) msg.obj;
1000 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_ABORT);
1001 try {
1002 abort((String) args.arg1);
1003 } finally {
1004 args.recycle();
1005 Log.endSession();
1006 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001007 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001008 }
1009 case MSG_ANSWER: {
1010 SomeArgs args = (SomeArgs) msg.obj;
1011 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_ANSWER);
1012 try {
1013 answer((String) args.arg1);
1014 } finally {
1015 args.recycle();
1016 Log.endSession();
1017 }
Tyler Gunnbe74de02014-08-29 14:51:48 -07001018 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001019 }
Tyler Gunnbe74de02014-08-29 14:51:48 -07001020 case MSG_ANSWER_VIDEO: {
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001021 SomeArgs args = (SomeArgs) msg.obj;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001022 Log.continueSession((Session) args.arg2,
1023 SESSION_HANDLER + SESSION_ANSWER_VIDEO);
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001024 try {
1025 String callId = (String) args.arg1;
Evan Charltonbf11f982014-07-20 22:06:28 -07001026 int videoState = args.argi1;
Tyler Gunnbe74de02014-08-29 14:51:48 -07001027 answerVideo(callId, videoState);
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001028 } finally {
1029 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001030 Log.endSession();
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001031 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001032 break;
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001033 }
Pooja Jaind34698d2017-12-28 14:15:31 +05301034 case MSG_DEFLECT: {
1035 SomeArgs args = (SomeArgs) msg.obj;
1036 Log.continueSession((Session) args.arg3, SESSION_HANDLER + SESSION_DEFLECT);
1037 try {
1038 deflect((String) args.arg1, (Uri) args.arg2);
1039 } finally {
1040 args.recycle();
1041 Log.endSession();
1042 }
1043 break;
1044 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001045 case MSG_REJECT: {
1046 SomeArgs args = (SomeArgs) msg.obj;
1047 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_REJECT);
1048 try {
1049 reject((String) args.arg1);
1050 } finally {
1051 args.recycle();
1052 Log.endSession();
1053 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001054 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001055 }
Bryce Lee81901682015-08-28 16:38:02 -07001056 case MSG_REJECT_WITH_MESSAGE: {
1057 SomeArgs args = (SomeArgs) msg.obj;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001058 Log.continueSession((Session) args.arg3,
1059 SESSION_HANDLER + SESSION_REJECT_MESSAGE);
Bryce Lee81901682015-08-28 16:38:02 -07001060 try {
1061 reject((String) args.arg1, (String) args.arg2);
1062 } finally {
1063 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001064 Log.endSession();
Bryce Lee81901682015-08-28 16:38:02 -07001065 }
1066 break;
1067 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001068 case MSG_DISCONNECT: {
1069 SomeArgs args = (SomeArgs) msg.obj;
1070 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_DISCONNECT);
1071 try {
1072 disconnect((String) args.arg1);
1073 } finally {
1074 args.recycle();
1075 Log.endSession();
1076 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001077 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001078 }
1079 case MSG_SILENCE: {
1080 SomeArgs args = (SomeArgs) msg.obj;
1081 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_SILENCE);
1082 try {
1083 silence((String) args.arg1);
1084 } finally {
1085 args.recycle();
1086 Log.endSession();
1087 }
Bryce Leecac50772015-11-17 15:13:29 -08001088 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001089 }
1090 case MSG_HOLD: {
1091 SomeArgs args = (SomeArgs) msg.obj;
1092 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_REJECT);
1093 try {
1094 hold((String) args.arg1);
1095 } finally {
1096 args.recycle();
1097 Log.endSession();
1098 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001099 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001100 }
1101 case MSG_UNHOLD: {
1102 SomeArgs args = (SomeArgs) msg.obj;
1103 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_UNHOLD);
1104 try {
1105 unhold((String) args.arg1);
1106 } finally {
1107 args.recycle();
1108 Log.endSession();
1109 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001110 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001111 }
Yorke Lee4af59352015-05-13 14:14:54 -07001112 case MSG_ON_CALL_AUDIO_STATE_CHANGED: {
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001113 SomeArgs args = (SomeArgs) msg.obj;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001114 Log.continueSession((Session) args.arg3,
1115 SESSION_HANDLER + SESSION_CALL_AUDIO_SC);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001116 try {
1117 String callId = (String) args.arg1;
Yorke Lee4af59352015-05-13 14:14:54 -07001118 CallAudioState audioState = (CallAudioState) args.arg2;
1119 onCallAudioStateChanged(callId, new CallAudioState(audioState));
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001120 } finally {
1121 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001122 Log.endSession();
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001123 }
1124 break;
1125 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001126 case MSG_PLAY_DTMF_TONE: {
1127 SomeArgs args = (SomeArgs) msg.obj;
1128 try {
1129 Log.continueSession((Session) args.arg3,
1130 SESSION_HANDLER + SESSION_PLAY_DTMF);
1131 playDtmfTone((String) args.arg2, (char) args.arg1);
1132 } finally {
1133 args.recycle();
1134 Log.endSession();
1135 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001136 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001137 }
1138 case MSG_STOP_DTMF_TONE: {
1139 SomeArgs args = (SomeArgs) msg.obj;
1140 try {
1141 Log.continueSession((Session) args.arg2,
1142 SESSION_HANDLER + SESSION_STOP_DTMF);
1143 stopDtmfTone((String) args.arg1);
1144 } finally {
1145 args.recycle();
1146 Log.endSession();
1147 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001148 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001149 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001150 case MSG_CONFERENCE: {
1151 SomeArgs args = (SomeArgs) msg.obj;
1152 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001153 Log.continueSession((Session) args.arg3,
1154 SESSION_HANDLER + SESSION_CONFERENCE);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001155 String callId1 = (String) args.arg1;
1156 String callId2 = (String) args.arg2;
1157 conference(callId1, callId2);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001158 } finally {
1159 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001160 Log.endSession();
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001161 }
1162 break;
1163 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001164 case MSG_SPLIT_FROM_CONFERENCE: {
1165 SomeArgs args = (SomeArgs) msg.obj;
1166 try {
1167 Log.continueSession((Session) args.arg2,
1168 SESSION_HANDLER + SESSION_SPLIT_CONFERENCE);
1169 splitFromConference((String) args.arg1);
1170 } finally {
1171 args.recycle();
1172 Log.endSession();
1173 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001174 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001175 }
1176 case MSG_MERGE_CONFERENCE: {
1177 SomeArgs args = (SomeArgs) msg.obj;
1178 try {
1179 Log.continueSession((Session) args.arg2,
1180 SESSION_HANDLER + SESSION_MERGE_CONFERENCE);
1181 mergeConference((String) args.arg1);
1182 } finally {
1183 args.recycle();
1184 Log.endSession();
1185 }
Santos Cordona4868042014-09-04 17:39:22 -07001186 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001187 }
1188 case MSG_SWAP_CONFERENCE: {
1189 SomeArgs args = (SomeArgs) msg.obj;
1190 try {
1191 Log.continueSession((Session) args.arg2,
1192 SESSION_HANDLER + SESSION_SWAP_CONFERENCE);
1193 swapConference((String) args.arg1);
1194 } finally {
1195 args.recycle();
1196 Log.endSession();
1197 }
Santos Cordona4868042014-09-04 17:39:22 -07001198 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001199 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001200 case MSG_ON_POST_DIAL_CONTINUE: {
1201 SomeArgs args = (SomeArgs) msg.obj;
1202 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001203 Log.continueSession((Session) args.arg2,
1204 SESSION_HANDLER + SESSION_POST_DIAL_CONT);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001205 String callId = (String) args.arg1;
1206 boolean proceed = (args.argi1 == 1);
1207 onPostDialContinue(callId, proceed);
1208 } finally {
1209 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001210 Log.endSession();
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001211 }
1212 break;
1213 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001214 case MSG_PULL_EXTERNAL_CALL: {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001215 SomeArgs args = (SomeArgs) msg.obj;
1216 try {
1217 Log.continueSession((Session) args.arg2,
1218 SESSION_HANDLER + SESSION_PULL_EXTERNAL_CALL);
1219 pullExternalCall((String) args.arg1);
1220 } finally {
1221 args.recycle();
1222 Log.endSession();
1223 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001224 break;
1225 }
1226 case MSG_SEND_CALL_EVENT: {
1227 SomeArgs args = (SomeArgs) msg.obj;
1228 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001229 Log.continueSession((Session) args.arg4,
1230 SESSION_HANDLER + SESSION_SEND_CALL_EVENT);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001231 String callId = (String) args.arg1;
1232 String event = (String) args.arg2;
1233 Bundle extras = (Bundle) args.arg3;
1234 sendCallEvent(callId, event, extras);
1235 } finally {
1236 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001237 Log.endSession();
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001238 }
1239 break;
1240 }
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08001241 case MSG_HANDOVER_COMPLETE: {
1242 SomeArgs args = (SomeArgs) msg.obj;
1243 try {
1244 Log.continueSession((Session) args.arg2,
1245 SESSION_HANDLER + SESSION_HANDOVER_COMPLETE);
1246 String callId = (String) args.arg1;
1247 notifyHandoverComplete(callId);
1248 } finally {
1249 args.recycle();
1250 Log.endSession();
1251 }
1252 break;
1253 }
Tyler Gunndee56a82016-03-23 16:06:34 -07001254 case MSG_ON_EXTRAS_CHANGED: {
1255 SomeArgs args = (SomeArgs) msg.obj;
1256 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001257 Log.continueSession((Session) args.arg3,
1258 SESSION_HANDLER + SESSION_EXTRAS_CHANGED);
Tyler Gunndee56a82016-03-23 16:06:34 -07001259 String callId = (String) args.arg1;
1260 Bundle extras = (Bundle) args.arg2;
1261 handleExtrasChanged(callId, extras);
1262 } finally {
1263 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001264 Log.endSession();
Tyler Gunndee56a82016-03-23 16:06:34 -07001265 }
1266 break;
1267 }
Hall Liub64ac4c2017-02-06 10:49:48 -08001268 case MSG_ON_START_RTT: {
1269 SomeArgs args = (SomeArgs) msg.obj;
1270 try {
1271 Log.continueSession((Session) args.arg3,
1272 SESSION_HANDLER + SESSION_START_RTT);
1273 String callId = (String) args.arg1;
1274 Connection.RttTextStream rttTextStream =
1275 (Connection.RttTextStream) args.arg2;
1276 startRtt(callId, rttTextStream);
1277 } finally {
1278 args.recycle();
1279 Log.endSession();
1280 }
1281 break;
1282 }
1283 case MSG_ON_STOP_RTT: {
1284 SomeArgs args = (SomeArgs) msg.obj;
1285 try {
1286 Log.continueSession((Session) args.arg2,
1287 SESSION_HANDLER + SESSION_STOP_RTT);
1288 String callId = (String) args.arg1;
1289 stopRtt(callId);
1290 } finally {
1291 args.recycle();
1292 Log.endSession();
1293 }
1294 break;
1295 }
1296 case MSG_RTT_UPGRADE_RESPONSE: {
1297 SomeArgs args = (SomeArgs) msg.obj;
1298 try {
1299 Log.continueSession((Session) args.arg3,
1300 SESSION_HANDLER + SESSION_RTT_UPGRADE_RESPONSE);
1301 String callId = (String) args.arg1;
1302 Connection.RttTextStream rttTextStream =
1303 (Connection.RttTextStream) args.arg2;
1304 handleRttUpgradeResponse(callId, rttTextStream);
1305 } finally {
1306 args.recycle();
1307 Log.endSession();
1308 }
1309 break;
1310 }
Pengquan Meng731c1a32017-11-21 18:01:13 -08001311 case MSG_CONNECTION_SERVICE_FOCUS_GAINED:
1312 onConnectionServiceFocusGained();
1313 break;
1314 case MSG_CONNECTION_SERVICE_FOCUS_LOST:
1315 onConnectionServiceFocusLost();
1316 break;
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001317 default:
1318 break;
1319 }
1320 }
1321 };
1322
Santos Cordon823fd3c2014-08-07 18:35:18 -07001323 private final Conference.Listener mConferenceListener = new Conference.Listener() {
1324 @Override
1325 public void onStateChanged(Conference conference, int oldState, int newState) {
1326 String id = mIdByConference.get(conference);
1327 switch (newState) {
Ravi Paluri80aa2142019-12-02 11:57:37 +05301328 case Connection.STATE_RINGING:
1329 mAdapter.setRinging(id);
1330 break;
1331 case Connection.STATE_DIALING:
1332 mAdapter.setDialing(id);
1333 break;
Santos Cordon823fd3c2014-08-07 18:35:18 -07001334 case Connection.STATE_ACTIVE:
1335 mAdapter.setActive(id);
1336 break;
1337 case Connection.STATE_HOLDING:
1338 mAdapter.setOnHold(id);
1339 break;
1340 case Connection.STATE_DISCONNECTED:
1341 // handled by onDisconnected
1342 break;
1343 }
1344 }
1345
1346 @Override
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001347 public void onDisconnected(Conference conference, DisconnectCause disconnectCause) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001348 String id = mIdByConference.get(conference);
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001349 mAdapter.setDisconnected(id, disconnectCause);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001350 }
1351
1352 @Override
1353 public void onConnectionAdded(Conference conference, Connection connection) {
1354 }
1355
1356 @Override
1357 public void onConnectionRemoved(Conference conference, Connection connection) {
1358 }
1359
1360 @Override
Ihab Awad50e35062014-09-30 09:17:03 -07001361 public void onConferenceableConnectionsChanged(
1362 Conference conference, List<Connection> conferenceableConnections) {
1363 mAdapter.setConferenceableConnections(
1364 mIdByConference.get(conference),
1365 createConnectionIdList(conferenceableConnections));
1366 }
1367
1368 @Override
Santos Cordon823fd3c2014-08-07 18:35:18 -07001369 public void onDestroyed(Conference conference) {
1370 removeConference(conference);
1371 }
1372
1373 @Override
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001374 public void onConnectionCapabilitiesChanged(
1375 Conference conference,
1376 int connectionCapabilities) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001377 String id = mIdByConference.get(conference);
1378 Log.d(this, "call capabilities: conference: %s",
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001379 Connection.capabilitiesToString(connectionCapabilities));
1380 mAdapter.setConnectionCapabilities(id, connectionCapabilities);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001381 }
Rekha Kumar07366812015-03-24 16:42:31 -07001382
1383 @Override
Tyler Gunn720c6642016-03-22 09:02:47 -07001384 public void onConnectionPropertiesChanged(
1385 Conference conference,
1386 int connectionProperties) {
1387 String id = mIdByConference.get(conference);
1388 Log.d(this, "call capabilities: conference: %s",
1389 Connection.propertiesToString(connectionProperties));
1390 mAdapter.setConnectionProperties(id, connectionProperties);
1391 }
1392
1393 @Override
Rekha Kumar07366812015-03-24 16:42:31 -07001394 public void onVideoStateChanged(Conference c, int videoState) {
1395 String id = mIdByConference.get(c);
1396 Log.d(this, "onVideoStateChanged set video state %d", videoState);
1397 mAdapter.setVideoState(id, videoState);
1398 }
1399
1400 @Override
1401 public void onVideoProviderChanged(Conference c, Connection.VideoProvider videoProvider) {
1402 String id = mIdByConference.get(c);
1403 Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c,
1404 videoProvider);
1405 mAdapter.setVideoProvider(id, videoProvider);
1406 }
Andrew Lee0f51da32015-04-16 13:11:55 -07001407
1408 @Override
Andrew Leeedc625f2015-04-14 13:38:12 -07001409 public void onStatusHintsChanged(Conference conference, StatusHints statusHints) {
1410 String id = mIdByConference.get(conference);
Tyler Gunndee56a82016-03-23 16:06:34 -07001411 if (id != null) {
1412 mAdapter.setStatusHints(id, statusHints);
1413 }
Andrew Leeedc625f2015-04-14 13:38:12 -07001414 }
Santos Cordon6b7f9552015-05-27 17:21:45 -07001415
1416 @Override
Tyler Gunndee56a82016-03-23 16:06:34 -07001417 public void onExtrasChanged(Conference c, Bundle extras) {
1418 String id = mIdByConference.get(c);
1419 if (id != null) {
1420 mAdapter.putExtras(id, extras);
1421 }
1422 }
1423
1424 @Override
1425 public void onExtrasRemoved(Conference c, List<String> keys) {
1426 String id = mIdByConference.get(c);
1427 if (id != null) {
1428 mAdapter.removeExtras(id, keys);
1429 }
Santos Cordon6b7f9552015-05-27 17:21:45 -07001430 }
Tyler Gunn68a73a42018-10-03 15:38:57 -07001431
1432 @Override
1433 public void onConferenceStateChanged(Conference c, boolean isConference) {
1434 String id = mIdByConference.get(c);
1435 if (id != null) {
1436 mAdapter.setConferenceState(id, isConference);
1437 }
1438 }
1439
1440 @Override
1441 public void onAddressChanged(Conference c, Uri newAddress, int presentation) {
1442 String id = mIdByConference.get(c);
1443 if (id != null) {
1444 mAdapter.setAddress(id, newAddress, presentation);
1445 }
1446 }
1447
1448 @Override
1449 public void onCallerDisplayNameChanged(Conference c, String callerDisplayName,
1450 int presentation) {
1451 String id = mIdByConference.get(c);
1452 if (id != null) {
1453 mAdapter.setCallerDisplayName(id, callerDisplayName, presentation);
1454 }
1455 }
Hall Liuc9bc1c62019-04-16 14:00:55 -07001456
1457 @Override
1458 public void onConnectionEvent(Conference c, String event, Bundle extras) {
1459 String id = mIdByConference.get(c);
1460 if (id != null) {
1461 mAdapter.onConnectionEvent(id, event, extras);
1462 }
1463 }
Ravi Paluri80aa2142019-12-02 11:57:37 +05301464
1465 @Override
1466 public void onRingbackRequested(Conference c, boolean ringback) {
1467 String id = mIdByConference.get(c);
1468 Log.d(this, "Adapter conference onRingback %b", ringback);
1469 mAdapter.setRingbackRequested(id, ringback);
1470 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07001471 };
1472
Ihab Awad542e0ea2014-05-16 10:22:16 -07001473 private final Connection.Listener mConnectionListener = new Connection.Listener() {
1474 @Override
1475 public void onStateChanged(Connection c, int state) {
1476 String id = mIdByConnection.get(c);
Ihab Awad42b30e12014-05-22 09:49:34 -07001477 Log.d(this, "Adapter set state %s %s", id, Connection.stateToString(state));
Ihab Awad542e0ea2014-05-16 10:22:16 -07001478 switch (state) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001479 case Connection.STATE_ACTIVE:
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001480 mAdapter.setActive(id);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001481 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001482 case Connection.STATE_DIALING:
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001483 mAdapter.setDialing(id);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001484 break;
Tyler Gunnc96b5e02016-07-07 22:53:57 -07001485 case Connection.STATE_PULLING_CALL:
1486 mAdapter.setPulling(id);
1487 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001488 case Connection.STATE_DISCONNECTED:
Ihab Awad542e0ea2014-05-16 10:22:16 -07001489 // Handled in onDisconnected()
1490 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001491 case Connection.STATE_HOLDING:
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001492 mAdapter.setOnHold(id);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001493 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001494 case Connection.STATE_NEW:
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001495 // Nothing to tell Telecom
Ihab Awad542e0ea2014-05-16 10:22:16 -07001496 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001497 case Connection.STATE_RINGING:
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001498 mAdapter.setRinging(id);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001499 break;
1500 }
1501 }
1502
1503 @Override
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001504 public void onDisconnected(Connection c, DisconnectCause disconnectCause) {
Ihab Awad542e0ea2014-05-16 10:22:16 -07001505 String id = mIdByConnection.get(c);
Andrew Lee26786392014-09-16 18:14:59 -07001506 Log.d(this, "Adapter set disconnected %s", disconnectCause);
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001507 mAdapter.setDisconnected(id, disconnectCause);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001508 }
1509
1510 @Override
Tyler Gunnaa07df82014-07-17 07:50:22 -07001511 public void onVideoStateChanged(Connection c, int videoState) {
1512 String id = mIdByConnection.get(c);
1513 Log.d(this, "Adapter set video state %d", videoState);
1514 mAdapter.setVideoState(id, videoState);
1515 }
1516
1517 @Override
Andrew Lee100e2932014-09-08 15:34:24 -07001518 public void onAddressChanged(Connection c, Uri address, int presentation) {
Sailesh Nepal61203862014-07-11 14:50:13 -07001519 String id = mIdByConnection.get(c);
Andrew Lee100e2932014-09-08 15:34:24 -07001520 mAdapter.setAddress(id, address, presentation);
Sailesh Nepal61203862014-07-11 14:50:13 -07001521 }
1522
1523 @Override
1524 public void onCallerDisplayNameChanged(
1525 Connection c, String callerDisplayName, int presentation) {
1526 String id = mIdByConnection.get(c);
1527 mAdapter.setCallerDisplayName(id, callerDisplayName, presentation);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001528 }
1529
1530 @Override
Ihab Awad542e0ea2014-05-16 10:22:16 -07001531 public void onDestroyed(Connection c) {
1532 removeConnection(c);
1533 }
Ihab Awadf8358972014-05-28 16:46:42 -07001534
1535 @Override
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001536 public void onPostDialWait(Connection c, String remaining) {
Sailesh Nepal091768c2014-06-30 15:15:23 -07001537 String id = mIdByConnection.get(c);
1538 Log.d(this, "Adapter onPostDialWait %s, %s", c, remaining);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001539 mAdapter.onPostDialWait(id, remaining);
Sailesh Nepal091768c2014-06-30 15:15:23 -07001540 }
1541
1542 @Override
Nancy Chen27d1c2d2014-12-15 16:12:50 -08001543 public void onPostDialChar(Connection c, char nextChar) {
1544 String id = mIdByConnection.get(c);
1545 Log.d(this, "Adapter onPostDialChar %s, %s", c, nextChar);
1546 mAdapter.onPostDialChar(id, nextChar);
1547 }
1548
1549 @Override
Andrew Lee100e2932014-09-08 15:34:24 -07001550 public void onRingbackRequested(Connection c, boolean ringback) {
Ihab Awadf8358972014-05-28 16:46:42 -07001551 String id = mIdByConnection.get(c);
1552 Log.d(this, "Adapter onRingback %b", ringback);
Andrew Lee100e2932014-09-08 15:34:24 -07001553 mAdapter.setRingbackRequested(id, ringback);
Ihab Awadf8358972014-05-28 16:46:42 -07001554 }
Santos Cordonb6939982014-06-04 20:20:58 -07001555
1556 @Override
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001557 public void onConnectionCapabilitiesChanged(Connection c, int capabilities) {
Santos Cordonb6939982014-06-04 20:20:58 -07001558 String id = mIdByConnection.get(c);
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001559 Log.d(this, "capabilities: parcelableconnection: %s",
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001560 Connection.capabilitiesToString(capabilities));
1561 mAdapter.setConnectionCapabilities(id, capabilities);
Santos Cordonb6939982014-06-04 20:20:58 -07001562 }
1563
Santos Cordonb6939982014-06-04 20:20:58 -07001564 @Override
Tyler Gunn720c6642016-03-22 09:02:47 -07001565 public void onConnectionPropertiesChanged(Connection c, int properties) {
1566 String id = mIdByConnection.get(c);
1567 Log.d(this, "properties: parcelableconnection: %s",
1568 Connection.propertiesToString(properties));
1569 mAdapter.setConnectionProperties(id, properties);
1570 }
1571
1572 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001573 public void onVideoProviderChanged(Connection c, Connection.VideoProvider videoProvider) {
Andrew Lee5ffbe8b82014-06-20 16:29:33 -07001574 String id = mIdByConnection.get(c);
Rekha Kumar07366812015-03-24 16:42:31 -07001575 Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c,
1576 videoProvider);
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001577 mAdapter.setVideoProvider(id, videoProvider);
Andrew Lee5ffbe8b82014-06-20 16:29:33 -07001578 }
Sailesh Nepal33aaae42014-07-07 22:49:44 -07001579
1580 @Override
Sailesh Nepal001bbbb2014-07-15 14:40:39 -07001581 public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {
Sailesh Nepal33aaae42014-07-07 22:49:44 -07001582 String id = mIdByConnection.get(c);
Andrew Lee100e2932014-09-08 15:34:24 -07001583 mAdapter.setIsVoipAudioMode(id, isVoip);
Sailesh Nepal33aaae42014-07-07 22:49:44 -07001584 }
Sailesh Nepale7ef59a2014-07-08 21:48:22 -07001585
1586 @Override
Sailesh Nepal001bbbb2014-07-15 14:40:39 -07001587 public void onStatusHintsChanged(Connection c, StatusHints statusHints) {
Sailesh Nepale7ef59a2014-07-08 21:48:22 -07001588 String id = mIdByConnection.get(c);
1589 mAdapter.setStatusHints(id, statusHints);
1590 }
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07001591
1592 @Override
Tyler Gunn6d76ca02014-11-17 15:49:51 -08001593 public void onConferenceablesChanged(
Tyler Gunndf2cbc82015-04-20 09:13:01 -07001594 Connection connection, List<Conferenceable> conferenceables) {
Ihab Awadb8e85c72014-08-23 20:34:57 -07001595 mAdapter.setConferenceableConnections(
1596 mIdByConnection.get(connection),
Tyler Gunn6d76ca02014-11-17 15:49:51 -08001597 createIdList(conferenceables));
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001598 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07001599
1600 @Override
1601 public void onConferenceChanged(Connection connection, Conference conference) {
1602 String id = mIdByConnection.get(connection);
1603 if (id != null) {
1604 String conferenceId = null;
1605 if (conference != null) {
1606 conferenceId = mIdByConference.get(conference);
1607 }
1608 mAdapter.setIsConferenced(id, conferenceId);
1609 }
1610 }
Anthony Lee17455a32015-04-24 15:25:29 -07001611
1612 @Override
1613 public void onConferenceMergeFailed(Connection connection) {
1614 String id = mIdByConnection.get(connection);
1615 if (id != null) {
1616 mAdapter.onConferenceMergeFailed(id);
1617 }
1618 }
Santos Cordon6b7f9552015-05-27 17:21:45 -07001619
1620 @Override
Tyler Gunndee56a82016-03-23 16:06:34 -07001621 public void onExtrasChanged(Connection c, Bundle extras) {
1622 String id = mIdByConnection.get(c);
Santos Cordon6b7f9552015-05-27 17:21:45 -07001623 if (id != null) {
Tyler Gunndee56a82016-03-23 16:06:34 -07001624 mAdapter.putExtras(id, extras);
Santos Cordon6b7f9552015-05-27 17:21:45 -07001625 }
1626 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001627
Tyler Gunnf5035432017-01-09 09:43:12 -08001628 @Override
Tyler Gunndee56a82016-03-23 16:06:34 -07001629 public void onExtrasRemoved(Connection c, List<String> keys) {
1630 String id = mIdByConnection.get(c);
1631 if (id != null) {
1632 mAdapter.removeExtras(id, keys);
1633 }
1634 }
1635
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -08001636 @Override
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001637 public void onConnectionEvent(Connection connection, String event, Bundle extras) {
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -08001638 String id = mIdByConnection.get(connection);
1639 if (id != null) {
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001640 mAdapter.onConnectionEvent(id, event, extras);
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -08001641 }
1642 }
Tyler Gunnf5035432017-01-09 09:43:12 -08001643
1644 @Override
Hall Liua98f58b52017-11-07 17:59:28 -08001645 public void onAudioRouteChanged(Connection c, int audioRoute, String bluetoothAddress) {
Tyler Gunnf5035432017-01-09 09:43:12 -08001646 String id = mIdByConnection.get(c);
1647 if (id != null) {
Hall Liua98f58b52017-11-07 17:59:28 -08001648 mAdapter.setAudioRoute(id, audioRoute, bluetoothAddress);
Tyler Gunnf5035432017-01-09 09:43:12 -08001649 }
1650 }
Hall Liub64ac4c2017-02-06 10:49:48 -08001651
1652 @Override
1653 public void onRttInitiationSuccess(Connection c) {
1654 String id = mIdByConnection.get(c);
1655 if (id != null) {
1656 mAdapter.onRttInitiationSuccess(id);
1657 }
1658 }
1659
1660 @Override
1661 public void onRttInitiationFailure(Connection c, int reason) {
1662 String id = mIdByConnection.get(c);
1663 if (id != null) {
1664 mAdapter.onRttInitiationFailure(id, reason);
1665 }
1666 }
1667
1668 @Override
1669 public void onRttSessionRemotelyTerminated(Connection c) {
1670 String id = mIdByConnection.get(c);
1671 if (id != null) {
1672 mAdapter.onRttSessionRemotelyTerminated(id);
1673 }
1674 }
1675
1676 @Override
1677 public void onRemoteRttRequest(Connection c) {
1678 String id = mIdByConnection.get(c);
1679 if (id != null) {
1680 mAdapter.onRemoteRttRequest(id);
1681 }
1682 }
Srikanth Chintalafcb15012017-05-04 20:58:34 +05301683
1684 @Override
1685 public void onPhoneAccountChanged(Connection c, PhoneAccountHandle pHandle) {
1686 String id = mIdByConnection.get(c);
1687 if (id != null) {
1688 mAdapter.onPhoneAccountChanged(id, pHandle);
1689 }
1690 }
Mengjun Leng25707742017-07-04 11:10:37 +08001691
1692 public void onConnectionTimeReset(Connection c) {
1693 String id = mIdByConnection.get(c);
1694 if (id != null) {
1695 mAdapter.resetConnectionTime(id);
1696 }
1697 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07001698 };
1699
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001700 /** {@inheritDoc} */
Ihab Awad542e0ea2014-05-16 10:22:16 -07001701 @Override
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001702 public final IBinder onBind(Intent intent) {
1703 return mBinder;
1704 }
1705
Santos Cordon29f2f2e2014-09-11 19:50:24 -07001706 /** {@inheritDoc} */
1707 @Override
1708 public boolean onUnbind(Intent intent) {
1709 endAllConnections();
1710 return super.onUnbind(intent);
1711 }
1712
Ravi Paluri80aa2142019-12-02 11:57:37 +05301713
1714 /**
1715 * This can be used by telecom to either create a new outgoing conference call or attach
1716 * to an existing incoming conference call. In either case, telecom will cycle through a
1717 * set of services and call createConference until a connection service cancels the process
1718 * or completes it successfully.
1719 */
1720 private void createConference(
1721 final PhoneAccountHandle callManagerAccount,
1722 final String callId,
1723 final ConnectionRequest request,
1724 boolean isIncoming,
1725 boolean isUnknown) {
1726
1727 Conference conference = null;
1728 conference = isIncoming ? onCreateIncomingConference(callManagerAccount, request)
1729 : onCreateOutgoingConference(callManagerAccount, request);
1730
1731 Log.d(this, "createConference, conference: %s", conference);
1732 if (conference == null) {
1733 Log.i(this, "createConference, implementation returned null conference.");
1734 conference = Conference.createFailedConference(
1735 new DisconnectCause(DisconnectCause.ERROR, "IMPL_RETURNED_NULL_CONFERENCE"),
1736 request.getAccountHandle());
1737 }
1738 if (conference.getExtras() != null) {
1739 conference.getExtras().putString(Connection.EXTRA_ORIGINAL_CONNECTION_ID, callId);
1740 }
1741 mConferenceById.put(callId, conference);
1742 mIdByConference.put(conference, callId);
1743 conference.addListener(mConferenceListener);
1744 ParcelableConference parcelableConference = new ParcelableConference(
1745 request.getAccountHandle(),
1746 conference.getState(),
1747 conference.getConnectionCapabilities(),
1748 conference.getConnectionProperties(),
1749 Collections.<String>emptyList(), //connectionIds
1750 conference.getVideoProvider() == null ?
1751 null : conference.getVideoProvider().getInterface(),
1752 conference.getVideoState(),
1753 conference.getConnectTimeMillis(),
1754 conference.getConnectionStartElapsedRealTime(),
1755 conference.getStatusHints(),
1756 conference.getExtras(),
1757 conference.getAddress(),
1758 conference.getAddressPresentation(),
1759 conference.getCallerDisplayName(),
1760 conference.getCallerDisplayNamePresentation(),
1761 conference.getDisconnectCause(),
1762 conference.isRingbackRequested());
1763 if (conference.getState() != Connection.STATE_DISCONNECTED) {
1764 conference.setTelecomCallId(callId);
1765 mAdapter.setVideoProvider(callId, conference.getVideoProvider());
1766 mAdapter.setVideoState(callId, conference.getVideoState());
1767 onConferenceAdded(conference);
1768 }
1769
1770 Log.d(this, "createConference, calling handleCreateConferenceSuccessful %s", callId);
1771 mAdapter.handleCreateConferenceComplete(
1772 callId,
1773 request,
1774 parcelableConference);
1775 }
1776
Sailesh Nepalc5b01572014-07-14 16:29:44 -07001777 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001778 * This can be used by telecom to either create a new outgoing call or attach to an existing
1779 * incoming call. In either case, telecom will cycle through a set of services and call
Sailesh Nepalc5b01572014-07-14 16:29:44 -07001780 * createConnection util a connection service cancels the process or completes it successfully.
1781 */
Ihab Awadf8b69882014-07-25 15:14:01 -07001782 private void createConnection(
1783 final PhoneAccountHandle callManagerAccount,
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001784 final String callId,
Ihab Awadf8b69882014-07-25 15:14:01 -07001785 final ConnectionRequest request,
Yorke Leec3cf9822014-10-02 09:38:39 -07001786 boolean isIncoming,
1787 boolean isUnknown) {
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08001788 boolean isLegacyHandover = request.getExtras() != null &&
1789 request.getExtras().getBoolean(TelecomManager.EXTRA_IS_HANDOVER, false);
1790 boolean isHandover = request.getExtras() != null && request.getExtras().getBoolean(
1791 TelecomManager.EXTRA_IS_HANDOVER_CONNECTION, false);
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001792 Log.d(this, "createConnection, callManagerAccount: %s, callId: %s, request: %s, " +
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08001793 "isIncoming: %b, isUnknown: %b, isLegacyHandover: %b, isHandover: %b",
1794 callManagerAccount, callId, request, isIncoming, isUnknown, isLegacyHandover,
1795 isHandover);
Ihab Awad542e0ea2014-05-16 10:22:16 -07001796
Sanket Padawee29a2662017-12-01 13:59:27 -08001797 Connection connection = null;
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08001798 if (isHandover) {
1799 PhoneAccountHandle fromPhoneAccountHandle = request.getExtras() != null
1800 ? (PhoneAccountHandle) request.getExtras().getParcelable(
1801 TelecomManager.EXTRA_HANDOVER_FROM_PHONE_ACCOUNT) : null;
Sanket Padawee29a2662017-12-01 13:59:27 -08001802 if (!isIncoming) {
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08001803 connection = onCreateOutgoingHandoverConnection(fromPhoneAccountHandle, request);
Sanket Padawee29a2662017-12-01 13:59:27 -08001804 } else {
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08001805 connection = onCreateIncomingHandoverConnection(fromPhoneAccountHandle, request);
Sanket Padawee29a2662017-12-01 13:59:27 -08001806 }
1807 } else {
1808 connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
1809 : isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
1810 : onCreateOutgoingConnection(callManagerAccount, request);
1811 }
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001812 Log.d(this, "createConnection, connection: %s", connection);
1813 if (connection == null) {
Tyler Gunnfba1a8e2017-12-19 15:23:59 -08001814 Log.i(this, "createConnection, implementation returned null connection.");
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001815 connection = Connection.createFailedConnection(
Tyler Gunnfba1a8e2017-12-19 15:23:59 -08001816 new DisconnectCause(DisconnectCause.ERROR, "IMPL_RETURNED_NULL_CONNECTION"));
Sailesh Nepalc5b01572014-07-14 16:29:44 -07001817 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07001818
Tyler Gunnf2e08b42018-05-24 10:44:44 -07001819 boolean isSelfManaged =
1820 (connection.getConnectionProperties() & Connection.PROPERTY_SELF_MANAGED)
1821 == Connection.PROPERTY_SELF_MANAGED;
1822 // Self-managed Connections should always use voip audio mode; we default here so that the
1823 // local state within the ConnectionService matches the default we assume in Telecom.
1824 if (isSelfManaged) {
1825 connection.setAudioModeIsVoip(true);
1826 }
Tyler Gunnf0500bd2015-09-01 10:59:48 -07001827 connection.setTelecomCallId(callId);
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001828 if (connection.getState() != Connection.STATE_DISCONNECTED) {
Pengquan Meng70c9885332017-10-02 18:09:03 -07001829 addConnection(request.getAccountHandle(), callId, connection);
Ihab Awad6107bab2014-08-18 09:23:25 -07001830 }
1831
Andrew Lee100e2932014-09-08 15:34:24 -07001832 Uri address = connection.getAddress();
1833 String number = address == null ? "null" : address.getSchemeSpecificPart();
Tyler Gunn720c6642016-03-22 09:02:47 -07001834 Log.v(this, "createConnection, number: %s, state: %s, capabilities: %s, properties: %s",
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001835 Connection.toLogSafePhoneNumber(number),
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001836 Connection.stateToString(connection.getState()),
Tyler Gunn720c6642016-03-22 09:02:47 -07001837 Connection.capabilitiesToString(connection.getConnectionCapabilities()),
1838 Connection.propertiesToString(connection.getConnectionProperties()));
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001839
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001840 Log.d(this, "createConnection, calling handleCreateConnectionSuccessful %s", callId);
Ihab Awad6107bab2014-08-18 09:23:25 -07001841 mAdapter.handleCreateConnectionComplete(
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001842 callId,
Evan Charltonbf11f982014-07-20 22:06:28 -07001843 request,
1844 new ParcelableConnection(
1845 request.getAccountHandle(),
1846 connection.getState(),
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001847 connection.getConnectionCapabilities(),
Tyler Gunn720c6642016-03-22 09:02:47 -07001848 connection.getConnectionProperties(),
Christine Hallstrom2830ce92016-11-30 16:06:42 -08001849 connection.getSupportedAudioRoutes(),
Andrew Lee100e2932014-09-08 15:34:24 -07001850 connection.getAddress(),
1851 connection.getAddressPresentation(),
Evan Charltonbf11f982014-07-20 22:06:28 -07001852 connection.getCallerDisplayName(),
1853 connection.getCallerDisplayNamePresentation(),
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001854 connection.getVideoProvider() == null ?
1855 null : connection.getVideoProvider().getInterface(),
Sailesh Nepal8b9d3ca2014-08-14 17:39:34 -07001856 connection.getVideoState(),
Andrew Lee100e2932014-09-08 15:34:24 -07001857 connection.isRingbackRequested(),
Sailesh Nepal8b9d3ca2014-08-14 17:39:34 -07001858 connection.getAudioModeIsVoip(),
Roshan Piuse927ec02015-07-15 15:47:21 -07001859 connection.getConnectTimeMillis(),
Tyler Gunn3fa819c2017-08-04 09:27:26 -07001860 connection.getConnectElapsedTimeMillis(),
Ihab Awad6107bab2014-08-18 09:23:25 -07001861 connection.getStatusHints(),
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001862 connection.getDisconnectCause(),
Santos Cordon6b7f9552015-05-27 17:21:45 -07001863 createIdList(connection.getConferenceables()),
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001864 connection.getExtras(),
1865 connection.getCallerNumberVerificationStatus()));
Tyler Gunnf5035432017-01-09 09:43:12 -08001866
Tyler Gunnf2e08b42018-05-24 10:44:44 -07001867 if (isIncoming && request.shouldShowIncomingCallUi() && isSelfManaged) {
Tyler Gunnf5035432017-01-09 09:43:12 -08001868 // Tell ConnectionService to show its incoming call UX.
1869 connection.onShowIncomingCallUi();
1870 }
Shriram Ganesh6bf35ac2014-12-11 17:53:38 -08001871 if (isUnknown) {
1872 triggerConferenceRecalculate();
1873 }
Evan Charltonbf11f982014-07-20 22:06:28 -07001874 }
1875
Tyler Gunn159f35c2017-03-02 09:28:37 -08001876 private void createConnectionFailed(final PhoneAccountHandle callManagerAccount,
1877 final String callId, final ConnectionRequest request,
1878 boolean isIncoming) {
Tyler Gunn44e01912017-01-31 10:49:05 -08001879
1880 Log.i(this, "createConnectionFailed %s", callId);
1881 if (isIncoming) {
Tyler Gunn159f35c2017-03-02 09:28:37 -08001882 onCreateIncomingConnectionFailed(callManagerAccount, request);
Tyler Gunn44e01912017-01-31 10:49:05 -08001883 } else {
Tyler Gunn159f35c2017-03-02 09:28:37 -08001884 onCreateOutgoingConnectionFailed(callManagerAccount, request);
Tyler Gunn44e01912017-01-31 10:49:05 -08001885 }
1886 }
1887
Ravi Paluri80aa2142019-12-02 11:57:37 +05301888 private void createConferenceFailed(final PhoneAccountHandle callManagerAccount,
1889 final String callId, final ConnectionRequest request,
1890 boolean isIncoming) {
1891
1892 Log.i(this, "createConferenceFailed %s", callId);
1893 if (isIncoming) {
1894 onCreateIncomingConferenceFailed(callManagerAccount, request);
1895 } else {
1896 onCreateOutgoingConferenceFailed(callManagerAccount, request);
1897 }
1898 }
1899
Sanket Padawe4cc8ed52017-12-04 16:22:20 -08001900 private void handoverFailed(final String callId, final ConnectionRequest request,
1901 int reason) {
1902
1903 Log.i(this, "handoverFailed %s", callId);
1904 onHandoverFailed(request, reason);
1905 }
1906
Tyler Gunn041a1fe2017-05-12 10:04:49 -07001907 /**
1908 * Called by Telecom when the creation of a new Connection has completed and it is now added
1909 * to Telecom.
1910 * @param callId The ID of the connection.
1911 */
1912 private void notifyCreateConnectionComplete(final String callId) {
1913 Log.i(this, "notifyCreateConnectionComplete %s", callId);
Tyler Gunn0a88f2e2017-06-16 20:20:34 -07001914 if (callId == null) {
1915 // This could happen if the connection fails quickly and is removed from the
1916 // ConnectionService before Telecom sends the create connection complete callback.
1917 Log.w(this, "notifyCreateConnectionComplete: callId is null.");
1918 return;
1919 }
Tyler Gunn041a1fe2017-05-12 10:04:49 -07001920 onCreateConnectionComplete(findConnectionForAction(callId,
1921 "notifyCreateConnectionComplete"));
1922 }
1923
Ravi Paluri80aa2142019-12-02 11:57:37 +05301924 /**
1925 * Called by Telecom when the creation of a new Conference has completed and it is now added
1926 * to Telecom.
1927 * @param callId The ID of the connection.
1928 */
1929 private void notifyCreateConferenceComplete(final String callId) {
1930 Log.i(this, "notifyCreateConferenceComplete %s", callId);
1931 if (callId == null) {
1932 // This could happen if the conference fails quickly and is removed from the
1933 // ConnectionService before Telecom sends the create conference complete callback.
1934 Log.w(this, "notifyCreateConferenceComplete: callId is null.");
1935 return;
1936 }
1937 onCreateConferenceComplete(findConferenceForAction(callId,
1938 "notifyCreateConferenceComplete"));
1939 }
1940
1941
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001942 private void abort(String callId) {
Ihab Awad60ac30b2014-05-20 22:32:12 -07001943 Log.d(this, "abort %s", callId);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001944 findConnectionForAction(callId, "abort").onAbort();
Ihab Awad542e0ea2014-05-16 10:22:16 -07001945 }
1946
Tyler Gunnbe74de02014-08-29 14:51:48 -07001947 private void answerVideo(String callId, int videoState) {
1948 Log.d(this, "answerVideo %s", callId);
Ravi Paluri80aa2142019-12-02 11:57:37 +05301949 if (mConnectionById.containsKey(callId)) {
1950 findConnectionForAction(callId, "answer").onAnswer(videoState);
1951 } else {
1952 findConferenceForAction(callId, "answer").onAnswer(videoState);
1953 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07001954 }
1955
Tyler Gunnbe74de02014-08-29 14:51:48 -07001956 private void answer(String callId) {
1957 Log.d(this, "answer %s", callId);
Ravi Paluri80aa2142019-12-02 11:57:37 +05301958 if (mConnectionById.containsKey(callId)) {
1959 findConnectionForAction(callId, "answer").onAnswer();
1960 } else {
1961 findConferenceForAction(callId, "answer").onAnswer();
1962 }
Tyler Gunnbe74de02014-08-29 14:51:48 -07001963 }
1964
Pooja Jaind34698d2017-12-28 14:15:31 +05301965 private void deflect(String callId, Uri address) {
1966 Log.d(this, "deflect %s", callId);
1967 findConnectionForAction(callId, "deflect").onDeflect(address);
1968 }
1969
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001970 private void reject(String callId) {
Ihab Awad60ac30b2014-05-20 22:32:12 -07001971 Log.d(this, "reject %s", callId);
Ravi Paluri80aa2142019-12-02 11:57:37 +05301972 if (mConnectionById.containsKey(callId)) {
1973 findConnectionForAction(callId, "reject").onReject();
1974 } else {
1975 findConferenceForAction(callId, "reject").onReject();
1976 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07001977 }
1978
Bryce Lee81901682015-08-28 16:38:02 -07001979 private void reject(String callId, String rejectWithMessage) {
1980 Log.d(this, "reject %s with message", callId);
1981 findConnectionForAction(callId, "reject").onReject(rejectWithMessage);
1982 }
1983
Bryce Leecac50772015-11-17 15:13:29 -08001984 private void silence(String callId) {
1985 Log.d(this, "silence %s", callId);
1986 findConnectionForAction(callId, "silence").onSilence();
1987 }
1988
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001989 private void disconnect(String callId) {
Ihab Awad60ac30b2014-05-20 22:32:12 -07001990 Log.d(this, "disconnect %s", callId);
Santos Cordon0159ac02014-08-21 14:28:11 -07001991 if (mConnectionById.containsKey(callId)) {
1992 findConnectionForAction(callId, "disconnect").onDisconnect();
1993 } else {
1994 findConferenceForAction(callId, "disconnect").onDisconnect();
1995 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07001996 }
1997
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001998 private void hold(String callId) {
Ihab Awad60ac30b2014-05-20 22:32:12 -07001999 Log.d(this, "hold %s", callId);
Santos Cordon0159ac02014-08-21 14:28:11 -07002000 if (mConnectionById.containsKey(callId)) {
2001 findConnectionForAction(callId, "hold").onHold();
2002 } else {
2003 findConferenceForAction(callId, "hold").onHold();
2004 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002005 }
2006
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002007 private void unhold(String callId) {
Ihab Awad60ac30b2014-05-20 22:32:12 -07002008 Log.d(this, "unhold %s", callId);
Santos Cordon0159ac02014-08-21 14:28:11 -07002009 if (mConnectionById.containsKey(callId)) {
2010 findConnectionForAction(callId, "unhold").onUnhold();
2011 } else {
2012 findConferenceForAction(callId, "unhold").onUnhold();
2013 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002014 }
2015
Yorke Lee4af59352015-05-13 14:14:54 -07002016 private void onCallAudioStateChanged(String callId, CallAudioState callAudioState) {
2017 Log.d(this, "onAudioStateChanged %s %s", callId, callAudioState);
Yorke Leea0d3ca92014-09-15 19:18:13 -07002018 if (mConnectionById.containsKey(callId)) {
Yorke Lee4af59352015-05-13 14:14:54 -07002019 findConnectionForAction(callId, "onCallAudioStateChanged").setCallAudioState(
2020 callAudioState);
Yorke Leea0d3ca92014-09-15 19:18:13 -07002021 } else {
Yorke Lee4af59352015-05-13 14:14:54 -07002022 findConferenceForAction(callId, "onCallAudioStateChanged").setCallAudioState(
2023 callAudioState);
Yorke Leea0d3ca92014-09-15 19:18:13 -07002024 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002025 }
2026
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002027 private void playDtmfTone(String callId, char digit) {
2028 Log.d(this, "playDtmfTone %s %c", callId, digit);
Yorke Leea0d3ca92014-09-15 19:18:13 -07002029 if (mConnectionById.containsKey(callId)) {
2030 findConnectionForAction(callId, "playDtmfTone").onPlayDtmfTone(digit);
2031 } else {
2032 findConferenceForAction(callId, "playDtmfTone").onPlayDtmfTone(digit);
2033 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002034 }
2035
2036 private void stopDtmfTone(String callId) {
2037 Log.d(this, "stopDtmfTone %s", callId);
Yorke Leea0d3ca92014-09-15 19:18:13 -07002038 if (mConnectionById.containsKey(callId)) {
2039 findConnectionForAction(callId, "stopDtmfTone").onStopDtmfTone();
2040 } else {
2041 findConferenceForAction(callId, "stopDtmfTone").onStopDtmfTone();
2042 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002043 }
2044
Santos Cordon823fd3c2014-08-07 18:35:18 -07002045 private void conference(String callId1, String callId2) {
2046 Log.d(this, "conference %s, %s", callId1, callId2);
Santos Cordon980acb92014-05-31 10:31:19 -07002047
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002048 // Attempt to get second connection or conference.
Santos Cordon823fd3c2014-08-07 18:35:18 -07002049 Connection connection2 = findConnectionForAction(callId2, "conference");
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002050 Conference conference2 = getNullConference();
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07002051 if (connection2 == getNullConnection()) {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002052 conference2 = findConferenceForAction(callId2, "conference");
2053 if (conference2 == getNullConference()) {
2054 Log.w(this, "Connection2 or Conference2 missing in conference request %s.",
2055 callId2);
2056 return;
2057 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002058 }
Santos Cordonb6939982014-06-04 20:20:58 -07002059
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002060 // Attempt to get first connection or conference and perform merge.
Ihab Awad50e35062014-09-30 09:17:03 -07002061 Connection connection1 = findConnectionForAction(callId1, "conference");
2062 if (connection1 == getNullConnection()) {
2063 Conference conference1 = findConferenceForAction(callId1, "addConnection");
2064 if (conference1 == getNullConference()) {
2065 Log.w(this,
2066 "Connection1 or Conference1 missing in conference request %s.",
2067 callId1);
2068 } else {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002069 // Call 1 is a conference.
2070 if (connection2 != getNullConnection()) {
2071 // Call 2 is a connection so merge via call 1 (conference).
2072 conference1.onMerge(connection2);
2073 } else {
2074 // Call 2 is ALSO a conference; this should never happen.
2075 Log.wtf(this, "There can only be one conference and an attempt was made to " +
2076 "merge two conferences.");
2077 return;
2078 }
Ihab Awad50e35062014-09-30 09:17:03 -07002079 }
2080 } else {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002081 // Call 1 is a connection.
2082 if (conference2 != getNullConference()) {
2083 // Call 2 is a conference, so merge via call 2.
2084 conference2.onMerge(connection1);
2085 } else {
2086 // Call 2 is a connection, so merge together.
2087 onConference(connection1, connection2);
2088 }
Ihab Awad50e35062014-09-30 09:17:03 -07002089 }
Santos Cordon980acb92014-05-31 10:31:19 -07002090 }
2091
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002092 private void splitFromConference(String callId) {
Santos Cordonb6939982014-06-04 20:20:58 -07002093 Log.d(this, "splitFromConference(%s)", callId);
Santos Cordon980acb92014-05-31 10:31:19 -07002094
2095 Connection connection = findConnectionForAction(callId, "splitFromConference");
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07002096 if (connection == getNullConnection()) {
Santos Cordon980acb92014-05-31 10:31:19 -07002097 Log.w(this, "Connection missing in conference request %s.", callId);
2098 return;
2099 }
2100
Santos Cordon0159ac02014-08-21 14:28:11 -07002101 Conference conference = connection.getConference();
2102 if (conference != null) {
2103 conference.onSeparate(connection);
2104 }
Santos Cordon980acb92014-05-31 10:31:19 -07002105 }
2106
Santos Cordona4868042014-09-04 17:39:22 -07002107 private void mergeConference(String callId) {
2108 Log.d(this, "mergeConference(%s)", callId);
2109 Conference conference = findConferenceForAction(callId, "mergeConference");
2110 if (conference != null) {
2111 conference.onMerge();
2112 }
2113 }
2114
2115 private void swapConference(String callId) {
2116 Log.d(this, "swapConference(%s)", callId);
2117 Conference conference = findConferenceForAction(callId, "swapConference");
2118 if (conference != null) {
2119 conference.onSwap();
2120 }
2121 }
2122
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002123 /**
2124 * Notifies a {@link Connection} of a request to pull an external call.
2125 *
2126 * See {@link Call#pullExternalCall()}.
2127 *
2128 * @param callId The ID of the call to pull.
2129 */
2130 private void pullExternalCall(String callId) {
2131 Log.d(this, "pullExternalCall(%s)", callId);
2132 Connection connection = findConnectionForAction(callId, "pullExternalCall");
2133 if (connection != null) {
2134 connection.onPullExternalCall();
2135 }
2136 }
2137
2138 /**
2139 * Notifies a {@link Connection} of a call event.
2140 *
2141 * See {@link Call#sendCallEvent(String, Bundle)}.
2142 *
2143 * @param callId The ID of the call receiving the event.
2144 * @param event The event.
2145 * @param extras Extras associated with the event.
2146 */
2147 private void sendCallEvent(String callId, String event, Bundle extras) {
2148 Log.d(this, "sendCallEvent(%s, %s)", callId, event);
2149 Connection connection = findConnectionForAction(callId, "sendCallEvent");
2150 if (connection != null) {
2151 connection.onCallEvent(event, extras);
2152 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002153 }
2154
Tyler Gunndee56a82016-03-23 16:06:34 -07002155 /**
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08002156 * Notifies a {@link Connection} that a handover has completed.
2157 *
2158 * @param callId The ID of the call which completed handover.
2159 */
2160 private void notifyHandoverComplete(String callId) {
2161 Log.d(this, "notifyHandoverComplete(%s)", callId);
2162 Connection connection = findConnectionForAction(callId, "notifyHandoverComplete");
2163 if (connection != null) {
2164 connection.onHandoverComplete();
2165 }
2166 }
2167
2168 /**
Tyler Gunndee56a82016-03-23 16:06:34 -07002169 * Notifies a {@link Connection} or {@link Conference} of a change to the extras from Telecom.
2170 * <p>
2171 * These extra changes can originate from Telecom itself, or from an {@link InCallService} via
2172 * the {@link android.telecom.Call#putExtra(String, boolean)},
2173 * {@link android.telecom.Call#putExtra(String, int)},
2174 * {@link android.telecom.Call#putExtra(String, String)},
2175 * {@link Call#removeExtras(List)}.
2176 *
2177 * @param callId The ID of the call receiving the event.
2178 * @param extras The new extras bundle.
2179 */
2180 private void handleExtrasChanged(String callId, Bundle extras) {
2181 Log.d(this, "handleExtrasChanged(%s, %s)", callId, extras);
2182 if (mConnectionById.containsKey(callId)) {
2183 findConnectionForAction(callId, "handleExtrasChanged").handleExtrasChanged(extras);
2184 } else if (mConferenceById.containsKey(callId)) {
2185 findConferenceForAction(callId, "handleExtrasChanged").handleExtrasChanged(extras);
2186 }
2187 }
2188
Hall Liub64ac4c2017-02-06 10:49:48 -08002189 private void startRtt(String callId, Connection.RttTextStream rttTextStream) {
2190 Log.d(this, "startRtt(%s)", callId);
2191 if (mConnectionById.containsKey(callId)) {
2192 findConnectionForAction(callId, "startRtt").onStartRtt(rttTextStream);
2193 } else if (mConferenceById.containsKey(callId)) {
2194 Log.w(this, "startRtt called on a conference.");
2195 }
2196 }
2197
2198 private void stopRtt(String callId) {
2199 Log.d(this, "stopRtt(%s)", callId);
2200 if (mConnectionById.containsKey(callId)) {
2201 findConnectionForAction(callId, "stopRtt").onStopRtt();
2202 } else if (mConferenceById.containsKey(callId)) {
2203 Log.w(this, "stopRtt called on a conference.");
2204 }
2205 }
2206
2207 private void handleRttUpgradeResponse(String callId, Connection.RttTextStream rttTextStream) {
2208 Log.d(this, "handleRttUpgradeResponse(%s, %s)", callId, rttTextStream == null);
2209 if (mConnectionById.containsKey(callId)) {
2210 findConnectionForAction(callId, "handleRttUpgradeResponse")
2211 .handleRttUpgradeResponse(rttTextStream);
2212 } else if (mConferenceById.containsKey(callId)) {
2213 Log.w(this, "handleRttUpgradeResponse called on a conference.");
2214 }
2215 }
2216
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002217 private void onPostDialContinue(String callId, boolean proceed) {
Evan Charlton6dea4ac2014-06-03 14:07:13 -07002218 Log.d(this, "onPostDialContinue(%s)", callId);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002219 findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
Evan Charlton6dea4ac2014-06-03 14:07:13 -07002220 }
2221
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002222 private void onAdapterAttached() {
Ihab Awad9c3f1882014-06-30 21:17:13 -07002223 if (mAreAccountsInitialized) {
Santos Cordon52d8a152014-06-17 19:08:45 -07002224 // No need to query again if we already did it.
2225 return;
2226 }
2227
Tyler Gunn4c69fb32019-05-17 10:49:16 -07002228 String callingPackage = getOpPackageName();
2229
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002230 mAdapter.queryRemoteConnectionServices(new RemoteServiceCallback.Stub() {
Santos Cordon52d8a152014-06-17 19:08:45 -07002231 @Override
2232 public void onResult(
2233 final List<ComponentName> componentNames,
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002234 final List<IBinder> services) {
Brad Ebinger0c3541b2016-11-01 14:11:38 -07002235 mHandler.post(new android.telecom.Logging.Runnable("oAA.qRCS.oR", null /*lock*/) {
Ihab Awad6107bab2014-08-18 09:23:25 -07002236 @Override
Brad Ebinger0c3541b2016-11-01 14:11:38 -07002237 public void loggedRun() {
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002238 for (int i = 0; i < componentNames.size() && i < services.size(); i++) {
Santos Cordon52d8a152014-06-17 19:08:45 -07002239 mRemoteConnectionManager.addConnectionService(
2240 componentNames.get(i),
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002241 IConnectionService.Stub.asInterface(services.get(i)));
Santos Cordon52d8a152014-06-17 19:08:45 -07002242 }
Ihab Awad5d0410f2014-07-30 10:07:40 -07002243 onAccountsInitialized();
Sailesh Nepalc5b01572014-07-14 16:29:44 -07002244 Log.d(this, "remote connection services found: " + services);
Santos Cordon52d8a152014-06-17 19:08:45 -07002245 }
Brad Ebinger0c3541b2016-11-01 14:11:38 -07002246 }.prepare());
Santos Cordon52d8a152014-06-17 19:08:45 -07002247 }
2248
2249 @Override
2250 public void onError() {
Brad Ebinger0c3541b2016-11-01 14:11:38 -07002251 mHandler.post(new android.telecom.Logging.Runnable("oAA.qRCS.oE", null /*lock*/) {
Ihab Awad6107bab2014-08-18 09:23:25 -07002252 @Override
Brad Ebinger0c3541b2016-11-01 14:11:38 -07002253 public void loggedRun() {
Ihab Awad9c3f1882014-06-30 21:17:13 -07002254 mAreAccountsInitialized = true;
Santos Cordon52d8a152014-06-17 19:08:45 -07002255 }
Brad Ebinger0c3541b2016-11-01 14:11:38 -07002256 }.prepare());
Santos Cordon52d8a152014-06-17 19:08:45 -07002257 }
Tyler Gunn4c69fb32019-05-17 10:49:16 -07002258 }, callingPackage);
Santos Cordon52d8a152014-06-17 19:08:45 -07002259 }
2260
Ihab Awadf8b69882014-07-25 15:14:01 -07002261 /**
2262 * Ask some other {@code ConnectionService} to create a {@code RemoteConnection} given an
Santos Cordona663f862014-10-29 13:49:58 -07002263 * incoming request. This is used by {@code ConnectionService}s that are registered with
2264 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} and want to be able to manage
2265 * SIM-based incoming calls.
Ihab Awadf8b69882014-07-25 15:14:01 -07002266 *
2267 * @param connectionManagerPhoneAccount See description at
2268 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
2269 * @param request Details about the incoming call.
2270 * @return The {@code Connection} object to satisfy this call, or {@code null} to
2271 * not handle the call.
2272 */
2273 public final RemoteConnection createRemoteIncomingConnection(
2274 PhoneAccountHandle connectionManagerPhoneAccount,
2275 ConnectionRequest request) {
2276 return mRemoteConnectionManager.createRemoteConnection(
2277 connectionManagerPhoneAccount, request, true);
Santos Cordon52d8a152014-06-17 19:08:45 -07002278 }
2279
2280 /**
Ihab Awadf8b69882014-07-25 15:14:01 -07002281 * Ask some other {@code ConnectionService} to create a {@code RemoteConnection} given an
Santos Cordona663f862014-10-29 13:49:58 -07002282 * outgoing request. This is used by {@code ConnectionService}s that are registered with
2283 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} and want to be able to use the
2284 * SIM-based {@code ConnectionService} to place its outgoing calls.
Ihab Awadf8b69882014-07-25 15:14:01 -07002285 *
2286 * @param connectionManagerPhoneAccount See description at
2287 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
Cuihtlauac ALVARADO0b3b2a52016-09-13 14:49:41 +02002288 * @param request Details about the outgoing call.
Ihab Awadf8b69882014-07-25 15:14:01 -07002289 * @return The {@code Connection} object to satisfy this call, or {@code null} to
2290 * not handle the call.
2291 */
2292 public final RemoteConnection createRemoteOutgoingConnection(
2293 PhoneAccountHandle connectionManagerPhoneAccount,
2294 ConnectionRequest request) {
2295 return mRemoteConnectionManager.createRemoteConnection(
2296 connectionManagerPhoneAccount, request, false);
2297 }
2298
2299 /**
Santos Cordona663f862014-10-29 13:49:58 -07002300 * Indicates to the relevant {@code RemoteConnectionService} that the specified
2301 * {@link RemoteConnection}s should be merged into a conference call.
2302 * <p>
2303 * If the conference request is successful, the method {@link #onRemoteConferenceAdded} will
2304 * be invoked.
2305 *
2306 * @param remoteConnection1 The first of the remote connections to conference.
2307 * @param remoteConnection2 The second of the remote connections to conference.
Ihab Awadb8e85c72014-08-23 20:34:57 -07002308 */
2309 public final void conferenceRemoteConnections(
Santos Cordona663f862014-10-29 13:49:58 -07002310 RemoteConnection remoteConnection1,
2311 RemoteConnection remoteConnection2) {
2312 mRemoteConnectionManager.conferenceRemoteConnections(remoteConnection1, remoteConnection2);
Ihab Awadb8e85c72014-08-23 20:34:57 -07002313 }
2314
2315 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -07002316 * Adds a new conference call. When a conference call is created either as a result of an
2317 * explicit request via {@link #onConference} or otherwise, the connection service should supply
2318 * an instance of {@link Conference} by invoking this method. A conference call provided by this
2319 * method will persist until {@link Conference#destroy} is invoked on the conference instance.
2320 *
2321 * @param conference The new conference object.
2322 */
2323 public final void addConference(Conference conference) {
Rekha Kumar07366812015-03-24 16:42:31 -07002324 Log.d(this, "addConference: conference=%s", conference);
2325
Santos Cordon823fd3c2014-08-07 18:35:18 -07002326 String id = addConferenceInternal(conference);
2327 if (id != null) {
2328 List<String> connectionIds = new ArrayList<>(2);
2329 for (Connection connection : conference.getConnections()) {
2330 if (mIdByConnection.containsKey(connection)) {
2331 connectionIds.add(mIdByConnection.get(connection));
2332 }
2333 }
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002334 conference.setTelecomCallId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002335 ParcelableConference parcelableConference = new ParcelableConference(
Nancy Chenea38cca2014-09-05 16:38:49 -07002336 conference.getPhoneAccountHandle(),
Santos Cordon823fd3c2014-08-07 18:35:18 -07002337 conference.getState(),
Ihab Awad5c9c86e2014-11-12 13:41:16 -08002338 conference.getConnectionCapabilities(),
Tyler Gunn720c6642016-03-22 09:02:47 -07002339 conference.getConnectionProperties(),
Tyler Gunncd5d33c2015-01-12 09:02:01 -08002340 connectionIds,
Rekha Kumar07366812015-03-24 16:42:31 -07002341 conference.getVideoProvider() == null ?
2342 null : conference.getVideoProvider().getInterface(),
2343 conference.getVideoState(),
Andrew Lee3e3e2f22015-04-16 13:48:43 -07002344 conference.getConnectTimeMillis(),
Tyler Gunn17541392018-02-01 08:58:38 -08002345 conference.getConnectionStartElapsedRealTime(),
Santos Cordon6b7f9552015-05-27 17:21:45 -07002346 conference.getStatusHints(),
Tyler Gunnac60f952019-05-31 07:23:16 -07002347 conference.getExtras(),
2348 conference.getAddress(),
2349 conference.getAddressPresentation(),
2350 conference.getCallerDisplayName(),
2351 conference.getCallerDisplayNamePresentation());
Andrew Lee0f51da32015-04-16 13:11:55 -07002352
Santos Cordon823fd3c2014-08-07 18:35:18 -07002353 mAdapter.addConferenceCall(id, parcelableConference);
Rekha Kumar07366812015-03-24 16:42:31 -07002354 mAdapter.setVideoProvider(id, conference.getVideoProvider());
2355 mAdapter.setVideoState(id, conference.getVideoState());
Santos Cordon823fd3c2014-08-07 18:35:18 -07002356
2357 // Go through any child calls and set the parent.
2358 for (Connection connection : conference.getConnections()) {
2359 String connectionId = mIdByConnection.get(connection);
2360 if (connectionId != null) {
2361 mAdapter.setIsConferenced(connectionId, id);
2362 }
2363 }
Pengquan Meng70c9885332017-10-02 18:09:03 -07002364 onConferenceAdded(conference);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002365 }
2366 }
2367
2368 /**
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002369 * Adds a connection created by the {@link ConnectionService} and informs telecom of the new
2370 * connection.
2371 *
2372 * @param phoneAccountHandle The phone account handle for the connection.
2373 * @param connection The connection to add.
2374 */
2375 public final void addExistingConnection(PhoneAccountHandle phoneAccountHandle,
2376 Connection connection) {
Tyler Gunn78da7812017-05-09 14:34:57 -07002377 addExistingConnection(phoneAccountHandle, connection, null /* conference */);
2378 }
2379
2380 /**
Pengquan Meng731c1a32017-11-21 18:01:13 -08002381 * Call to inform Telecom that your {@link ConnectionService} has released call resources (e.g
2382 * microphone, camera).
2383 *
Pengquan Menge3bf7e22018-02-22 17:30:04 -08002384 * <p>
2385 * The {@link ConnectionService} will be disconnected when it failed to call this method within
2386 * 5 seconds after {@link #onConnectionServiceFocusLost()} is called.
2387 *
Pengquan Meng731c1a32017-11-21 18:01:13 -08002388 * @see ConnectionService#onConnectionServiceFocusLost()
2389 */
2390 public final void connectionServiceFocusReleased() {
2391 mAdapter.onConnectionServiceFocusReleased();
2392 }
2393
2394 /**
Tyler Gunn78da7812017-05-09 14:34:57 -07002395 * Adds a connection created by the {@link ConnectionService} and informs telecom of the new
Tyler Gunn5567d742019-10-31 13:04:37 -07002396 * connection, as well as adding that connection to the specified conference.
2397 * <p>
2398 * Note: This API is intended ONLY for use by the Telephony stack to provide an easy way to add
2399 * IMS conference participants to be added to a conference in a single step; this helps ensure
2400 * UI updates happen atomically, rather than adding the connection and then adding it to
2401 * the conference in another step.
Tyler Gunn78da7812017-05-09 14:34:57 -07002402 *
2403 * @param phoneAccountHandle The phone account handle for the connection.
2404 * @param connection The connection to add.
2405 * @param conference The parent conference of the new connection.
2406 * @hide
2407 */
Tyler Gunn5567d742019-10-31 13:04:37 -07002408 @SystemApi
2409 public final void addExistingConnection(@NonNull PhoneAccountHandle phoneAccountHandle,
2410 @NonNull Connection connection, @NonNull Conference conference) {
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002411
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002412 String id = addExistingConnectionInternal(phoneAccountHandle, connection);
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002413 if (id != null) {
2414 List<String> emptyList = new ArrayList<>(0);
Tyler Gunn78da7812017-05-09 14:34:57 -07002415 String conferenceId = null;
2416 if (conference != null) {
2417 conferenceId = mIdByConference.get(conference);
2418 }
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002419
2420 ParcelableConnection parcelableConnection = new ParcelableConnection(
2421 phoneAccountHandle,
2422 connection.getState(),
Ihab Awad5c9c86e2014-11-12 13:41:16 -08002423 connection.getConnectionCapabilities(),
Tyler Gunn720c6642016-03-22 09:02:47 -07002424 connection.getConnectionProperties(),
Christine Hallstrom2830ce92016-11-30 16:06:42 -08002425 connection.getSupportedAudioRoutes(),
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002426 connection.getAddress(),
2427 connection.getAddressPresentation(),
2428 connection.getCallerDisplayName(),
2429 connection.getCallerDisplayNamePresentation(),
2430 connection.getVideoProvider() == null ?
2431 null : connection.getVideoProvider().getInterface(),
2432 connection.getVideoState(),
2433 connection.isRingbackRequested(),
2434 connection.getAudioModeIsVoip(),
Roshan Piuse927ec02015-07-15 15:47:21 -07002435 connection.getConnectTimeMillis(),
Tyler Gunn3fa819c2017-08-04 09:27:26 -07002436 connection.getConnectElapsedTimeMillis(),
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002437 connection.getStatusHints(),
2438 connection.getDisconnectCause(),
Santos Cordon6b7f9552015-05-27 17:21:45 -07002439 emptyList,
Tyler Gunn78da7812017-05-09 14:34:57 -07002440 connection.getExtras(),
Tyler Gunn6986a632019-06-25 13:45:32 -07002441 conferenceId,
Tyler Gunnd57d76c2019-09-24 14:53:23 -07002442 connection.getCallDirection(),
2443 Connection.VERIFICATION_STATUS_NOT_VERIFIED);
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002444 mAdapter.addExistingConnection(id, parcelableConnection);
2445 }
2446 }
2447
2448 /**
Ihab Awadf8b69882014-07-25 15:14:01 -07002449 * Returns all the active {@code Connection}s for which this {@code ConnectionService}
2450 * has taken responsibility.
2451 *
2452 * @return A collection of {@code Connection}s created by this {@code ConnectionService}.
Santos Cordonb6939982014-06-04 20:20:58 -07002453 */
Sailesh Nepal091768c2014-06-30 15:15:23 -07002454 public final Collection<Connection> getAllConnections() {
Santos Cordonb6939982014-06-04 20:20:58 -07002455 return mConnectionById.values();
2456 }
2457
2458 /**
Santos Cordona6018b92016-02-16 14:23:12 -08002459 * Returns all the active {@code Conference}s for which this {@code ConnectionService}
2460 * has taken responsibility.
2461 *
2462 * @return A collection of {@code Conference}s created by this {@code ConnectionService}.
2463 */
2464 public final Collection<Conference> getAllConferences() {
2465 return mConferenceById.values();
2466 }
2467
2468 /**
Ihab Awadf8b69882014-07-25 15:14:01 -07002469 * Create a {@code Connection} given an incoming request. This is used to attach to existing
2470 * incoming calls.
Evan Charltonbf11f982014-07-20 22:06:28 -07002471 *
Ihab Awadf8b69882014-07-25 15:14:01 -07002472 * @param connectionManagerPhoneAccount See description at
2473 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
2474 * @param request Details about the incoming call.
2475 * @return The {@code Connection} object to satisfy this call, or {@code null} to
2476 * not handle the call.
Ihab Awad542e0ea2014-05-16 10:22:16 -07002477 */
Ihab Awadf8b69882014-07-25 15:14:01 -07002478 public Connection onCreateIncomingConnection(
2479 PhoneAccountHandle connectionManagerPhoneAccount,
2480 ConnectionRequest request) {
2481 return null;
2482 }
Ravi Paluri80aa2142019-12-02 11:57:37 +05302483 /**
2484 * Create a {@code Connection} given an incoming request. This is used to attach to existing
2485 * incoming conference call.
2486 *
2487 * @param connectionManagerPhoneAccount See description at
2488 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
2489 * @param request Details about the incoming call.
2490 * @return The {@code Connection} object to satisfy this call, or {@code null} to
2491 * not handle the call.
2492 */
2493 public @Nullable Conference onCreateIncomingConference(
2494 @Nullable PhoneAccountHandle connectionManagerPhoneAccount,
2495 @Nullable ConnectionRequest request) {
2496 return null;
2497 }
Sailesh Nepalc5b01572014-07-14 16:29:44 -07002498
2499 /**
Tyler Gunn041a1fe2017-05-12 10:04:49 -07002500 * Called after the {@link Connection} returned by
2501 * {@link #onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}
2502 * or {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)} has been
2503 * added to the {@link ConnectionService} and sent to Telecom.
2504 *
2505 * @param connection the {@link Connection}.
2506 * @hide
2507 */
2508 public void onCreateConnectionComplete(Connection connection) {
2509 }
2510
2511 /**
Ravi Paluri80aa2142019-12-02 11:57:37 +05302512 * Called after the {@link Conference} returned by
2513 * {@link #onCreateIncomingConference(PhoneAccountHandle, ConnectionRequest)}
2514 * or {@link #onCreateOutgoingConference(PhoneAccountHandle, ConnectionRequest)} has been
2515 * added to the {@link ConnectionService} and sent to Telecom.
2516 *
2517 * @param conference the {@link Conference}.
2518 * @hide
2519 */
2520 public void onCreateConferenceComplete(Conference conference) {
2521 }
2522
2523
2524 /**
Tyler Gunnf5035432017-01-09 09:43:12 -08002525 * Called by Telecom to inform the {@link ConnectionService} that its request to create a new
2526 * incoming {@link Connection} was denied.
2527 * <p>
2528 * Used when a self-managed {@link ConnectionService} attempts to create a new incoming
2529 * {@link Connection}, but Telecom has determined that the call cannot be allowed at this time.
2530 * The {@link ConnectionService} is responsible for silently rejecting the new incoming
2531 * {@link Connection}.
2532 * <p>
2533 * See {@link TelecomManager#isIncomingCallPermitted(PhoneAccountHandle)} for more information.
2534 *
Tyler Gunn159f35c2017-03-02 09:28:37 -08002535 * @param connectionManagerPhoneAccount See description at
2536 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
Tyler Gunnf5035432017-01-09 09:43:12 -08002537 * @param request The incoming connection request.
2538 */
Tyler Gunn159f35c2017-03-02 09:28:37 -08002539 public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount,
2540 ConnectionRequest request) {
Tyler Gunnf5035432017-01-09 09:43:12 -08002541 }
2542
2543 /**
2544 * Called by Telecom to inform the {@link ConnectionService} that its request to create a new
2545 * outgoing {@link Connection} was denied.
2546 * <p>
2547 * Used when a self-managed {@link ConnectionService} attempts to create a new outgoing
2548 * {@link Connection}, but Telecom has determined that the call cannot be placed at this time.
2549 * The {@link ConnectionService} is responisible for informing the user that the
2550 * {@link Connection} cannot be made at this time.
2551 * <p>
2552 * See {@link TelecomManager#isOutgoingCallPermitted(PhoneAccountHandle)} for more information.
2553 *
Tyler Gunn159f35c2017-03-02 09:28:37 -08002554 * @param connectionManagerPhoneAccount See description at
2555 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
Tyler Gunnf5035432017-01-09 09:43:12 -08002556 * @param request The outgoing connection request.
2557 */
Tyler Gunn159f35c2017-03-02 09:28:37 -08002558 public void onCreateOutgoingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount,
2559 ConnectionRequest request) {
Tyler Gunnf5035432017-01-09 09:43:12 -08002560 }
2561
2562 /**
Ravi Paluri80aa2142019-12-02 11:57:37 +05302563 * Called by Telecom to inform the {@link ConnectionService} that its request to create a new
2564 * incoming {@link Conference} was denied.
2565 * <p>
2566 * Used when a self-managed {@link ConnectionService} attempts to create a new incoming
2567 * {@link Conference}, but Telecom has determined that the call cannot be allowed at this time.
2568 * The {@link ConnectionService} is responsible for silently rejecting the new incoming
2569 * {@link Conference}.
2570 * <p>
2571 * See {@link TelecomManager#isIncomingCallPermitted(PhoneAccountHandle)} for more information.
2572 *
2573 * @param connectionManagerPhoneAccount See description at
2574 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
2575 * @param request The incoming connection request.
2576 */
2577 public void onCreateIncomingConferenceFailed(
2578 @Nullable PhoneAccountHandle connectionManagerPhoneAccount,
2579 @Nullable ConnectionRequest request) {
2580 }
2581
2582 /**
2583 * Called by Telecom to inform the {@link ConnectionService} that its request to create a new
2584 * outgoing {@link Conference} was denied.
2585 * <p>
2586 * Used when a self-managed {@link ConnectionService} attempts to create a new outgoing
2587 * {@link Conference}, but Telecom has determined that the call cannot be placed at this time.
2588 * The {@link ConnectionService} is responisible for informing the user that the
2589 * {@link Conference} cannot be made at this time.
2590 * <p>
2591 * See {@link TelecomManager#isOutgoingCallPermitted(PhoneAccountHandle)} for more information.
2592 *
2593 * @param connectionManagerPhoneAccount See description at
2594 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
2595 * @param request The outgoing connection request.
2596 */
2597 public void onCreateOutgoingConferenceFailed(
2598 @Nullable PhoneAccountHandle connectionManagerPhoneAccount,
2599 @Nullable ConnectionRequest request) {
2600 }
2601
2602
2603 /**
Shriram Ganesh6bf35ac2014-12-11 17:53:38 -08002604 * Trigger recalculate functinality for conference calls. This is used when a Telephony
2605 * Connection is part of a conference controller but is not yet added to Connection
2606 * Service and hence cannot be added to the conference call.
2607 *
2608 * @hide
2609 */
2610 public void triggerConferenceRecalculate() {
2611 }
2612
2613 /**
Ihab Awadf8b69882014-07-25 15:14:01 -07002614 * Create a {@code Connection} given an outgoing request. This is used to initiate new
2615 * outgoing calls.
Sailesh Nepalc5b01572014-07-14 16:29:44 -07002616 *
Ihab Awadf8b69882014-07-25 15:14:01 -07002617 * @param connectionManagerPhoneAccount The connection manager account to use for managing
2618 * this call.
2619 * <p>
2620 * If this parameter is not {@code null}, it means that this {@code ConnectionService}
2621 * has registered one or more {@code PhoneAccount}s having
2622 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}. This parameter will contain
2623 * one of these {@code PhoneAccount}s, while the {@code request} will contain another
2624 * (usually but not always distinct) {@code PhoneAccount} to be used for actually
2625 * making the connection.
2626 * <p>
2627 * If this parameter is {@code null}, it means that this {@code ConnectionService} is
2628 * being asked to make a direct connection. The
2629 * {@link ConnectionRequest#getAccountHandle()} of parameter {@code request} will be
2630 * a {@code PhoneAccount} registered by this {@code ConnectionService} to use for
2631 * making the connection.
2632 * @param request Details about the outgoing call.
2633 * @return The {@code Connection} object to satisfy this call, or the result of an invocation
Andrew Lee7f3d41f2014-09-11 17:33:16 -07002634 * of {@link Connection#createFailedConnection(DisconnectCause)} to not handle the call.
Sailesh Nepalc5b01572014-07-14 16:29:44 -07002635 */
Ihab Awadf8b69882014-07-25 15:14:01 -07002636 public Connection onCreateOutgoingConnection(
2637 PhoneAccountHandle connectionManagerPhoneAccount,
2638 ConnectionRequest request) {
2639 return null;
2640 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002641
2642 /**
Ravi Paluri80aa2142019-12-02 11:57:37 +05302643 * Create a {@code Conference} given an outgoing request. This is used to initiate new
2644 * outgoing conference call.
2645 *
2646 * @param connectionManagerPhoneAccount The connection manager account to use for managing
2647 * this call.
2648 * <p>
2649 * If this parameter is not {@code null}, it means that this {@code ConnectionService}
2650 * has registered one or more {@code PhoneAccount}s having
2651 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}. This parameter will contain
2652 * one of these {@code PhoneAccount}s, while the {@code request} will contain another
2653 * (usually but not always distinct) {@code PhoneAccount} to be used for actually
2654 * making the connection.
2655 * <p>
2656 * If this parameter is {@code null}, it means that this {@code ConnectionService} is
2657 * being asked to make a direct connection. The
2658 * {@link ConnectionRequest#getAccountHandle()} of parameter {@code request} will be
2659 * a {@code PhoneAccount} registered by this {@code ConnectionService} to use for
2660 * making the connection.
2661 * @param request Details about the outgoing call.
2662 * @return The {@code Conference} object to satisfy this call, or the result of an invocation
2663 * of {@link Connection#createFailedConnection(DisconnectCause)} to not handle the call.
2664 */
2665 public @Nullable Conference onCreateOutgoingConference(
2666 @Nullable PhoneAccountHandle connectionManagerPhoneAccount,
2667 @Nullable ConnectionRequest request) {
2668 return null;
2669 }
2670
2671
2672 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08002673 * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
2674 * outgoing handover {@link Connection}.
2675 * <p>
2676 * A call handover is the process where an ongoing call is transferred from one app (i.e.
2677 * {@link ConnectionService} to another app. The user could, for example, choose to continue a
2678 * mobile network call in a video calling app. The mobile network call via the Telephony stack
2679 * is referred to as the source of the handover, and the video calling app is referred to as the
2680 * destination.
2681 * <p>
2682 * When considering a handover scenario the <em>initiating</em> device is where a user initiated
2683 * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
2684 * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
2685 * device.
2686 * <p>
2687 * This method is called on the destination {@link ConnectionService} on <em>initiating</em>
2688 * device when the user initiates a handover request from one app to another. The user request
2689 * originates in the {@link InCallService} via
2690 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
2691 * <p>
2692 * For a full discussion of the handover process and the APIs involved, see
2693 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
2694 * <p>
2695 * Implementations of this method should return an instance of {@link Connection} which
2696 * represents the handover. If your app does not wish to accept a handover to it at this time,
2697 * you can return {@code null}. The code below shows an example of how this is done.
2698 * <pre>
2699 * {@code
2700 * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
2701 * fromPhoneAccountHandle, ConnectionRequest request) {
2702 * if (!isHandoverAvailable()) {
2703 * return null;
2704 * }
2705 * MyConnection connection = new MyConnection();
2706 * connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
2707 * connection.setVideoState(request.getVideoState());
2708 * return connection;
2709 * }
2710 * }
2711 * </pre>
2712 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07002713 * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
2714 * ConnectionService which needs to handover the call.
Tyler Gunn9d127732018-03-02 15:45:51 -08002715 * @param request Details about the call to handover.
2716 * @return {@link Connection} instance corresponding to the handover call.
Sanket Padawea8eddd42017-11-03 11:07:35 -07002717 */
2718 public Connection onCreateOutgoingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
2719 ConnectionRequest request) {
2720 return null;
2721 }
2722
2723 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08002724 * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
2725 * incoming handover {@link Connection}.
2726 * <p>
2727 * A call handover is the process where an ongoing call is transferred from one app (i.e.
2728 * {@link ConnectionService} to another app. The user could, for example, choose to continue a
2729 * mobile network call in a video calling app. The mobile network call via the Telephony stack
2730 * is referred to as the source of the handover, and the video calling app is referred to as the
2731 * destination.
2732 * <p>
2733 * When considering a handover scenario the <em>initiating</em> device is where a user initiated
2734 * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
2735 * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
2736 * device.
2737 * <p>
2738 * This method is called on the destination app on the <em>receiving</em> device when the
2739 * destination app calls {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to
2740 * accept an incoming handover from the <em>initiating</em> device.
2741 * <p>
2742 * For a full discussion of the handover process and the APIs involved, see
2743 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
2744 * <p>
2745 * Implementations of this method should return an instance of {@link Connection} which
2746 * represents the handover. The code below shows an example of how this is done.
2747 * <pre>
2748 * {@code
2749 * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
2750 * fromPhoneAccountHandle, ConnectionRequest request) {
2751 * // Given that your app requested to accept the handover, you should not return null here.
2752 * MyConnection connection = new MyConnection();
2753 * connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
2754 * connection.setVideoState(request.getVideoState());
2755 * return connection;
2756 * }
2757 * }
2758 * </pre>
2759 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07002760 * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
2761 * ConnectionService which needs to handover the call.
2762 * @param request Details about the call which needs to be handover.
Tyler Gunn9d127732018-03-02 15:45:51 -08002763 * @return {@link Connection} instance corresponding to the handover call.
Sanket Padawea8eddd42017-11-03 11:07:35 -07002764 */
2765 public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
2766 ConnectionRequest request) {
2767 return null;
2768 }
2769
2770 /**
2771 * Called by Telecom in response to a {@code TelecomManager#acceptHandover()}
2772 * invocation which failed.
Tyler Gunn9d127732018-03-02 15:45:51 -08002773 * <p>
2774 * For a full discussion of the handover process and the APIs involved, see
2775 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}
2776 *
2777 * @param request Details about the call which failed to handover.
2778 * @param error Reason for handover failure. Will be one of the
Sanket Padawea8eddd42017-11-03 11:07:35 -07002779 */
Tyler Gunn9d127732018-03-02 15:45:51 -08002780 public void onHandoverFailed(ConnectionRequest request,
2781 @Call.Callback.HandoverFailureErrors int error) {
Sanket Padawea8eddd42017-11-03 11:07:35 -07002782 return;
2783 }
2784
2785 /**
Yorke Leec3cf9822014-10-02 09:38:39 -07002786 * Create a {@code Connection} for a new unknown call. An unknown call is a call originating
2787 * from the ConnectionService that was neither a user-initiated outgoing call, nor an incoming
2788 * call created using
2789 * {@code TelecomManager#addNewIncomingCall(PhoneAccountHandle, android.os.Bundle)}.
2790 *
Yorke Lee770ed6e2014-10-06 18:58:52 -07002791 * @hide
Yorke Leec3cf9822014-10-02 09:38:39 -07002792 */
2793 public Connection onCreateUnknownConnection(PhoneAccountHandle connectionManagerPhoneAccount,
2794 ConnectionRequest request) {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07002795 return null;
Yorke Leec3cf9822014-10-02 09:38:39 -07002796 }
2797
2798 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -07002799 * Conference two specified connections. Invoked when the user has made a request to merge the
2800 * specified connections into a conference call. In response, the connection service should
2801 * create an instance of {@link Conference} and pass it into {@link #addConference}.
Santos Cordonb6939982014-06-04 20:20:58 -07002802 *
Santos Cordon823fd3c2014-08-07 18:35:18 -07002803 * @param connection1 A connection to merge into a conference call.
2804 * @param connection2 A connection to merge into a conference call.
Santos Cordonb6939982014-06-04 20:20:58 -07002805 */
Santos Cordon823fd3c2014-08-07 18:35:18 -07002806 public void onConference(Connection connection1, Connection connection2) {}
Santos Cordonb6939982014-06-04 20:20:58 -07002807
Santos Cordona663f862014-10-29 13:49:58 -07002808 /**
Pengquan Meng70c9885332017-10-02 18:09:03 -07002809 * Called when a connection is added.
2810 * @hide
2811 */
2812 public void onConnectionAdded(Connection connection) {}
2813
2814 /**
2815 * Called when a connection is removed.
2816 * @hide
2817 */
2818 public void onConnectionRemoved(Connection connection) {}
2819
2820 /**
2821 * Called when a conference is added.
2822 * @hide
2823 */
2824 public void onConferenceAdded(Conference conference) {}
2825
2826 /**
2827 * Called when a conference is removed.
2828 * @hide
2829 */
2830 public void onConferenceRemoved(Conference conference) {}
2831
2832 /**
Santos Cordona663f862014-10-29 13:49:58 -07002833 * Indicates that a remote conference has been created for existing {@link RemoteConnection}s.
2834 * When this method is invoked, this {@link ConnectionService} should create its own
2835 * representation of the conference call and send it to telecom using {@link #addConference}.
2836 * <p>
2837 * This is only relevant to {@link ConnectionService}s which are registered with
2838 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}.
2839 *
2840 * @param conference The remote conference call.
2841 */
Ihab Awadb8e85c72014-08-23 20:34:57 -07002842 public void onRemoteConferenceAdded(RemoteConference conference) {}
2843
Santos Cordon823fd3c2014-08-07 18:35:18 -07002844 /**
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002845 * Called when an existing connection is added remotely.
2846 * @param connection The existing connection which was added.
2847 */
2848 public void onRemoteExistingConnectionAdded(RemoteConnection connection) {}
2849
2850 /**
Pengquan Meng731c1a32017-11-21 18:01:13 -08002851 * Called when the {@link ConnectionService} has lost the call focus.
2852 * The {@link ConnectionService} should release the call resources and invokes
2853 * {@link ConnectionService#connectionServiceFocusReleased()} to inform telecom that it has
2854 * released the call resources.
2855 */
2856 public void onConnectionServiceFocusLost() {}
2857
2858 /**
2859 * Called when the {@link ConnectionService} has gained the call focus. The
2860 * {@link ConnectionService} can acquire the call resources at this time.
2861 */
2862 public void onConnectionServiceFocusGained() {}
2863
2864 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -07002865 * @hide
2866 */
2867 public boolean containsConference(Conference conference) {
2868 return mIdByConference.containsKey(conference);
2869 }
2870
Ihab Awadb8e85c72014-08-23 20:34:57 -07002871 /** {@hide} */
2872 void addRemoteConference(RemoteConference remoteConference) {
2873 onRemoteConferenceAdded(remoteConference);
2874 }
2875
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002876 /** {@hide} */
2877 void addRemoteExistingConnection(RemoteConnection remoteConnection) {
2878 onRemoteExistingConnectionAdded(remoteConnection);
2879 }
2880
Ihab Awad5d0410f2014-07-30 10:07:40 -07002881 private void onAccountsInitialized() {
2882 mAreAccountsInitialized = true;
2883 for (Runnable r : mPreInitializationConnectionRequests) {
2884 r.run();
2885 }
2886 mPreInitializationConnectionRequests.clear();
2887 }
2888
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002889 /**
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002890 * Adds an existing connection to the list of connections, identified by a new call ID unique
2891 * to this connection service.
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002892 *
2893 * @param connection The connection.
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002894 * @return The ID of the connection (e.g. the call-id).
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002895 */
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002896 private String addExistingConnectionInternal(PhoneAccountHandle handle, Connection connection) {
2897 String id;
Tyler Gunncd6ccfd2016-10-17 15:48:19 -07002898
2899 if (connection.getExtras() != null && connection.getExtras()
2900 .containsKey(Connection.EXTRA_ORIGINAL_CONNECTION_ID)) {
2901 id = connection.getExtras().getString(Connection.EXTRA_ORIGINAL_CONNECTION_ID);
2902 Log.d(this, "addExistingConnectionInternal - conn %s reusing original id %s",
2903 connection.getTelecomCallId(), id);
2904 } else if (handle == null) {
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002905 // If no phone account handle was provided, we cannot be sure the call ID is unique,
2906 // so just use a random UUID.
2907 id = UUID.randomUUID().toString();
2908 } else {
2909 // Phone account handle was provided, so use the ConnectionService class name as a
2910 // prefix for a unique incremental call ID.
2911 id = handle.getComponentName().getClassName() + "@" + getNextCallId();
2912 }
Pengquan Meng70c9885332017-10-02 18:09:03 -07002913 addConnection(handle, id, connection);
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07002914 return id;
2915 }
2916
Pengquan Meng70c9885332017-10-02 18:09:03 -07002917 private void addConnection(PhoneAccountHandle handle, String callId, Connection connection) {
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002918 connection.setTelecomCallId(callId);
Ihab Awad542e0ea2014-05-16 10:22:16 -07002919 mConnectionById.put(callId, connection);
2920 mIdByConnection.put(connection, callId);
2921 connection.addConnectionListener(mConnectionListener);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002922 connection.setConnectionService(this);
Pengquan Meng70c9885332017-10-02 18:09:03 -07002923 connection.setPhoneAccountHandle(handle);
2924 onConnectionAdded(connection);
Ihab Awad542e0ea2014-05-16 10:22:16 -07002925 }
2926
Anthony Lee30e65842014-11-06 16:30:53 -08002927 /** {@hide} */
2928 protected void removeConnection(Connection connection) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002929 connection.unsetConnectionService(this);
Ihab Awad542e0ea2014-05-16 10:22:16 -07002930 connection.removeConnectionListener(mConnectionListener);
Chenjie Luoe370b532016-05-12 16:59:43 -07002931 String id = mIdByConnection.get(connection);
2932 if (id != null) {
2933 mConnectionById.remove(id);
2934 mIdByConnection.remove(connection);
2935 mAdapter.removeCall(id);
Pengquan Meng70c9885332017-10-02 18:09:03 -07002936 onConnectionRemoved(connection);
Chenjie Luoe370b532016-05-12 16:59:43 -07002937 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002938 }
2939
Santos Cordon823fd3c2014-08-07 18:35:18 -07002940 private String addConferenceInternal(Conference conference) {
Tyler Gunncd6ccfd2016-10-17 15:48:19 -07002941 String originalId = null;
2942 if (conference.getExtras() != null && conference.getExtras()
2943 .containsKey(Connection.EXTRA_ORIGINAL_CONNECTION_ID)) {
2944 originalId = conference.getExtras().getString(Connection.EXTRA_ORIGINAL_CONNECTION_ID);
2945 Log.d(this, "addConferenceInternal: conf %s reusing original id %s",
2946 conference.getTelecomCallId(),
2947 originalId);
2948 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002949 if (mIdByConference.containsKey(conference)) {
2950 Log.w(this, "Re-adding an existing conference: %s.", conference);
2951 } else if (conference != null) {
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002952 // Conferences do not (yet) have a PhoneAccountHandle associated with them, so we
2953 // cannot determine a ConnectionService class name to associate with the ID, so use
2954 // a unique UUID (for now).
Tyler Gunncd6ccfd2016-10-17 15:48:19 -07002955 String id = originalId == null ? UUID.randomUUID().toString() : originalId;
Santos Cordon823fd3c2014-08-07 18:35:18 -07002956 mConferenceById.put(id, conference);
2957 mIdByConference.put(conference, id);
2958 conference.addListener(mConferenceListener);
2959 return id;
2960 }
2961
2962 return null;
2963 }
2964
2965 private void removeConference(Conference conference) {
2966 if (mIdByConference.containsKey(conference)) {
2967 conference.removeListener(mConferenceListener);
2968
2969 String id = mIdByConference.get(conference);
2970 mConferenceById.remove(id);
2971 mIdByConference.remove(conference);
2972 mAdapter.removeCall(id);
Pengquan Meng70c9885332017-10-02 18:09:03 -07002973
2974 onConferenceRemoved(conference);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002975 }
2976 }
2977
Ihab Awad542e0ea2014-05-16 10:22:16 -07002978 private Connection findConnectionForAction(String callId, String action) {
Tyler Gunn0a88f2e2017-06-16 20:20:34 -07002979 if (callId != null && mConnectionById.containsKey(callId)) {
Ihab Awad542e0ea2014-05-16 10:22:16 -07002980 return mConnectionById.get(callId);
2981 }
Ihab Awad60ac30b2014-05-20 22:32:12 -07002982 Log.w(this, "%s - Cannot find Connection %s", action, callId);
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07002983 return getNullConnection();
2984 }
2985
2986 static synchronized Connection getNullConnection() {
2987 if (sNullConnection == null) {
2988 sNullConnection = new Connection() {};
2989 }
2990 return sNullConnection;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002991 }
Santos Cordon0159ac02014-08-21 14:28:11 -07002992
2993 private Conference findConferenceForAction(String conferenceId, String action) {
2994 if (mConferenceById.containsKey(conferenceId)) {
2995 return mConferenceById.get(conferenceId);
2996 }
2997 Log.w(this, "%s - Cannot find conference %s", action, conferenceId);
2998 return getNullConference();
2999 }
3000
Ihab Awadb8e85c72014-08-23 20:34:57 -07003001 private List<String> createConnectionIdList(List<Connection> connections) {
3002 List<String> ids = new ArrayList<>();
3003 for (Connection c : connections) {
3004 if (mIdByConnection.containsKey(c)) {
3005 ids.add(mIdByConnection.get(c));
3006 }
3007 }
3008 Collections.sort(ids);
3009 return ids;
3010 }
3011
Tyler Gunn6d76ca02014-11-17 15:49:51 -08003012 /**
3013 * Builds a list of {@link Connection} and {@link Conference} IDs based on the list of
Tyler Gunndf2cbc82015-04-20 09:13:01 -07003014 * {@link Conferenceable}s passed in.
Tyler Gunn6d76ca02014-11-17 15:49:51 -08003015 *
Tyler Gunndf2cbc82015-04-20 09:13:01 -07003016 * @param conferenceables The {@link Conferenceable} connections and conferences.
Tyler Gunn6d76ca02014-11-17 15:49:51 -08003017 * @return List of string conference and call Ids.
3018 */
Tyler Gunndf2cbc82015-04-20 09:13:01 -07003019 private List<String> createIdList(List<Conferenceable> conferenceables) {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08003020 List<String> ids = new ArrayList<>();
Tyler Gunndf2cbc82015-04-20 09:13:01 -07003021 for (Conferenceable c : conferenceables) {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08003022 // Only allow Connection and Conference conferenceables.
3023 if (c instanceof Connection) {
3024 Connection connection = (Connection) c;
3025 if (mIdByConnection.containsKey(connection)) {
3026 ids.add(mIdByConnection.get(connection));
3027 }
3028 } else if (c instanceof Conference) {
3029 Conference conference = (Conference) c;
3030 if (mIdByConference.containsKey(conference)) {
3031 ids.add(mIdByConference.get(conference));
3032 }
3033 }
3034 }
3035 Collections.sort(ids);
3036 return ids;
3037 }
3038
Santos Cordon0159ac02014-08-21 14:28:11 -07003039 private Conference getNullConference() {
3040 if (sNullConference == null) {
3041 sNullConference = new Conference(null) {};
3042 }
3043 return sNullConference;
3044 }
Santos Cordon29f2f2e2014-09-11 19:50:24 -07003045
3046 private void endAllConnections() {
3047 // Unbound from telecomm. We should end all connections and conferences.
3048 for (Connection connection : mIdByConnection.keySet()) {
3049 // only operate on top-level calls. Conference calls will be removed on their own.
3050 if (connection.getConference() == null) {
3051 connection.onDisconnect();
3052 }
3053 }
3054 for (Conference conference : mIdByConference.keySet()) {
3055 conference.onDisconnect();
3056 }
3057 }
Tyler Gunnf0500bd2015-09-01 10:59:48 -07003058
3059 /**
3060 * Retrieves the next call ID as maintainted by the connection service.
3061 *
3062 * @return The call ID.
3063 */
3064 private int getNextCallId() {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07003065 synchronized (mIdSyncRoot) {
Tyler Gunnf0500bd2015-09-01 10:59:48 -07003066 return ++mId;
3067 }
3068 }
Brad Ebinger99f17ce2019-09-11 18:06:51 -07003069
3070 /**
3071 * Returns this handler, ONLY FOR TESTING.
3072 * @hide
3073 */
3074 @VisibleForTesting
3075 public Handler getHandler() {
3076 return mHandler;
3077 }
Santos Cordon980acb92014-05-31 10:31:19 -07003078}