blob: 536e458159d17748c5cd8a87c8d31b78e0f574d2 [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
yongnamcha8ec56242022-11-28 06:23:02 +000019import android.annotation.CallbackExecutor;
Tyler Gunn5567d742019-10-31 13:04:37 -070020import android.annotation.NonNull;
21import android.annotation.Nullable;
Roopa Sattiraju45de470c2022-01-27 21:31:35 -080022import android.annotation.RequiresPermission;
Santos Cordon5c6fa952014-07-20 17:47:12 -070023import android.annotation.SdkConstant;
Tyler Gunn5567d742019-10-31 13:04:37 -070024import android.annotation.SystemApi;
Hall Liueb7c9ea2021-03-09 20:24:50 -080025import android.annotation.TestApi;
Sailesh Nepal2a46b902014-07-04 17:21:07 -070026import android.app.Service;
Santos Cordon52d8a152014-06-17 19:08:45 -070027import android.content.ComponentName;
Santos Cordon5c6fa952014-07-20 17:47:12 -070028import android.content.Intent;
yongnamcha8ec56242022-11-28 06:23:02 +000029import android.location.Location;
Ihab Awad542e0ea2014-05-16 10:22:16 -070030import android.net.Uri;
Santos Cordon6b7f9552015-05-27 17:21:45 -070031import android.os.Bundle;
Santos Cordon52d8a152014-06-17 19:08:45 -070032import android.os.Handler;
33import android.os.IBinder;
34import android.os.Looper;
Sailesh Nepal2a46b902014-07-04 17:21:07 -070035import android.os.Message;
Junhoedf3d822022-11-24 09:26:37 +000036import android.os.OutcomeReceiver;
Hall Liub64ac4c2017-02-06 10:49:48 -080037import android.os.ParcelFileDescriptor;
38import android.os.RemoteException;
Brad Ebingerb32d4f82016-10-24 16:40:49 -070039import android.telecom.Logging.Session;
Andrew Lee14185762014-07-25 09:41:56 -070040
Brad Ebinger99f17ce2019-09-11 18:06:51 -070041import com.android.internal.annotations.VisibleForTesting;
Sailesh Nepal2a46b902014-07-04 17:21:07 -070042import com.android.internal.os.SomeArgs;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070043import com.android.internal.telecom.IConnectionService;
44import com.android.internal.telecom.IConnectionServiceAdapter;
45import com.android.internal.telecom.RemoteServiceCallback;
Santos Cordon52d8a152014-06-17 19:08:45 -070046
Ihab Awad5d0410f2014-07-30 10:07:40 -070047import java.util.ArrayList;
Santos Cordonb6939982014-06-04 20:20:58 -070048import java.util.Collection;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070049import java.util.Collections;
Santos Cordon52d8a152014-06-17 19:08:45 -070050import java.util.List;
Ihab Awad542e0ea2014-05-16 10:22:16 -070051import java.util.Map;
Santos Cordon823fd3c2014-08-07 18:35:18 -070052import java.util.UUID;
mike dooley95e80702014-09-18 14:07:52 -070053import java.util.concurrent.ConcurrentHashMap;
Junhoedf3d822022-11-24 09:26:37 +000054import java.util.concurrent.Executor;
Ihab Awad542e0ea2014-05-16 10:22:16 -070055
56/**
Tyler Gunnf5035432017-01-09 09:43:12 -080057 * An abstract service that should be implemented by any apps which either:
58 * <ol>
59 * <li>Can make phone calls (VoIP or otherwise) and want those calls to be integrated into the
60 * built-in phone app. Referred to as a <b>system managed</b> {@link ConnectionService}.</li>
61 * <li>Are a standalone calling app and don't want their calls to be integrated into the
62 * built-in phone app. Referred to as a <b>self managed</b> {@link ConnectionService}.</li>
63 * </ol>
64 * Once implemented, the {@link ConnectionService} needs to take the following steps so that Telecom
65 * will bind to it:
Santos Cordona663f862014-10-29 13:49:58 -070066 * <p>
67 * 1. <i>Registration in AndroidManifest.xml</i>
68 * <br/>
69 * <pre>
70 * &lt;service android:name="com.example.package.MyConnectionService"
71 * android:label="@string/some_label_for_my_connection_service"
Yorke Lee249c12e2015-05-13 15:59:29 -070072 * android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"&gt;
Santos Cordona663f862014-10-29 13:49:58 -070073 * &lt;intent-filter&gt;
74 * &lt;action android:name="android.telecom.ConnectionService" /&gt;
75 * &lt;/intent-filter&gt;
76 * &lt;/service&gt;
77 * </pre>
78 * <p>
79 * 2. <i> Registration of {@link PhoneAccount} with {@link TelecomManager}.</i>
80 * <br/>
81 * See {@link PhoneAccount} and {@link TelecomManager#registerPhoneAccount} for more information.
82 * <p>
Tyler Gunnf5035432017-01-09 09:43:12 -080083 * System managed {@link ConnectionService}s must be enabled by the user in the phone app settings
Tyler Gunn8eeb94f2023-01-20 22:46:19 +000084 * before Telecom will bind to them. Self-managed {@link ConnectionService}s must declare the
85 * {@link android.Manifest.permission#MANAGE_OWN_CALLS} permission in their manifest before Telecom
86 * will bind to them.
Tyler Gunnf5035432017-01-09 09:43:12 -080087 * <p>
88 * Once registered and enabled by the user in the phone app settings or granted permission, telecom
89 * will bind to a {@link ConnectionService} implementation when it wants that
90 * {@link ConnectionService} to place a call or the service has indicated that is has an incoming
Tyler Gunn8eeb94f2023-01-20 22:46:19 +000091 * call through {@link TelecomManager#addNewIncomingCall(PhoneAccountHandle, Bundle)}. The
92 * {@link ConnectionService} can then expect a call to
93 * {@link #onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)} or
94 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
Tyler Gunnf5035432017-01-09 09:43:12 -080095 * wherein it should provide a new instance of a {@link Connection} object. It is through this
96 * {@link Connection} object that telecom receives state updates and the {@link ConnectionService}
Santos Cordona663f862014-10-29 13:49:58 -070097 * receives call-commands such as answer, reject, hold and disconnect.
98 * <p>
Tyler Gunnf5035432017-01-09 09:43:12 -080099 * When there are no more live calls, telecom will unbind from the {@link ConnectionService}.
Tyler Gunn8eeb94f2023-01-20 22:46:19 +0000100 * <p>
101 * <h1>Self-Managed Connection Services</h1>
102 * A VoIP app can implement a {@link ConnectionService} to ensure that its calls are integrated
103 * into the Android platform. There are numerous benefits to using the Telecom APIs for a VoIP app:
104 * <ul>
105 * <li>Call concurrency is handled - the user is able to swap between calls in different
106 * apps and on the mobile network.</li>
107 * <li>Simplified audio routing - the platform provides your app with a unified list of the
108 * audio routes which are available
109 * (e.g. {@link android.telecom.Connection#onAvailableCallEndpointsChanged(List)}) and a
110 * standardized way to switch audio routes
111 * (e.g. {@link android.telecom.Connection#requestCallEndpointChange(CallEndpoint, Executor,
112 * OutcomeReceiver)} ).</li>
113 * <li>Bluetooth integration - your calls will be visible on and controllable via
114 * bluetooth devices (e.g. car head units and headsets).</li>
115 * <li>Companion device integration - wearable devices such as watches which implement an
116 * {@link InCallService} can optionally subscribe to see self-managed calls. Similar to a
117 * bluetooth headunit, wearables will typically render your call using a generic call UX and
118 * provide the user with basic call controls such as hangup, answer, reject.</li>
119 * <li>Automotive calling experiences - Android supports automotive optimized experiences which
120 * provides a means for calls to be controlled and viewed in an automobile; these experiences
121 * are capable of leveraging call metadata provided by your app.</li>
122 * </ul>
123 * <h2>Registering a Phone Account</h2>
124 * Before your app can handle incoming or outgoing calls through Telecom it needs to register a
125 * {@link PhoneAccount} with Telecom indicating to the platform that your app is capable of calling.
126 * <p>
127 * Your app should create a new instance of {@link PhoneAccount} which meets the following
128 * requirements:
129 * <ul>
130 * <li>Has {@link PhoneAccount#CAPABILITY_SELF_MANAGED} (set using
131 * {@link PhoneAccount.Builder#setCapabilities(int)}). This indicates to Telecom that your
132 * app will report calls but that it provides a primary UI for the calls by itself.</li>
133 * <li>Provide a unique identifier for the {@link PhoneAccount} via the
134 * {@link PhoneAccountHandle#getId()} attribute. As per the {@link PhoneAccountHandle}
135 * documentation, you should NOT use an identifier which contains PII or other sensitive
136 * information. A typical choice is a UUID.</li>
137 * </ul>
138 * Your app should register the new {@link PhoneAccount} with Telecom using
139 * {@link TelecomManager#registerPhoneAccount(PhoneAccount)}. {@link PhoneAccount}s persist across
140 * reboot. You can use {@link TelecomManager#getOwnSelfManagedPhoneAccounts()} to confirm the
141 * {@link PhoneAccount} you registered. Your app should generally only register a single
142 * {@link PhoneAccount}.
143 *
144 * <h2>Implementing ConnectionService</h2>
145 * Your app uses {@link TelecomManager#placeCall(Uri, Bundle)} to start new outgoing calls and
146 * {@link TelecomManager#addNewIncomingCall(PhoneAccountHandle, Bundle)} to report new incoming
147 * calls. Calling these APIs causes the Telecom stack to bind to your app's
148 * {@link ConnectionService} implementation. Telecom will either inform your app that it cannot
149 * handle a call request at the current time (i.e. there could be an ongoing emergency call, which
150 * means your app is not allowed to handle calls at the current time), or it will ask your app to
151 * create a new instance of {@link Connection} to represent a call in your app.
152 *
153 * Your app should implement the following {@link ConnectionService} methods:
154 * <ul>
155 * <li>{@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle,
156 * ConnectionRequest)} - called by Telecom to ask your app to make a new {@link Connection}
157 * to represent an outgoing call your app requested via
158 * {@link TelecomManager#placeCall(Uri, Bundle)}.</li>
159 * <li><{@link ConnectionService#onCreateOutgoingConnectionFailed(PhoneAccountHandle,
160 * ConnectionRequest)} - called by Telecom to inform your app that a call it reported via
161 * {@link TelecomManager#placeCall(Uri, Bundle)} cannot be handled at this time. Your app
162 * should NOT place a call at the current time.</li>
163 * <li>{@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle,
164 * ConnectionRequest)} - called by Telecom to ask your app to make a new {@link Connection}
165 * to represent an incoming call your app reported via
166 * {@link TelecomManager#addNewIncomingCall(PhoneAccountHandle, Bundle)}.</li>
167 * <li>{@link ConnectionService#onCreateIncomingConnectionFailed(PhoneAccountHandle,
168 * ConnectionRequest)} - called by Telecom to inform your app that an incoming call it reported
169 * via {@link TelecomManager#addNewIncomingCall(PhoneAccountHandle, Bundle)} cannot be handled
170 * at this time. Your app should NOT post a new incoming call notification and should silently
171 * reject the call.</li>
172 * </ul>
173 *
174 * <h2>Implementing a Connection</h2>
175 * Your app should extend the {@link Connection} class to represent calls in your app. When you
176 * create new instances of your {@link Connection}, you should ensure the following properties are
177 * set on the new {@link Connection} instance returned by your {@link ConnectionService}:
178 * <ul>
179 * <li>{@link Connection#setAddress(Uri, int)} - the identifier for the other party. For
180 * apps that user phone numbers the {@link Uri} can be a {@link PhoneAccount#SCHEME_TEL} URI
181 * representing the phone number.</li>
182 * <li>{@link Connection#setCallerDisplayName(String, int)} - the display name of the other
183 * party. This is what will be shown on Bluetooth devices and other calling surfaces such
184 * as wearable devices. This is particularly important for calls that do not use a phone
185 * number to identify the caller or called party.</li>
186 * <li>{@link Connection#setConnectionProperties(int)} - ensure you set
187 * {@link Connection#PROPERTY_SELF_MANAGED} to identify to the platform that the call is
188 * handled by your app.</li>
189 * <li>{@link Connection#setConnectionCapabilities(int)} - if your app supports making calls
190 * inactive (i.e. holding calls) you should get {@link Connection#CAPABILITY_SUPPORT_HOLD} and
191 * {@link Connection#CAPABILITY_HOLD} to indicate to the platform that you calls can potentially
192 * be held for concurrent calling scenarios.</li>
193 * <li>{@link Connection#setAudioModeIsVoip(boolean)} - set to {@code true} to ensure that the
194 * platform knows your call is a VoIP call.</li>
195 * <li>For newly created {@link Connection} instances, do NOT change the state of your call
196 * using {@link Connection#setActive()}, {@link Connection#setOnHold()} until the call is added
197 * to Telecom (ie you have returned it via
198 * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
199 * or
200 * {@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}).
201 * </li>
202 * </ul>
203 *
204 * <h2>How to Place Outgoing Calls</h2>
205 * When your app wants to place an outgoing call it calls
206 * {@link TelecomManager#placeCall(Uri, Bundle)}. You should specify a {@link Uri} to identify
207 * who the call is being placed to, and specify the {@link PhoneAccountHandle} associated with the
208 * {@link PhoneAccount} you registered for your app using
209 * {@link TelecomManager#EXTRA_PHONE_ACCOUNT_HANDLE} in the {@link Bundle} parameter.
210 * <p>
211 * Telecom will bind to your app's {@link ConnectionService} implementation and call either:
212 * <ul>
213 * <li>{@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle,
214 * ConnectionRequest)} - the {@link ConnectionRequest#getAddress()} will match the address
215 * you specified when placing the call. You should return a new instance of your app's
216 * {@link Connection} class to represent the outgoing call.</li>
217 * <li>{@link ConnectionService#onCreateOutgoingConnectionFailed(PhoneAccountHandle,
218 * ConnectionRequest)} - your app should not place the call at this time; the call should be
219 * cancelled and the user informed that the call cannot be placed.</li>
220 * </ul>
221 * <p>
222 * New outgoing calls will start in a {@link Connection#STATE_DIALING} state. This state indicates
223 * that your app is in the process of connecting the call to the other party.
224 * <p>
225 * Once the other party answers the call (or it is set up successfully), your app should call
226 * {@link Connection#setActive()} to inform Telecom that the call is now active.
227 *
228 * <h2>How to Add Incoming Calls</h2>
229 * When your app receives an incoming call, it should call
230 * {@link TelecomManager#addNewIncomingCall(PhoneAccountHandle, Bundle)}. Set the
231 * {@link PhoneAccountHandle} parameter to the {@link PhoneAccountHandle} associated with your
232 * app's {@link PhoneAccount}.
233 * <p>
234 * Telecom will bind to your app's {@link ConnectionService} implementation and call either:
235 * <ul>
236 * <li>{@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle,
237 * ConnectionRequest)} - You should return a new instance of your app's
238 * {@link Connection} class to represent the incoming call.</li>
239 * <li>{@link ConnectionService#onCreateIncomingConnectionFailed(PhoneAccountHandle,
240 * ConnectionRequest)} - your app should not receive the call at this time; the call should be
241 * rejected silently; the user may be informed of a missed call.</li>
242 * </ul>
243 * <p>
244 * New incoming calls will start with a {@link Connection#STATE_RINGING} state. This state
245 * indicates that your app has a new incoming call pending. Telecom will NOT play a ringtone or
246 * post a notification for your app. It is up to your app to post an incoming call notification
247 * with an associated ringtone. Telecom will call {@link Connection#onShowIncomingCallUi()} on the
248 * {@link Connection} when your app can post its incoming call notification. See
249 * {@link Connection#onShowIncomingCallUi() the docs} for more information on how to post the
250 * notification.
251 * <p>
252 * Your incoming call notification (or full screen UI) will typically have an "answer" and "decline"
253 * action which the user chooses. When your app receives the "answer" or "decline"
254 * {@link android.app.PendingIntent}, you should must call either {@link Connection#setActive()} to
255 * inform Telecom that the call was answered, or
256 * {@link Connection#setDisconnected(DisconnectCause)} to inform Telecom that the call was rejected.
257 * If the call was rejected, supply an instance of {@link DisconnectCause} with
258 * {@link DisconnectCause#REJECTED}, and then call {@link Connection#destroy()}.
259 * <p>
260 * In addition to handling requests to answer or decline the call via notification actions, your
261 * app should also be implement the {@link Connection#onAnswer(int)} and
262 * {@link Connection#onAnswer()} methods on the {@link Connection}. These will be raised if the
263 * user answers your call via a Bluetooth device or another device like a wearable or automotive
264 * calling UX. In response, your app should call {@link Connection#setActive()} to inform Telecom
265 * that the call was answered.
266 * <p>
267 * Additionally, your app should implement {@link Connection#onReject()} to handle requests to
268 * reject the call which are raised via Bluetooth or other calling surfaces. Your app should call
269 * {@link Connection#setDisconnected(DisconnectCause)} and supply an instance of
270 * {@link DisconnectCause} with {@link DisconnectCause#REJECTED} in this case.
271 *
272 * <h2>Ending Calls</h2>
273 * When an ongoing active call (incoming or outgoing) has ended, your app is responsible for
274 * informing Telecom that the call ended.
275 * <p>
276 * Your app calls:
277 * <ul>
278 * <li>{@link Connection#setDisconnected(DisconnectCause)} - this informs Telecom that the
279 * call has terminated. You should provide a new instance of {@link DisconnectCause} with
280 * either {@link DisconnectCause#LOCAL} or {@link DisconnectCause#REMOTE} to indicate where the
281 * call disconnection took place. {@link DisconnectCause#LOCAL} indicates that the call
282 * terminated in your app on the current device (i.e. via user action), where
283 * {@link DisconnectCause#REMOTE} indicates that the call terminates on the remote device.</li>
284 * <li>{@link Connection#destroy()} - this informs Telecom that your call instance can be
285 * cleaned up. You should always call this when you are finished with a call.</li>
286 * </ul>
287 * <p>
288 * Similar to answering incoming calls, requests to disconnect your call may originate from outside
289 * your app. You can handle these by implementing {@link Connection#onDisconnect()}. Your app
290 * should call {@link Connection#setDisconnected(DisconnectCause)} with an instance of
291 * {@link DisconnectCause} and reason {@link DisconnectCause#LOCAL} to indicate to Telecom that your
292 * app has disconnected the call as requested based on the user's request.
293 *
294 * <h2>Holding and Unholding Calls</h2>
295 * When your app specifies {@link Connection#CAPABILITY_SUPPORT_HOLD} and
296 * {@link Connection#CAPABILITY_HOLD} on your {@link Connection} instance, it is telling Telecom
297 * that your calls can be placed into a suspended, or "held" state if required. If your app
298 * supports holding its calls, it will be possible for the user to switch between calls in your app
299 * and holdable calls in another app or on the mobile network. If your app does not support
300 * holding its calls, you may receive a request to disconnect the call from Telecom if the user
301 * opts to answer an incoming call in another app or on the mobile network; this ensures that the
302 * user can only be in one call at a time.
303 * <p>
304 * Your app is free to change a call between the held and active state using
305 * {@link Connection#setOnHold()} and {@link Connection#setActive()}.
306 * <p>
307 * Your app may receive a request from Telecom to hold or unhold a call via
308 * {@link Connection#onHold()} and {@link Connection#onUnhold()}. Telecom can ask your app to
309 * hold or unhold its {@link Connection} either if the user requests this action through another
310 * calling surface such as Bluetooth, or if the user answers or switches to a call in a different
311 * app or on the mobile network.
312 * <p>
313 * When your app receives an {@link Connection#onHold()} it must call {@link Connection#setOnHold()}
314 * to inform Telecom that the call has been held successfully.
315 * <p>
316 * When your app receives an {@link Connection#onUnhold()} it must call
317 * {@link Connection#setActive()} to inform Telecom that the call has been resumed successfully.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700318 */
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700319public abstract class ConnectionService extends Service {
Santos Cordon5c6fa952014-07-20 17:47:12 -0700320 /**
321 * The {@link Intent} that must be declared as handled by the service.
322 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700323 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700324 public static final String SERVICE_INTERFACE = "android.telecom.ConnectionService";
Santos Cordon5c6fa952014-07-20 17:47:12 -0700325
Tyler Gunn8bf76572017-04-06 15:30:08 -0700326 /**
327 * Boolean extra used by Telecom to inform a {@link ConnectionService} that the purpose of it
328 * being asked to create a new outgoing {@link Connection} is to perform a handover of an
329 * ongoing call on the device from another {@link PhoneAccount}/{@link ConnectionService}. Will
330 * be specified in the {@link ConnectionRequest#getExtras()} passed by Telecom when
331 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)} is called.
332 * <p>
Tyler Gunn727c6bd2017-04-11 09:51:40 -0700333 * When your {@link ConnectionService} receives this extra, it should communicate the fact that
334 * this is a handover to the other device's matching {@link ConnectionService}. That
Tyler Gunn8bf76572017-04-06 15:30:08 -0700335 * {@link ConnectionService} will continue the handover using
336 * {@link TelecomManager#addNewIncomingCall(PhoneAccountHandle, Bundle)}, specifying
Tyler Gunn727c6bd2017-04-11 09:51:40 -0700337 * {@link TelecomManager#EXTRA_IS_HANDOVER}. Telecom will match the phone numbers of the
338 * handover call on the other device with ongoing calls for {@link ConnectionService}s which
339 * support {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700340 * @hide
341 */
342 public static final String EXTRA_IS_HANDOVER = TelecomManager.EXTRA_IS_HANDOVER;
343
Ihab Awad542e0ea2014-05-16 10:22:16 -0700344 // Flag controlling whether PII is emitted into the logs
Ihab Awad60ac30b2014-05-20 22:32:12 -0700345 private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700346
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700347 // Session Definitions
348 private static final String SESSION_HANDLER = "H.";
349 private static final String SESSION_ADD_CS_ADAPTER = "CS.aCSA";
350 private static final String SESSION_REMOVE_CS_ADAPTER = "CS.rCSA";
351 private static final String SESSION_CREATE_CONN = "CS.crCo";
Tyler Gunn041a1fe2017-05-12 10:04:49 -0700352 private static final String SESSION_CREATE_CONN_COMPLETE = "CS.crCoC";
Tyler Gunn44e01912017-01-31 10:49:05 -0800353 private static final String SESSION_CREATE_CONN_FAILED = "CS.crCoF";
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700354 private static final String SESSION_ABORT = "CS.ab";
355 private static final String SESSION_ANSWER = "CS.an";
356 private static final String SESSION_ANSWER_VIDEO = "CS.anV";
Pooja Jaind34698d2017-12-28 14:15:31 +0530357 private static final String SESSION_DEFLECT = "CS.def";
Ravi Palurif4b38e72020-02-05 12:35:41 +0530358 private static final String SESSION_TRANSFER = "CS.trans";
359 private static final String SESSION_CONSULTATIVE_TRANSFER = "CS.cTrans";
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700360 private static final String SESSION_REJECT = "CS.r";
361 private static final String SESSION_REJECT_MESSAGE = "CS.rWM";
362 private static final String SESSION_SILENCE = "CS.s";
363 private static final String SESSION_DISCONNECT = "CS.d";
364 private static final String SESSION_HOLD = "CS.h";
365 private static final String SESSION_UNHOLD = "CS.u";
366 private static final String SESSION_CALL_AUDIO_SC = "CS.cASC";
Grace Jiae99fde92021-01-19 14:58:01 -0800367 private static final String SESSION_USING_ALTERNATIVE_UI = "CS.uAU";
368 private static final String SESSION_TRACKED_BY_NON_UI_SERVICE = "CS.tBNUS";
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700369 private static final String SESSION_PLAY_DTMF = "CS.pDT";
370 private static final String SESSION_STOP_DTMF = "CS.sDT";
371 private static final String SESSION_CONFERENCE = "CS.c";
372 private static final String SESSION_SPLIT_CONFERENCE = "CS.sFC";
373 private static final String SESSION_MERGE_CONFERENCE = "CS.mC";
374 private static final String SESSION_SWAP_CONFERENCE = "CS.sC";
Ravi Paluri404babb2020-01-23 19:02:44 +0530375 private static final String SESSION_ADD_PARTICIPANT = "CS.aP";
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700376 private static final String SESSION_POST_DIAL_CONT = "CS.oPDC";
377 private static final String SESSION_PULL_EXTERNAL_CALL = "CS.pEC";
378 private static final String SESSION_SEND_CALL_EVENT = "CS.sCE";
Hall Liu49cabcc2021-01-15 11:41:48 -0800379 private static final String SESSION_CALL_FILTERING_COMPLETED = "CS.oCFC";
Tyler Gunn79bc1ec2018-01-22 15:17:54 -0800380 private static final String SESSION_HANDOVER_COMPLETE = "CS.hC";
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700381 private static final String SESSION_EXTRAS_CHANGED = "CS.oEC";
Hall Liub64ac4c2017-02-06 10:49:48 -0800382 private static final String SESSION_START_RTT = "CS.+RTT";
Hall Liua549fed2018-02-09 16:40:03 -0800383 private static final String SESSION_UPDATE_RTT_PIPES = "CS.uRTT";
Hall Liub64ac4c2017-02-06 10:49:48 -0800384 private static final String SESSION_STOP_RTT = "CS.-RTT";
385 private static final String SESSION_RTT_UPGRADE_RESPONSE = "CS.rTRUR";
Pengquan Meng731c1a32017-11-21 18:01:13 -0800386 private static final String SESSION_CONNECTION_SERVICE_FOCUS_LOST = "CS.cSFL";
387 private static final String SESSION_CONNECTION_SERVICE_FOCUS_GAINED = "CS.cSFG";
Sanket Padawe4cc8ed52017-12-04 16:22:20 -0800388 private static final String SESSION_HANDOVER_FAILED = "CS.haF";
Ravi Paluri80aa2142019-12-02 11:57:37 +0530389 private static final String SESSION_CREATE_CONF = "CS.crConf";
390 private static final String SESSION_CREATE_CONF_COMPLETE = "CS.crConfC";
391 private static final String SESSION_CREATE_CONF_FAILED = "CS.crConfF";
Junhoedf3d822022-11-24 09:26:37 +0000392 private static final String SESSION_CALL_ENDPOINT_CHANGED = "CS.oCEC";
393 private static final String SESSION_AVAILABLE_CALL_ENDPOINTS_CHANGED = "CS.oACEC";
394 private static final String SESSION_MUTE_STATE_CHANGED = "CS.oMSC";
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700395
Ihab Awad8aecfed2014-08-08 17:06:11 -0700396 private static final int MSG_ADD_CONNECTION_SERVICE_ADAPTER = 1;
Sailesh Nepalc5b01572014-07-14 16:29:44 -0700397 private static final int MSG_CREATE_CONNECTION = 2;
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700398 private static final int MSG_ABORT = 3;
Sailesh Nepalc5b01572014-07-14 16:29:44 -0700399 private static final int MSG_ANSWER = 4;
400 private static final int MSG_REJECT = 5;
401 private static final int MSG_DISCONNECT = 6;
402 private static final int MSG_HOLD = 7;
403 private static final int MSG_UNHOLD = 8;
Yorke Lee4af59352015-05-13 14:14:54 -0700404 private static final int MSG_ON_CALL_AUDIO_STATE_CHANGED = 9;
Sailesh Nepalc5b01572014-07-14 16:29:44 -0700405 private static final int MSG_PLAY_DTMF_TONE = 10;
406 private static final int MSG_STOP_DTMF_TONE = 11;
407 private static final int MSG_CONFERENCE = 12;
408 private static final int MSG_SPLIT_FROM_CONFERENCE = 13;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700409 private static final int MSG_ON_POST_DIAL_CONTINUE = 14;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700410 private static final int MSG_REMOVE_CONNECTION_SERVICE_ADAPTER = 16;
Tyler Gunnbe74de02014-08-29 14:51:48 -0700411 private static final int MSG_ANSWER_VIDEO = 17;
Santos Cordona4868042014-09-04 17:39:22 -0700412 private static final int MSG_MERGE_CONFERENCE = 18;
413 private static final int MSG_SWAP_CONFERENCE = 19;
Bryce Lee81901682015-08-28 16:38:02 -0700414 private static final int MSG_REJECT_WITH_MESSAGE = 20;
Bryce Leecac50772015-11-17 15:13:29 -0800415 private static final int MSG_SILENCE = 21;
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700416 private static final int MSG_PULL_EXTERNAL_CALL = 22;
417 private static final int MSG_SEND_CALL_EVENT = 23;
Tyler Gunndee56a82016-03-23 16:06:34 -0700418 private static final int MSG_ON_EXTRAS_CHANGED = 24;
Tyler Gunn44e01912017-01-31 10:49:05 -0800419 private static final int MSG_CREATE_CONNECTION_FAILED = 25;
Hall Liub64ac4c2017-02-06 10:49:48 -0800420 private static final int MSG_ON_START_RTT = 26;
421 private static final int MSG_ON_STOP_RTT = 27;
422 private static final int MSG_RTT_UPGRADE_RESPONSE = 28;
Tyler Gunn041a1fe2017-05-12 10:04:49 -0700423 private static final int MSG_CREATE_CONNECTION_COMPLETE = 29;
Pengquan Meng731c1a32017-11-21 18:01:13 -0800424 private static final int MSG_CONNECTION_SERVICE_FOCUS_LOST = 30;
425 private static final int MSG_CONNECTION_SERVICE_FOCUS_GAINED = 31;
Sanket Padawe4cc8ed52017-12-04 16:22:20 -0800426 private static final int MSG_HANDOVER_FAILED = 32;
Tyler Gunn79bc1ec2018-01-22 15:17:54 -0800427 private static final int MSG_HANDOVER_COMPLETE = 33;
Pooja Jaind34698d2017-12-28 14:15:31 +0530428 private static final int MSG_DEFLECT = 34;
Ravi Paluri80aa2142019-12-02 11:57:37 +0530429 private static final int MSG_CREATE_CONFERENCE = 35;
430 private static final int MSG_CREATE_CONFERENCE_COMPLETE = 36;
431 private static final int MSG_CREATE_CONFERENCE_FAILED = 37;
Tyler Gunnfacfdee2020-01-23 13:10:37 -0800432 private static final int MSG_REJECT_WITH_REASON = 38;
Ravi Paluri404babb2020-01-23 19:02:44 +0530433 private static final int MSG_ADD_PARTICIPANT = 39;
Ravi Palurif4b38e72020-02-05 12:35:41 +0530434 private static final int MSG_EXPLICIT_CALL_TRANSFER = 40;
435 private static final int MSG_EXPLICIT_CALL_TRANSFER_CONSULTATIVE = 41;
Hall Liu49cabcc2021-01-15 11:41:48 -0800436 private static final int MSG_ON_CALL_FILTERING_COMPLETED = 42;
Grace Jiae99fde92021-01-19 14:58:01 -0800437 private static final int MSG_ON_USING_ALTERNATIVE_UI = 43;
438 private static final int MSG_ON_TRACKED_BY_NON_UI_SERVICE = 44;
Junhoedf3d822022-11-24 09:26:37 +0000439 private static final int MSG_ON_CALL_ENDPOINT_CHANGED = 45;
440 private static final int MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED = 46;
441 private static final int MSG_ON_MUTE_STATE_CHANGED = 47;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700442
Sailesh Nepalcf7020b2014-08-20 10:07:19 -0700443 private static Connection sNullConnection;
444
mike dooley95e80702014-09-18 14:07:52 -0700445 private final Map<String, Connection> mConnectionById = new ConcurrentHashMap<>();
446 private final Map<Connection, String> mIdByConnection = new ConcurrentHashMap<>();
447 private final Map<String, Conference> mConferenceById = new ConcurrentHashMap<>();
448 private final Map<Conference, String> mIdByConference = new ConcurrentHashMap<>();
Ihab Awadb8e85c72014-08-23 20:34:57 -0700449 private final RemoteConnectionManager mRemoteConnectionManager =
450 new RemoteConnectionManager(this);
Ihab Awad5d0410f2014-07-30 10:07:40 -0700451 private final List<Runnable> mPreInitializationConnectionRequests = new ArrayList<>();
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700452 private final ConnectionServiceAdapter mAdapter = new ConnectionServiceAdapter();
Ihab Awad542e0ea2014-05-16 10:22:16 -0700453
Santos Cordon823fd3c2014-08-07 18:35:18 -0700454 private boolean mAreAccountsInitialized = false;
Santos Cordon0159ac02014-08-21 14:28:11 -0700455 private Conference sNullConference;
Tyler Gunnf0500bd2015-09-01 10:59:48 -0700456 private Object mIdSyncRoot = new Object();
457 private int mId = 0;
Santos Cordon823fd3c2014-08-07 18:35:18 -0700458
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700459 private final IBinder mBinder = new IConnectionService.Stub() {
460 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700461 public void addConnectionServiceAdapter(IConnectionServiceAdapter adapter,
462 Session.Info sessionInfo) {
463 Log.startSession(sessionInfo, SESSION_ADD_CS_ADAPTER);
464 try {
465 SomeArgs args = SomeArgs.obtain();
466 args.arg1 = adapter;
467 args.arg2 = Log.createSubsession();
468 mHandler.obtainMessage(MSG_ADD_CONNECTION_SERVICE_ADAPTER, args).sendToTarget();
469 } finally {
470 Log.endSession();
471 }
Ihab Awad8aecfed2014-08-08 17:06:11 -0700472 }
473
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700474 public void removeConnectionServiceAdapter(IConnectionServiceAdapter adapter,
475 Session.Info sessionInfo) {
476 Log.startSession(sessionInfo, SESSION_REMOVE_CS_ADAPTER);
477 try {
478 SomeArgs args = SomeArgs.obtain();
479 args.arg1 = adapter;
480 args.arg2 = Log.createSubsession();
481 mHandler.obtainMessage(MSG_REMOVE_CONNECTION_SERVICE_ADAPTER, args).sendToTarget();
482 } finally {
483 Log.endSession();
484 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700485 }
486
487 @Override
Ihab Awadf8b69882014-07-25 15:14:01 -0700488 public void createConnection(
489 PhoneAccountHandle connectionManagerPhoneAccount,
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700490 String id,
Ihab Awadf8b69882014-07-25 15:14:01 -0700491 ConnectionRequest request,
Yorke Leec3cf9822014-10-02 09:38:39 -0700492 boolean isIncoming,
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700493 boolean isUnknown,
494 Session.Info sessionInfo) {
495 Log.startSession(sessionInfo, SESSION_CREATE_CONN);
496 try {
497 SomeArgs args = SomeArgs.obtain();
498 args.arg1 = connectionManagerPhoneAccount;
499 args.arg2 = id;
500 args.arg3 = request;
501 args.arg4 = Log.createSubsession();
502 args.argi1 = isIncoming ? 1 : 0;
503 args.argi2 = isUnknown ? 1 : 0;
504 mHandler.obtainMessage(MSG_CREATE_CONNECTION, args).sendToTarget();
505 } finally {
506 Log.endSession();
507 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700508 }
509
510 @Override
Tyler Gunn041a1fe2017-05-12 10:04:49 -0700511 public void createConnectionComplete(String id, Session.Info sessionInfo) {
512 Log.startSession(sessionInfo, SESSION_CREATE_CONN_COMPLETE);
513 try {
514 SomeArgs args = SomeArgs.obtain();
515 args.arg1 = id;
516 args.arg2 = Log.createSubsession();
517 mHandler.obtainMessage(MSG_CREATE_CONNECTION_COMPLETE, args).sendToTarget();
518 } finally {
519 Log.endSession();
520 }
521 }
522
523 @Override
Tyler Gunn44e01912017-01-31 10:49:05 -0800524 public void createConnectionFailed(
Tyler Gunn159f35c2017-03-02 09:28:37 -0800525 PhoneAccountHandle connectionManagerPhoneAccount,
Tyler Gunn44e01912017-01-31 10:49:05 -0800526 String callId,
527 ConnectionRequest request,
528 boolean isIncoming,
529 Session.Info sessionInfo) {
530 Log.startSession(sessionInfo, SESSION_CREATE_CONN_FAILED);
531 try {
532 SomeArgs args = SomeArgs.obtain();
533 args.arg1 = callId;
534 args.arg2 = request;
535 args.arg3 = Log.createSubsession();
Tyler Gunn159f35c2017-03-02 09:28:37 -0800536 args.arg4 = connectionManagerPhoneAccount;
Tyler Gunn44e01912017-01-31 10:49:05 -0800537 args.argi1 = isIncoming ? 1 : 0;
538 mHandler.obtainMessage(MSG_CREATE_CONNECTION_FAILED, args).sendToTarget();
539 } finally {
540 Log.endSession();
541 }
542 }
543
544 @Override
Ravi Paluri80aa2142019-12-02 11:57:37 +0530545 public void createConference(
546 PhoneAccountHandle connectionManagerPhoneAccount,
547 String id,
548 ConnectionRequest request,
549 boolean isIncoming,
550 boolean isUnknown,
551 Session.Info sessionInfo) {
552 Log.startSession(sessionInfo, SESSION_CREATE_CONF);
553 try {
554 SomeArgs args = SomeArgs.obtain();
555 args.arg1 = connectionManagerPhoneAccount;
556 args.arg2 = id;
557 args.arg3 = request;
558 args.arg4 = Log.createSubsession();
559 args.argi1 = isIncoming ? 1 : 0;
560 args.argi2 = isUnknown ? 1 : 0;
561 mHandler.obtainMessage(MSG_CREATE_CONFERENCE, args).sendToTarget();
562 } finally {
563 Log.endSession();
564 }
565 }
566
567 @Override
568 public void createConferenceComplete(String id, Session.Info sessionInfo) {
569 Log.startSession(sessionInfo, SESSION_CREATE_CONF_COMPLETE);
570 try {
571 SomeArgs args = SomeArgs.obtain();
572 args.arg1 = id;
573 args.arg2 = Log.createSubsession();
574 mHandler.obtainMessage(MSG_CREATE_CONFERENCE_COMPLETE, args).sendToTarget();
575 } finally {
576 Log.endSession();
577 }
578 }
579
580 @Override
581 public void createConferenceFailed(
582 PhoneAccountHandle connectionManagerPhoneAccount,
583 String callId,
584 ConnectionRequest request,
585 boolean isIncoming,
586 Session.Info sessionInfo) {
587 Log.startSession(sessionInfo, SESSION_CREATE_CONF_FAILED);
588 try {
589 SomeArgs args = SomeArgs.obtain();
590 args.arg1 = callId;
591 args.arg2 = request;
592 args.arg3 = Log.createSubsession();
593 args.arg4 = connectionManagerPhoneAccount;
594 args.argi1 = isIncoming ? 1 : 0;
595 mHandler.obtainMessage(MSG_CREATE_CONFERENCE_FAILED, args).sendToTarget();
596 } finally {
597 Log.endSession();
598 }
599 }
600
601 @Override
Sanket Padawe4cc8ed52017-12-04 16:22:20 -0800602 public void handoverFailed(String callId, ConnectionRequest request, int reason,
603 Session.Info sessionInfo) {
604 Log.startSession(sessionInfo, SESSION_HANDOVER_FAILED);
605 try {
606 SomeArgs args = SomeArgs.obtain();
607 args.arg1 = callId;
608 args.arg2 = request;
609 args.arg3 = Log.createSubsession();
610 args.arg4 = reason;
611 mHandler.obtainMessage(MSG_HANDOVER_FAILED, args).sendToTarget();
612 } finally {
613 Log.endSession();
614 }
615 }
616
617 @Override
Tyler Gunn79bc1ec2018-01-22 15:17:54 -0800618 public void handoverComplete(String callId, Session.Info sessionInfo) {
619 Log.startSession(sessionInfo, SESSION_HANDOVER_COMPLETE);
620 try {
621 SomeArgs args = SomeArgs.obtain();
622 args.arg1 = callId;
623 args.arg2 = Log.createSubsession();
624 mHandler.obtainMessage(MSG_HANDOVER_COMPLETE, args).sendToTarget();
625 } finally {
626 Log.endSession();
627 }
628 }
629
630 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700631 public void abort(String callId, Session.Info sessionInfo) {
632 Log.startSession(sessionInfo, SESSION_ABORT);
633 try {
634 SomeArgs args = SomeArgs.obtain();
635 args.arg1 = callId;
636 args.arg2 = Log.createSubsession();
637 mHandler.obtainMessage(MSG_ABORT, args).sendToTarget();
638 } finally {
639 Log.endSession();
640 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700641 }
642
643 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700644 public void answerVideo(String callId, int videoState, Session.Info sessionInfo) {
645 Log.startSession(sessionInfo, SESSION_ANSWER_VIDEO);
646 try {
647 SomeArgs args = SomeArgs.obtain();
648 args.arg1 = callId;
649 args.arg2 = Log.createSubsession();
650 args.argi1 = videoState;
651 mHandler.obtainMessage(MSG_ANSWER_VIDEO, args).sendToTarget();
652 } finally {
653 Log.endSession();
654 }
Tyler Gunnbe74de02014-08-29 14:51:48 -0700655 }
656
657 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700658 public void answer(String callId, Session.Info sessionInfo) {
659 Log.startSession(sessionInfo, SESSION_ANSWER);
660 try {
661 SomeArgs args = SomeArgs.obtain();
662 args.arg1 = callId;
663 args.arg2 = Log.createSubsession();
664 mHandler.obtainMessage(MSG_ANSWER, args).sendToTarget();
665 } finally {
666 Log.endSession();
667 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700668 }
669
670 @Override
Pooja Jaind34698d2017-12-28 14:15:31 +0530671 public void deflect(String callId, Uri address, Session.Info sessionInfo) {
672 Log.startSession(sessionInfo, SESSION_DEFLECT);
673 try {
674 SomeArgs args = SomeArgs.obtain();
675 args.arg1 = callId;
676 args.arg2 = address;
677 args.arg3 = Log.createSubsession();
678 mHandler.obtainMessage(MSG_DEFLECT, args).sendToTarget();
679 } finally {
680 Log.endSession();
681 }
682 }
683
684 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700685 public void reject(String callId, Session.Info sessionInfo) {
686 Log.startSession(sessionInfo, SESSION_REJECT);
687 try {
688 SomeArgs args = SomeArgs.obtain();
689 args.arg1 = callId;
690 args.arg2 = Log.createSubsession();
691 mHandler.obtainMessage(MSG_REJECT, args).sendToTarget();
692 } finally {
693 Log.endSession();
694 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700695 }
696
697 @Override
Tyler Gunnfacfdee2020-01-23 13:10:37 -0800698 public void rejectWithReason(String callId,
699 @android.telecom.Call.RejectReason int rejectReason, Session.Info sessionInfo) {
700 Log.startSession(sessionInfo, SESSION_REJECT);
701 try {
702 SomeArgs args = SomeArgs.obtain();
703 args.arg1 = callId;
704 args.argi1 = rejectReason;
705 args.arg2 = Log.createSubsession();
706 mHandler.obtainMessage(MSG_REJECT_WITH_REASON, args).sendToTarget();
707 } finally {
708 Log.endSession();
709 }
710 }
711
712 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700713 public void rejectWithMessage(String callId, String message, Session.Info sessionInfo) {
714 Log.startSession(sessionInfo, SESSION_REJECT_MESSAGE);
715 try {
716 SomeArgs args = SomeArgs.obtain();
717 args.arg1 = callId;
718 args.arg2 = message;
719 args.arg3 = Log.createSubsession();
720 mHandler.obtainMessage(MSG_REJECT_WITH_MESSAGE, args).sendToTarget();
721 } finally {
722 Log.endSession();
723 }
Bryce Lee81901682015-08-28 16:38:02 -0700724 }
725
726 @Override
Ravi Palurif4b38e72020-02-05 12:35:41 +0530727 public void transfer(@NonNull String callId, @NonNull Uri number,
728 boolean isConfirmationRequired, Session.Info sessionInfo) {
729 Log.startSession(sessionInfo, SESSION_TRANSFER);
730 try {
731 SomeArgs args = SomeArgs.obtain();
732 args.arg1 = callId;
733 args.arg2 = number;
734 args.argi1 = isConfirmationRequired ? 1 : 0;
735 args.arg3 = Log.createSubsession();
736 mHandler.obtainMessage(MSG_EXPLICIT_CALL_TRANSFER, args).sendToTarget();
737 } finally {
738 Log.endSession();
739 }
740 }
741
742 @Override
743 public void consultativeTransfer(@NonNull String callId, @NonNull String otherCallId,
744 Session.Info sessionInfo) {
745 Log.startSession(sessionInfo, SESSION_CONSULTATIVE_TRANSFER);
746 try {
747 SomeArgs args = SomeArgs.obtain();
748 args.arg1 = callId;
749 args.arg2 = otherCallId;
750 args.arg3 = Log.createSubsession();
751 mHandler.obtainMessage(
752 MSG_EXPLICIT_CALL_TRANSFER_CONSULTATIVE, args).sendToTarget();
753 } finally {
754 Log.endSession();
755 }
756 }
757
758 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700759 public void silence(String callId, Session.Info sessionInfo) {
760 Log.startSession(sessionInfo, SESSION_SILENCE);
761 try {
762 SomeArgs args = SomeArgs.obtain();
763 args.arg1 = callId;
764 args.arg2 = Log.createSubsession();
765 mHandler.obtainMessage(MSG_SILENCE, args).sendToTarget();
766 } finally {
767 Log.endSession();
768 }
Bryce Leecac50772015-11-17 15:13:29 -0800769 }
770
771 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700772 public void disconnect(String callId, Session.Info sessionInfo) {
773 Log.startSession(sessionInfo, SESSION_DISCONNECT);
774 try {
775 SomeArgs args = SomeArgs.obtain();
776 args.arg1 = callId;
777 args.arg2 = Log.createSubsession();
778 mHandler.obtainMessage(MSG_DISCONNECT, args).sendToTarget();
779 } finally {
780 Log.endSession();
781 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700782 }
783
784 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700785 public void hold(String callId, Session.Info sessionInfo) {
786 Log.startSession(sessionInfo, SESSION_HOLD);
787 try {
788 SomeArgs args = SomeArgs.obtain();
789 args.arg1 = callId;
790 args.arg2 = Log.createSubsession();
791 mHandler.obtainMessage(MSG_HOLD, args).sendToTarget();
792 } finally {
793 Log.endSession();
794 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700795 }
796
797 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700798 public void unhold(String callId, Session.Info sessionInfo) {
799 Log.startSession(sessionInfo, SESSION_UNHOLD);
800 try {
801 SomeArgs args = SomeArgs.obtain();
802 args.arg1 = callId;
803 args.arg2 = Log.createSubsession();
804 mHandler.obtainMessage(MSG_UNHOLD, args).sendToTarget();
805 } finally {
806 Log.endSession();
807 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700808 }
809
810 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700811 public void onCallAudioStateChanged(String callId, CallAudioState callAudioState,
812 Session.Info sessionInfo) {
813 Log.startSession(sessionInfo, SESSION_CALL_AUDIO_SC);
814 try {
815 SomeArgs args = SomeArgs.obtain();
816 args.arg1 = callId;
817 args.arg2 = callAudioState;
818 args.arg3 = Log.createSubsession();
819 mHandler.obtainMessage(MSG_ON_CALL_AUDIO_STATE_CHANGED, args).sendToTarget();
820 } finally {
821 Log.endSession();
822 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700823 }
824
825 @Override
Junhoedf3d822022-11-24 09:26:37 +0000826 public void onCallEndpointChanged(String callId, CallEndpoint callEndpoint,
827 Session.Info sessionInfo) {
828 Log.startSession(sessionInfo, SESSION_CALL_ENDPOINT_CHANGED);
829 try {
830 SomeArgs args = SomeArgs.obtain();
831 args.arg1 = callId;
832 args.arg2 = callEndpoint;
833 args.arg3 = Log.createSubsession();
834 mHandler.obtainMessage(MSG_ON_CALL_ENDPOINT_CHANGED, args).sendToTarget();
835 } finally {
836 Log.endSession();
837 }
838 }
839
840 @Override
841 public void onAvailableCallEndpointsChanged(String callId,
842 List<CallEndpoint> availableCallEndpoints, Session.Info sessionInfo) {
843 Log.startSession(sessionInfo, SESSION_AVAILABLE_CALL_ENDPOINTS_CHANGED);
844 try {
845 SomeArgs args = SomeArgs.obtain();
846 args.arg1 = callId;
847 args.arg2 = availableCallEndpoints;
848 args.arg3 = Log.createSubsession();
849 mHandler.obtainMessage(MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED, args)
850 .sendToTarget();
851 } finally {
852 Log.endSession();
853 }
854 }
855
856 @Override
857 public void onMuteStateChanged(String callId, boolean isMuted, Session.Info sessionInfo) {
858 Log.startSession(sessionInfo, SESSION_MUTE_STATE_CHANGED);
859 try {
860 SomeArgs args = SomeArgs.obtain();
861 args.arg1 = callId;
862 args.arg2 = isMuted;
863 args.arg3 = Log.createSubsession();
864 mHandler.obtainMessage(MSG_ON_MUTE_STATE_CHANGED, args).sendToTarget();
865 } finally {
866 Log.endSession();
867 }
868 }
869
870 @Override
Grace Jiae99fde92021-01-19 14:58:01 -0800871 public void onUsingAlternativeUi(String callId, boolean usingAlternativeUiShowing,
872 Session.Info sessionInfo) {
873 Log.startSession(sessionInfo, SESSION_USING_ALTERNATIVE_UI);
874 try {
875 SomeArgs args = SomeArgs.obtain();
876 args.arg1 = callId;
877 args.arg2 = usingAlternativeUiShowing;
878 args.arg3 = Log.createSubsession();
879 mHandler.obtainMessage(MSG_ON_USING_ALTERNATIVE_UI, args).sendToTarget();
880 } finally {
881 Log.endSession();
882 }
883 }
884
885 @Override
886 public void onTrackedByNonUiService(String callId, boolean isTracked,
887 Session.Info sessionInfo) {
888 Log.startSession(sessionInfo, SESSION_TRACKED_BY_NON_UI_SERVICE);
889 try {
890 SomeArgs args = SomeArgs.obtain();
891 args.arg1 = callId;
892 args.arg2 = isTracked;
893 args.arg3 = Log.createSubsession();
894 mHandler.obtainMessage(MSG_ON_TRACKED_BY_NON_UI_SERVICE, args).sendToTarget();
895 } finally {
896 Log.endSession();
897 }
898 }
899
900 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700901 public void playDtmfTone(String callId, char digit, Session.Info sessionInfo) {
902 Log.startSession(sessionInfo, SESSION_PLAY_DTMF);
903 try {
904 SomeArgs args = SomeArgs.obtain();
905 args.arg1 = digit;
906 args.arg2 = callId;
907 args.arg3 = Log.createSubsession();
908 mHandler.obtainMessage(MSG_PLAY_DTMF_TONE, args).sendToTarget();
909 } finally {
910 Log.endSession();
911 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700912 }
913
914 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700915 public void stopDtmfTone(String callId, Session.Info sessionInfo) {
916 Log.startSession(sessionInfo, SESSION_STOP_DTMF);
917 try {
918 SomeArgs args = SomeArgs.obtain();
919 args.arg1 = callId;
920 args.arg2 = Log.createSubsession();
921 mHandler.obtainMessage(MSG_STOP_DTMF_TONE, args).sendToTarget();
922 } finally {
923 Log.endSession();
924 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700925 }
926
927 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700928 public void conference(String callId1, String callId2, Session.Info sessionInfo) {
929 Log.startSession(sessionInfo, SESSION_CONFERENCE);
930 try {
931 SomeArgs args = SomeArgs.obtain();
932 args.arg1 = callId1;
933 args.arg2 = callId2;
934 args.arg3 = Log.createSubsession();
935 mHandler.obtainMessage(MSG_CONFERENCE, args).sendToTarget();
936 } finally {
937 Log.endSession();
938 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700939 }
940
941 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700942 public void splitFromConference(String callId, Session.Info sessionInfo) {
943 Log.startSession(sessionInfo, SESSION_SPLIT_CONFERENCE);
944 try {
945 SomeArgs args = SomeArgs.obtain();
946 args.arg1 = callId;
947 args.arg2 = Log.createSubsession();
948 mHandler.obtainMessage(MSG_SPLIT_FROM_CONFERENCE, args).sendToTarget();
949 } finally {
950 Log.endSession();
951 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700952 }
953
954 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700955 public void mergeConference(String callId, Session.Info sessionInfo) {
956 Log.startSession(sessionInfo, SESSION_MERGE_CONFERENCE);
957 try {
958 SomeArgs args = SomeArgs.obtain();
959 args.arg1 = callId;
960 args.arg2 = Log.createSubsession();
961 mHandler.obtainMessage(MSG_MERGE_CONFERENCE, args).sendToTarget();
962 } finally {
963 Log.endSession();
964 }
Santos Cordona4868042014-09-04 17:39:22 -0700965 }
966
967 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700968 public void swapConference(String callId, Session.Info sessionInfo) {
969 Log.startSession(sessionInfo, SESSION_SWAP_CONFERENCE);
970 try {
971 SomeArgs args = SomeArgs.obtain();
972 args.arg1 = callId;
973 args.arg2 = Log.createSubsession();
974 mHandler.obtainMessage(MSG_SWAP_CONFERENCE, args).sendToTarget();
975 } finally {
976 Log.endSession();
977 }
Santos Cordona4868042014-09-04 17:39:22 -0700978 }
979
980 @Override
Ravi Paluri404babb2020-01-23 19:02:44 +0530981 public void addConferenceParticipants(String callId, List<Uri> participants,
982 Session.Info sessionInfo) {
983 Log.startSession(sessionInfo, SESSION_ADD_PARTICIPANT);
984 try {
985 SomeArgs args = SomeArgs.obtain();
986 args.arg1 = callId;
987 args.arg2 = participants;
988 args.arg3 = Log.createSubsession();
989 mHandler.obtainMessage(MSG_ADD_PARTICIPANT, args).sendToTarget();
990 } finally {
991 Log.endSession();
992 }
993 }
994
995 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -0700996 public void onPostDialContinue(String callId, boolean proceed, Session.Info sessionInfo) {
997 Log.startSession(sessionInfo, SESSION_POST_DIAL_CONT);
998 try {
999 SomeArgs args = SomeArgs.obtain();
1000 args.arg1 = callId;
1001 args.arg2 = Log.createSubsession();
1002 args.argi1 = proceed ? 1 : 0;
1003 mHandler.obtainMessage(MSG_ON_POST_DIAL_CONTINUE, args).sendToTarget();
1004 } finally {
1005 Log.endSession();
1006 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001007 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001008
1009 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001010 public void pullExternalCall(String callId, Session.Info sessionInfo) {
1011 Log.startSession(sessionInfo, SESSION_PULL_EXTERNAL_CALL);
1012 try {
1013 SomeArgs args = SomeArgs.obtain();
1014 args.arg1 = callId;
1015 args.arg2 = Log.createSubsession();
1016 mHandler.obtainMessage(MSG_PULL_EXTERNAL_CALL, args).sendToTarget();
1017 } finally {
1018 Log.endSession();
1019 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001020 }
1021
1022 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001023 public void sendCallEvent(String callId, String event, Bundle extras,
1024 Session.Info sessionInfo) {
1025 Log.startSession(sessionInfo, SESSION_SEND_CALL_EVENT);
1026 try {
1027 SomeArgs args = SomeArgs.obtain();
1028 args.arg1 = callId;
1029 args.arg2 = event;
1030 args.arg3 = extras;
1031 args.arg4 = Log.createSubsession();
1032 mHandler.obtainMessage(MSG_SEND_CALL_EVENT, args).sendToTarget();
1033 } finally {
1034 Log.endSession();
1035 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001036 }
Tyler Gunndee56a82016-03-23 16:06:34 -07001037
1038 @Override
Hall Liu73903142021-02-18 18:41:41 -08001039 public void onCallFilteringCompleted(String callId,
1040 Connection.CallFilteringCompletionInfo completionInfo,
Hall Liu49cabcc2021-01-15 11:41:48 -08001041 Session.Info sessionInfo) {
1042 Log.startSession(sessionInfo, SESSION_CALL_FILTERING_COMPLETED);
1043 try {
1044 SomeArgs args = SomeArgs.obtain();
1045 args.arg1 = callId;
Hall Liu73903142021-02-18 18:41:41 -08001046 args.arg2 = completionInfo;
1047 args.arg3 = Log.createSubsession();
Hall Liu49cabcc2021-01-15 11:41:48 -08001048 mHandler.obtainMessage(MSG_ON_CALL_FILTERING_COMPLETED, args).sendToTarget();
1049 } finally {
1050 Log.endSession();
1051 }
1052 }
1053
1054 @Override
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001055 public void onExtrasChanged(String callId, Bundle extras, Session.Info sessionInfo) {
1056 Log.startSession(sessionInfo, SESSION_EXTRAS_CHANGED);
1057 try {
1058 SomeArgs args = SomeArgs.obtain();
1059 args.arg1 = callId;
1060 args.arg2 = extras;
1061 args.arg3 = Log.createSubsession();
1062 mHandler.obtainMessage(MSG_ON_EXTRAS_CHANGED, args).sendToTarget();
1063 } finally {
1064 Log.endSession();
1065 }
Tyler Gunndee56a82016-03-23 16:06:34 -07001066 }
Hall Liub64ac4c2017-02-06 10:49:48 -08001067
1068 @Override
1069 public void startRtt(String callId, ParcelFileDescriptor fromInCall,
1070 ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException {
1071 Log.startSession(sessionInfo, SESSION_START_RTT);
1072 try {
1073 SomeArgs args = SomeArgs.obtain();
1074 args.arg1 = callId;
1075 args.arg2 = new Connection.RttTextStream(toInCall, fromInCall);
1076 args.arg3 = Log.createSubsession();
1077 mHandler.obtainMessage(MSG_ON_START_RTT, args).sendToTarget();
1078 } finally {
1079 Log.endSession();
1080 }
1081 }
1082
1083 @Override
1084 public void stopRtt(String callId, Session.Info sessionInfo) throws RemoteException {
1085 Log.startSession(sessionInfo, SESSION_STOP_RTT);
1086 try {
1087 SomeArgs args = SomeArgs.obtain();
1088 args.arg1 = callId;
1089 args.arg2 = Log.createSubsession();
1090 mHandler.obtainMessage(MSG_ON_STOP_RTT, args).sendToTarget();
1091 } finally {
1092 Log.endSession();
1093 }
1094 }
1095
1096 @Override
1097 public void respondToRttUpgradeRequest(String callId, ParcelFileDescriptor fromInCall,
1098 ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException {
1099 Log.startSession(sessionInfo, SESSION_RTT_UPGRADE_RESPONSE);
1100 try {
1101 SomeArgs args = SomeArgs.obtain();
1102 args.arg1 = callId;
1103 if (toInCall == null || fromInCall == null) {
1104 args.arg2 = null;
1105 } else {
1106 args.arg2 = new Connection.RttTextStream(toInCall, fromInCall);
1107 }
1108 args.arg3 = Log.createSubsession();
1109 mHandler.obtainMessage(MSG_RTT_UPGRADE_RESPONSE, args).sendToTarget();
1110 } finally {
1111 Log.endSession();
1112 }
1113 }
Pengquan Meng731c1a32017-11-21 18:01:13 -08001114
1115 @Override
1116 public void connectionServiceFocusLost(Session.Info sessionInfo) throws RemoteException {
1117 Log.startSession(sessionInfo, SESSION_CONNECTION_SERVICE_FOCUS_LOST);
1118 try {
1119 mHandler.obtainMessage(MSG_CONNECTION_SERVICE_FOCUS_LOST).sendToTarget();
1120 } finally {
1121 Log.endSession();
1122 }
1123 }
1124
1125 @Override
1126 public void connectionServiceFocusGained(Session.Info sessionInfo) throws RemoteException {
1127 Log.startSession(sessionInfo, SESSION_CONNECTION_SERVICE_FOCUS_GAINED);
1128 try {
1129 mHandler.obtainMessage(MSG_CONNECTION_SERVICE_FOCUS_GAINED).sendToTarget();
1130 } finally {
1131 Log.endSession();
1132 }
1133 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001134 };
1135
1136 private final Handler mHandler = new Handler(Looper.getMainLooper()) {
1137 @Override
1138 public void handleMessage(Message msg) {
1139 switch (msg.what) {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001140 case MSG_ADD_CONNECTION_SERVICE_ADAPTER: {
1141 SomeArgs args = (SomeArgs) msg.obj;
1142 try {
1143 IConnectionServiceAdapter adapter = (IConnectionServiceAdapter) args.arg1;
1144 Log.continueSession((Session) args.arg2,
1145 SESSION_HANDLER + SESSION_ADD_CS_ADAPTER);
1146 mAdapter.addAdapter(adapter);
1147 onAdapterAttached();
1148 } finally {
1149 args.recycle();
1150 Log.endSession();
1151 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001152 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001153 }
1154 case MSG_REMOVE_CONNECTION_SERVICE_ADAPTER: {
1155 SomeArgs args = (SomeArgs) msg.obj;
1156 try {
1157 Log.continueSession((Session) args.arg2,
1158 SESSION_HANDLER + SESSION_REMOVE_CS_ADAPTER);
1159 mAdapter.removeAdapter((IConnectionServiceAdapter) args.arg1);
1160 } finally {
1161 args.recycle();
1162 Log.endSession();
1163 }
Ihab Awad8aecfed2014-08-08 17:06:11 -07001164 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001165 }
Ihab Awadf8b69882014-07-25 15:14:01 -07001166 case MSG_CREATE_CONNECTION: {
1167 SomeArgs args = (SomeArgs) msg.obj;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001168 Log.continueSession((Session) args.arg4, SESSION_HANDLER + SESSION_CREATE_CONN);
Ihab Awadf8b69882014-07-25 15:14:01 -07001169 try {
Ihab Awad5d0410f2014-07-30 10:07:40 -07001170 final PhoneAccountHandle connectionManagerPhoneAccount =
Ihab Awadf8b69882014-07-25 15:14:01 -07001171 (PhoneAccountHandle) args.arg1;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001172 final String id = (String) args.arg2;
1173 final ConnectionRequest request = (ConnectionRequest) args.arg3;
Ihab Awad5d0410f2014-07-30 10:07:40 -07001174 final boolean isIncoming = args.argi1 == 1;
Yorke Leec3cf9822014-10-02 09:38:39 -07001175 final boolean isUnknown = args.argi2 == 1;
Ihab Awad5d0410f2014-07-30 10:07:40 -07001176 if (!mAreAccountsInitialized) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001177 Log.d(this, "Enqueueing pre-init request %s", id);
Brad Ebinger0c3541b2016-11-01 14:11:38 -07001178 mPreInitializationConnectionRequests.add(
1179 new android.telecom.Logging.Runnable(
1180 SESSION_HANDLER + SESSION_CREATE_CONN + ".pICR",
1181 null /*lock*/) {
Ihab Awad5d0410f2014-07-30 10:07:40 -07001182 @Override
Brad Ebinger0c3541b2016-11-01 14:11:38 -07001183 public void loggedRun() {
Ihab Awad5d0410f2014-07-30 10:07:40 -07001184 createConnection(
1185 connectionManagerPhoneAccount,
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001186 id,
Ihab Awad5d0410f2014-07-30 10:07:40 -07001187 request,
Yorke Leec3cf9822014-10-02 09:38:39 -07001188 isIncoming,
1189 isUnknown);
Ihab Awad5d0410f2014-07-30 10:07:40 -07001190 }
Brad Ebinger0c3541b2016-11-01 14:11:38 -07001191 }.prepare());
Ihab Awad5d0410f2014-07-30 10:07:40 -07001192 } else {
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001193 createConnection(
1194 connectionManagerPhoneAccount,
1195 id,
1196 request,
Yorke Leec3cf9822014-10-02 09:38:39 -07001197 isIncoming,
1198 isUnknown);
Ihab Awad5d0410f2014-07-30 10:07:40 -07001199 }
Ihab Awadf8b69882014-07-25 15:14:01 -07001200 } finally {
1201 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001202 Log.endSession();
Ihab Awadf8b69882014-07-25 15:14:01 -07001203 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001204 break;
Ihab Awadf8b69882014-07-25 15:14:01 -07001205 }
Tyler Gunn041a1fe2017-05-12 10:04:49 -07001206 case MSG_CREATE_CONNECTION_COMPLETE: {
1207 SomeArgs args = (SomeArgs) msg.obj;
1208 Log.continueSession((Session) args.arg2,
1209 SESSION_HANDLER + SESSION_CREATE_CONN_COMPLETE);
1210 try {
1211 final String id = (String) args.arg1;
1212 if (!mAreAccountsInitialized) {
1213 Log.d(this, "Enqueueing pre-init request %s", id);
1214 mPreInitializationConnectionRequests.add(
1215 new android.telecom.Logging.Runnable(
1216 SESSION_HANDLER + SESSION_CREATE_CONN_COMPLETE
1217 + ".pICR",
1218 null /*lock*/) {
1219 @Override
1220 public void loggedRun() {
1221 notifyCreateConnectionComplete(id);
1222 }
1223 }.prepare());
1224 } else {
1225 notifyCreateConnectionComplete(id);
1226 }
1227 } finally {
1228 args.recycle();
1229 Log.endSession();
1230 }
1231 break;
1232 }
Tyler Gunn44e01912017-01-31 10:49:05 -08001233 case MSG_CREATE_CONNECTION_FAILED: {
1234 SomeArgs args = (SomeArgs) msg.obj;
1235 Log.continueSession((Session) args.arg3, SESSION_HANDLER +
1236 SESSION_CREATE_CONN_FAILED);
1237 try {
1238 final String id = (String) args.arg1;
1239 final ConnectionRequest request = (ConnectionRequest) args.arg2;
1240 final boolean isIncoming = args.argi1 == 1;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001241 final PhoneAccountHandle connectionMgrPhoneAccount =
1242 (PhoneAccountHandle) args.arg4;
Tyler Gunn44e01912017-01-31 10:49:05 -08001243 if (!mAreAccountsInitialized) {
1244 Log.d(this, "Enqueueing pre-init request %s", id);
1245 mPreInitializationConnectionRequests.add(
1246 new android.telecom.Logging.Runnable(
1247 SESSION_HANDLER + SESSION_CREATE_CONN_FAILED + ".pICR",
1248 null /*lock*/) {
1249 @Override
1250 public void loggedRun() {
Tyler Gunn159f35c2017-03-02 09:28:37 -08001251 createConnectionFailed(connectionMgrPhoneAccount, id,
1252 request, isIncoming);
Tyler Gunn44e01912017-01-31 10:49:05 -08001253 }
1254 }.prepare());
1255 } else {
1256 Log.i(this, "createConnectionFailed %s", id);
Tyler Gunn159f35c2017-03-02 09:28:37 -08001257 createConnectionFailed(connectionMgrPhoneAccount, id, request,
1258 isIncoming);
Tyler Gunn44e01912017-01-31 10:49:05 -08001259 }
1260 } finally {
1261 args.recycle();
1262 Log.endSession();
1263 }
1264 break;
1265 }
Ravi Paluri80aa2142019-12-02 11:57:37 +05301266 case MSG_CREATE_CONFERENCE: {
1267 SomeArgs args = (SomeArgs) msg.obj;
1268 Log.continueSession((Session) args.arg4, SESSION_HANDLER + SESSION_CREATE_CONN);
1269 try {
1270 final PhoneAccountHandle connectionManagerPhoneAccount =
1271 (PhoneAccountHandle) args.arg1;
1272 final String id = (String) args.arg2;
1273 final ConnectionRequest request = (ConnectionRequest) args.arg3;
1274 final boolean isIncoming = args.argi1 == 1;
1275 final boolean isUnknown = args.argi2 == 1;
1276 if (!mAreAccountsInitialized) {
1277 Log.d(this, "Enqueueing pre-initconference request %s", id);
1278 mPreInitializationConnectionRequests.add(
1279 new android.telecom.Logging.Runnable(
1280 SESSION_HANDLER + SESSION_CREATE_CONF + ".pIConfR",
1281 null /*lock*/) {
1282 @Override
1283 public void loggedRun() {
1284 createConference(connectionManagerPhoneAccount,
1285 id,
1286 request,
1287 isIncoming,
1288 isUnknown);
1289 }
1290 }.prepare());
1291 } else {
1292 createConference(connectionManagerPhoneAccount,
1293 id,
1294 request,
1295 isIncoming,
1296 isUnknown);
1297 }
1298 } finally {
1299 args.recycle();
1300 Log.endSession();
1301 }
1302 break;
1303 }
1304 case MSG_CREATE_CONFERENCE_COMPLETE: {
1305 SomeArgs args = (SomeArgs) msg.obj;
1306 Log.continueSession((Session) args.arg2,
1307 SESSION_HANDLER + SESSION_CREATE_CONN_COMPLETE);
1308 try {
1309 final String id = (String) args.arg1;
1310 if (!mAreAccountsInitialized) {
1311 Log.d(this, "Enqueueing pre-init conference request %s", id);
1312 mPreInitializationConnectionRequests.add(
1313 new android.telecom.Logging.Runnable(
1314 SESSION_HANDLER + SESSION_CREATE_CONF_COMPLETE
1315 + ".pIConfR",
1316 null /*lock*/) {
1317 @Override
1318 public void loggedRun() {
1319 notifyCreateConferenceComplete(id);
1320 }
1321 }.prepare());
1322 } else {
1323 notifyCreateConferenceComplete(id);
1324 }
1325 } finally {
1326 args.recycle();
1327 Log.endSession();
1328 }
1329 break;
1330 }
1331 case MSG_CREATE_CONFERENCE_FAILED: {
1332 SomeArgs args = (SomeArgs) msg.obj;
1333 Log.continueSession((Session) args.arg3, SESSION_HANDLER +
1334 SESSION_CREATE_CONN_FAILED);
1335 try {
1336 final String id = (String) args.arg1;
1337 final ConnectionRequest request = (ConnectionRequest) args.arg2;
1338 final boolean isIncoming = args.argi1 == 1;
1339 final PhoneAccountHandle connectionMgrPhoneAccount =
1340 (PhoneAccountHandle) args.arg4;
1341 if (!mAreAccountsInitialized) {
1342 Log.d(this, "Enqueueing pre-init conference request %s", id);
1343 mPreInitializationConnectionRequests.add(
1344 new android.telecom.Logging.Runnable(
1345 SESSION_HANDLER + SESSION_CREATE_CONF_FAILED
1346 + ".pIConfR",
1347 null /*lock*/) {
1348 @Override
1349 public void loggedRun() {
1350 createConferenceFailed(connectionMgrPhoneAccount, id,
1351 request, isIncoming);
1352 }
1353 }.prepare());
1354 } else {
1355 Log.i(this, "createConferenceFailed %s", id);
1356 createConferenceFailed(connectionMgrPhoneAccount, id, request,
1357 isIncoming);
1358 }
1359 } finally {
1360 args.recycle();
1361 Log.endSession();
1362 }
1363 break;
1364 }
1365
Sanket Padawe4cc8ed52017-12-04 16:22:20 -08001366 case MSG_HANDOVER_FAILED: {
1367 SomeArgs args = (SomeArgs) msg.obj;
1368 Log.continueSession((Session) args.arg3, SESSION_HANDLER +
1369 SESSION_HANDOVER_FAILED);
1370 try {
1371 final String id = (String) args.arg1;
1372 final ConnectionRequest request = (ConnectionRequest) args.arg2;
1373 final int reason = (int) args.arg4;
1374 if (!mAreAccountsInitialized) {
1375 Log.d(this, "Enqueueing pre-init request %s", id);
1376 mPreInitializationConnectionRequests.add(
1377 new android.telecom.Logging.Runnable(
1378 SESSION_HANDLER
1379 + SESSION_HANDOVER_FAILED + ".pICR",
1380 null /*lock*/) {
1381 @Override
1382 public void loggedRun() {
1383 handoverFailed(id, request, reason);
1384 }
1385 }.prepare());
1386 } else {
1387 Log.i(this, "createConnectionFailed %s", id);
1388 handoverFailed(id, request, reason);
1389 }
1390 } finally {
1391 args.recycle();
1392 Log.endSession();
1393 }
1394 break;
1395 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001396 case MSG_ABORT: {
1397 SomeArgs args = (SomeArgs) msg.obj;
1398 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_ABORT);
1399 try {
1400 abort((String) args.arg1);
1401 } finally {
1402 args.recycle();
1403 Log.endSession();
1404 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001405 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001406 }
1407 case MSG_ANSWER: {
1408 SomeArgs args = (SomeArgs) msg.obj;
1409 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_ANSWER);
1410 try {
1411 answer((String) args.arg1);
1412 } finally {
1413 args.recycle();
1414 Log.endSession();
1415 }
Tyler Gunnbe74de02014-08-29 14:51:48 -07001416 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001417 }
Tyler Gunnbe74de02014-08-29 14:51:48 -07001418 case MSG_ANSWER_VIDEO: {
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001419 SomeArgs args = (SomeArgs) msg.obj;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001420 Log.continueSession((Session) args.arg2,
1421 SESSION_HANDLER + SESSION_ANSWER_VIDEO);
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001422 try {
1423 String callId = (String) args.arg1;
Evan Charltonbf11f982014-07-20 22:06:28 -07001424 int videoState = args.argi1;
Tyler Gunnbe74de02014-08-29 14:51:48 -07001425 answerVideo(callId, videoState);
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001426 } finally {
1427 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001428 Log.endSession();
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001429 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001430 break;
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001431 }
Pooja Jaind34698d2017-12-28 14:15:31 +05301432 case MSG_DEFLECT: {
1433 SomeArgs args = (SomeArgs) msg.obj;
1434 Log.continueSession((Session) args.arg3, SESSION_HANDLER + SESSION_DEFLECT);
1435 try {
1436 deflect((String) args.arg1, (Uri) args.arg2);
1437 } finally {
1438 args.recycle();
1439 Log.endSession();
1440 }
1441 break;
1442 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001443 case MSG_REJECT: {
1444 SomeArgs args = (SomeArgs) msg.obj;
1445 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_REJECT);
1446 try {
1447 reject((String) args.arg1);
1448 } finally {
1449 args.recycle();
1450 Log.endSession();
1451 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001452 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001453 }
Tyler Gunnfacfdee2020-01-23 13:10:37 -08001454 case MSG_REJECT_WITH_REASON: {
1455 SomeArgs args = (SomeArgs) msg.obj;
1456 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_REJECT);
1457 try {
1458 reject((String) args.arg1, args.argi1);
1459 } finally {
1460 args.recycle();
1461 Log.endSession();
1462 }
1463 break;
1464 }
Bryce Lee81901682015-08-28 16:38:02 -07001465 case MSG_REJECT_WITH_MESSAGE: {
1466 SomeArgs args = (SomeArgs) msg.obj;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001467 Log.continueSession((Session) args.arg3,
1468 SESSION_HANDLER + SESSION_REJECT_MESSAGE);
Bryce Lee81901682015-08-28 16:38:02 -07001469 try {
1470 reject((String) args.arg1, (String) args.arg2);
1471 } finally {
1472 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001473 Log.endSession();
Bryce Lee81901682015-08-28 16:38:02 -07001474 }
1475 break;
1476 }
Ravi Palurif4b38e72020-02-05 12:35:41 +05301477 case MSG_EXPLICIT_CALL_TRANSFER: {
1478 SomeArgs args = (SomeArgs) msg.obj;
1479 Log.continueSession((Session) args.arg3, SESSION_HANDLER + SESSION_TRANSFER);
1480 try {
1481 final boolean isConfirmationRequired = args.argi1 == 1;
1482 transfer((String) args.arg1, (Uri) args.arg2, isConfirmationRequired);
1483 } finally {
1484 args.recycle();
1485 Log.endSession();
1486 }
1487 break;
1488 }
1489 case MSG_EXPLICIT_CALL_TRANSFER_CONSULTATIVE: {
1490 SomeArgs args = (SomeArgs) msg.obj;
1491 Log.continueSession(
1492 (Session) args.arg3, SESSION_HANDLER + SESSION_CONSULTATIVE_TRANSFER);
1493 try {
1494 consultativeTransfer((String) args.arg1, (String) args.arg2);
1495 } finally {
1496 args.recycle();
1497 Log.endSession();
1498 }
1499 break;
1500 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001501 case MSG_DISCONNECT: {
1502 SomeArgs args = (SomeArgs) msg.obj;
1503 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_DISCONNECT);
1504 try {
1505 disconnect((String) args.arg1);
1506 } finally {
1507 args.recycle();
1508 Log.endSession();
1509 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001510 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001511 }
1512 case MSG_SILENCE: {
1513 SomeArgs args = (SomeArgs) msg.obj;
1514 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_SILENCE);
1515 try {
1516 silence((String) args.arg1);
1517 } finally {
1518 args.recycle();
1519 Log.endSession();
1520 }
Bryce Leecac50772015-11-17 15:13:29 -08001521 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001522 }
1523 case MSG_HOLD: {
1524 SomeArgs args = (SomeArgs) msg.obj;
1525 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_REJECT);
1526 try {
1527 hold((String) args.arg1);
1528 } finally {
1529 args.recycle();
1530 Log.endSession();
1531 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001532 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001533 }
1534 case MSG_UNHOLD: {
1535 SomeArgs args = (SomeArgs) msg.obj;
1536 Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_UNHOLD);
1537 try {
1538 unhold((String) args.arg1);
1539 } finally {
1540 args.recycle();
1541 Log.endSession();
1542 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001543 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001544 }
Yorke Lee4af59352015-05-13 14:14:54 -07001545 case MSG_ON_CALL_AUDIO_STATE_CHANGED: {
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001546 SomeArgs args = (SomeArgs) msg.obj;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001547 Log.continueSession((Session) args.arg3,
1548 SESSION_HANDLER + SESSION_CALL_AUDIO_SC);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001549 try {
1550 String callId = (String) args.arg1;
Yorke Lee4af59352015-05-13 14:14:54 -07001551 CallAudioState audioState = (CallAudioState) args.arg2;
1552 onCallAudioStateChanged(callId, new CallAudioState(audioState));
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001553 } finally {
1554 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001555 Log.endSession();
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001556 }
1557 break;
1558 }
Grace Jiae99fde92021-01-19 14:58:01 -08001559 case MSG_ON_USING_ALTERNATIVE_UI: {
1560 SomeArgs args = (SomeArgs) msg.obj;
1561 Log.continueSession((Session) args.arg3,
1562 SESSION_HANDLER + SESSION_USING_ALTERNATIVE_UI);
1563 try {
1564 String callId = (String) args.arg1;
1565 boolean isUsingAlternativeUi = (boolean) args.arg2;
1566 onUsingAlternativeUi(callId, isUsingAlternativeUi);
1567 } finally {
1568 args.recycle();
1569 Log.endSession();
1570 }
1571 break;
1572 }
1573 case MSG_ON_TRACKED_BY_NON_UI_SERVICE: {
1574 SomeArgs args = (SomeArgs) msg.obj;
1575 Log.continueSession((Session) args.arg3,
1576 SESSION_HANDLER + SESSION_TRACKED_BY_NON_UI_SERVICE);
1577 try {
1578 String callId = (String) args.arg1;
1579 boolean isTracked = (boolean) args.arg2;
1580 onTrackedByNonUiService(callId, isTracked);
1581 } finally {
1582 args.recycle();
1583 Log.endSession();
1584 }
1585 break;
1586 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001587 case MSG_PLAY_DTMF_TONE: {
1588 SomeArgs args = (SomeArgs) msg.obj;
1589 try {
1590 Log.continueSession((Session) args.arg3,
1591 SESSION_HANDLER + SESSION_PLAY_DTMF);
1592 playDtmfTone((String) args.arg2, (char) args.arg1);
1593 } finally {
1594 args.recycle();
1595 Log.endSession();
1596 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001597 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001598 }
1599 case MSG_STOP_DTMF_TONE: {
1600 SomeArgs args = (SomeArgs) msg.obj;
1601 try {
1602 Log.continueSession((Session) args.arg2,
1603 SESSION_HANDLER + SESSION_STOP_DTMF);
1604 stopDtmfTone((String) args.arg1);
1605 } finally {
1606 args.recycle();
1607 Log.endSession();
1608 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001609 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001610 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001611 case MSG_CONFERENCE: {
1612 SomeArgs args = (SomeArgs) msg.obj;
1613 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001614 Log.continueSession((Session) args.arg3,
1615 SESSION_HANDLER + SESSION_CONFERENCE);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001616 String callId1 = (String) args.arg1;
1617 String callId2 = (String) args.arg2;
1618 conference(callId1, callId2);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001619 } finally {
1620 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001621 Log.endSession();
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001622 }
1623 break;
1624 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001625 case MSG_SPLIT_FROM_CONFERENCE: {
1626 SomeArgs args = (SomeArgs) msg.obj;
1627 try {
1628 Log.continueSession((Session) args.arg2,
1629 SESSION_HANDLER + SESSION_SPLIT_CONFERENCE);
1630 splitFromConference((String) args.arg1);
1631 } finally {
1632 args.recycle();
1633 Log.endSession();
1634 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001635 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001636 }
1637 case MSG_MERGE_CONFERENCE: {
1638 SomeArgs args = (SomeArgs) msg.obj;
1639 try {
1640 Log.continueSession((Session) args.arg2,
1641 SESSION_HANDLER + SESSION_MERGE_CONFERENCE);
1642 mergeConference((String) args.arg1);
1643 } finally {
1644 args.recycle();
1645 Log.endSession();
1646 }
Santos Cordona4868042014-09-04 17:39:22 -07001647 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001648 }
1649 case MSG_SWAP_CONFERENCE: {
1650 SomeArgs args = (SomeArgs) msg.obj;
1651 try {
1652 Log.continueSession((Session) args.arg2,
1653 SESSION_HANDLER + SESSION_SWAP_CONFERENCE);
1654 swapConference((String) args.arg1);
1655 } finally {
1656 args.recycle();
1657 Log.endSession();
1658 }
Santos Cordona4868042014-09-04 17:39:22 -07001659 break;
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001660 }
Ravi Paluri404babb2020-01-23 19:02:44 +05301661 case MSG_ADD_PARTICIPANT: {
1662 SomeArgs args = (SomeArgs) msg.obj;
1663 try {
1664 Log.continueSession((Session) args.arg3,
1665 SESSION_HANDLER + SESSION_ADD_PARTICIPANT);
1666 addConferenceParticipants((String) args.arg1, (List<Uri>)args.arg2);
1667 } finally {
1668 args.recycle();
1669 Log.endSession();
1670 }
1671 break;
1672 }
1673
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001674 case MSG_ON_POST_DIAL_CONTINUE: {
1675 SomeArgs args = (SomeArgs) msg.obj;
1676 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001677 Log.continueSession((Session) args.arg2,
1678 SESSION_HANDLER + SESSION_POST_DIAL_CONT);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001679 String callId = (String) args.arg1;
1680 boolean proceed = (args.argi1 == 1);
1681 onPostDialContinue(callId, proceed);
1682 } finally {
1683 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001684 Log.endSession();
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001685 }
1686 break;
1687 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001688 case MSG_PULL_EXTERNAL_CALL: {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001689 SomeArgs args = (SomeArgs) msg.obj;
1690 try {
1691 Log.continueSession((Session) args.arg2,
1692 SESSION_HANDLER + SESSION_PULL_EXTERNAL_CALL);
1693 pullExternalCall((String) args.arg1);
1694 } finally {
1695 args.recycle();
1696 Log.endSession();
1697 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001698 break;
1699 }
1700 case MSG_SEND_CALL_EVENT: {
1701 SomeArgs args = (SomeArgs) msg.obj;
1702 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001703 Log.continueSession((Session) args.arg4,
1704 SESSION_HANDLER + SESSION_SEND_CALL_EVENT);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001705 String callId = (String) args.arg1;
1706 String event = (String) args.arg2;
1707 Bundle extras = (Bundle) args.arg3;
1708 sendCallEvent(callId, event, extras);
1709 } finally {
1710 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001711 Log.endSession();
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001712 }
1713 break;
1714 }
Hall Liu49cabcc2021-01-15 11:41:48 -08001715 case MSG_ON_CALL_FILTERING_COMPLETED: {
1716 SomeArgs args = (SomeArgs) msg.obj;
1717 try {
Hall Liu73903142021-02-18 18:41:41 -08001718 Log.continueSession((Session) args.arg3,
Hall Liu49cabcc2021-01-15 11:41:48 -08001719 SESSION_HANDLER + SESSION_CALL_FILTERING_COMPLETED);
1720 String callId = (String) args.arg1;
Hall Liu73903142021-02-18 18:41:41 -08001721 Connection.CallFilteringCompletionInfo completionInfo =
1722 (Connection.CallFilteringCompletionInfo) args.arg2;
1723 onCallFilteringCompleted(callId, completionInfo);
Hall Liu49cabcc2021-01-15 11:41:48 -08001724 } finally {
1725 args.recycle();
1726 Log.endSession();
1727 }
1728 break;
1729 }
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08001730 case MSG_HANDOVER_COMPLETE: {
1731 SomeArgs args = (SomeArgs) msg.obj;
1732 try {
1733 Log.continueSession((Session) args.arg2,
1734 SESSION_HANDLER + SESSION_HANDOVER_COMPLETE);
1735 String callId = (String) args.arg1;
1736 notifyHandoverComplete(callId);
1737 } finally {
1738 args.recycle();
1739 Log.endSession();
1740 }
1741 break;
1742 }
Tyler Gunndee56a82016-03-23 16:06:34 -07001743 case MSG_ON_EXTRAS_CHANGED: {
1744 SomeArgs args = (SomeArgs) msg.obj;
1745 try {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001746 Log.continueSession((Session) args.arg3,
1747 SESSION_HANDLER + SESSION_EXTRAS_CHANGED);
Tyler Gunndee56a82016-03-23 16:06:34 -07001748 String callId = (String) args.arg1;
1749 Bundle extras = (Bundle) args.arg2;
1750 handleExtrasChanged(callId, extras);
1751 } finally {
1752 args.recycle();
Brad Ebingerb32d4f82016-10-24 16:40:49 -07001753 Log.endSession();
Tyler Gunndee56a82016-03-23 16:06:34 -07001754 }
1755 break;
1756 }
Hall Liub64ac4c2017-02-06 10:49:48 -08001757 case MSG_ON_START_RTT: {
1758 SomeArgs args = (SomeArgs) msg.obj;
1759 try {
1760 Log.continueSession((Session) args.arg3,
1761 SESSION_HANDLER + SESSION_START_RTT);
1762 String callId = (String) args.arg1;
1763 Connection.RttTextStream rttTextStream =
1764 (Connection.RttTextStream) args.arg2;
1765 startRtt(callId, rttTextStream);
1766 } finally {
1767 args.recycle();
1768 Log.endSession();
1769 }
1770 break;
1771 }
1772 case MSG_ON_STOP_RTT: {
1773 SomeArgs args = (SomeArgs) msg.obj;
1774 try {
1775 Log.continueSession((Session) args.arg2,
1776 SESSION_HANDLER + SESSION_STOP_RTT);
1777 String callId = (String) args.arg1;
1778 stopRtt(callId);
1779 } finally {
1780 args.recycle();
1781 Log.endSession();
1782 }
1783 break;
1784 }
1785 case MSG_RTT_UPGRADE_RESPONSE: {
1786 SomeArgs args = (SomeArgs) msg.obj;
1787 try {
1788 Log.continueSession((Session) args.arg3,
1789 SESSION_HANDLER + SESSION_RTT_UPGRADE_RESPONSE);
1790 String callId = (String) args.arg1;
1791 Connection.RttTextStream rttTextStream =
1792 (Connection.RttTextStream) args.arg2;
1793 handleRttUpgradeResponse(callId, rttTextStream);
1794 } finally {
1795 args.recycle();
1796 Log.endSession();
1797 }
1798 break;
1799 }
Pengquan Meng731c1a32017-11-21 18:01:13 -08001800 case MSG_CONNECTION_SERVICE_FOCUS_GAINED:
1801 onConnectionServiceFocusGained();
1802 break;
1803 case MSG_CONNECTION_SERVICE_FOCUS_LOST:
1804 onConnectionServiceFocusLost();
1805 break;
Junhoedf3d822022-11-24 09:26:37 +00001806 case MSG_ON_CALL_ENDPOINT_CHANGED: {
1807 SomeArgs args = (SomeArgs) msg.obj;
1808 Log.continueSession((Session) args.arg3,
1809 SESSION_HANDLER + SESSION_CALL_AUDIO_SC);
1810 try {
1811 String callId = (String) args.arg1;
1812 CallEndpoint callEndpoint = (CallEndpoint) args.arg2;
1813 onCallEndpointChanged(callId, callEndpoint);
1814 } finally {
1815 args.recycle();
1816 Log.endSession();
1817 }
1818 break;
1819 }
1820 case MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED: {
1821 SomeArgs args = (SomeArgs) msg.obj;
1822 Log.continueSession((Session) args.arg3,
1823 SESSION_HANDLER + SESSION_CALL_AUDIO_SC);
1824 try {
1825 String callId = (String) args.arg1;
1826 List<CallEndpoint> availableCallEndpoints = (List<CallEndpoint>) args.arg2;
1827 onAvailableCallEndpointsChanged(callId, availableCallEndpoints);
1828 } finally {
1829 args.recycle();
1830 Log.endSession();
1831 }
1832 break;
1833 }
1834 case MSG_ON_MUTE_STATE_CHANGED: {
1835 SomeArgs args = (SomeArgs) msg.obj;
1836 Log.continueSession((Session) args.arg3,
1837 SESSION_HANDLER + SESSION_CALL_AUDIO_SC);
1838 try {
1839 String callId = (String) args.arg1;
1840 boolean isMuted = (boolean) args.arg2;
1841 onMuteStateChanged(callId, isMuted);
1842 } finally {
1843 args.recycle();
1844 Log.endSession();
1845 }
1846 break;
1847 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07001848 default:
1849 break;
1850 }
1851 }
1852 };
1853
Santos Cordon823fd3c2014-08-07 18:35:18 -07001854 private final Conference.Listener mConferenceListener = new Conference.Listener() {
1855 @Override
1856 public void onStateChanged(Conference conference, int oldState, int newState) {
1857 String id = mIdByConference.get(conference);
1858 switch (newState) {
Ravi Paluri80aa2142019-12-02 11:57:37 +05301859 case Connection.STATE_RINGING:
1860 mAdapter.setRinging(id);
1861 break;
1862 case Connection.STATE_DIALING:
1863 mAdapter.setDialing(id);
1864 break;
Santos Cordon823fd3c2014-08-07 18:35:18 -07001865 case Connection.STATE_ACTIVE:
1866 mAdapter.setActive(id);
1867 break;
1868 case Connection.STATE_HOLDING:
1869 mAdapter.setOnHold(id);
1870 break;
1871 case Connection.STATE_DISCONNECTED:
1872 // handled by onDisconnected
1873 break;
1874 }
1875 }
1876
1877 @Override
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001878 public void onDisconnected(Conference conference, DisconnectCause disconnectCause) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001879 String id = mIdByConference.get(conference);
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001880 mAdapter.setDisconnected(id, disconnectCause);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001881 }
1882
1883 @Override
1884 public void onConnectionAdded(Conference conference, Connection connection) {
1885 }
1886
1887 @Override
1888 public void onConnectionRemoved(Conference conference, Connection connection) {
1889 }
1890
1891 @Override
Ihab Awad50e35062014-09-30 09:17:03 -07001892 public void onConferenceableConnectionsChanged(
1893 Conference conference, List<Connection> conferenceableConnections) {
1894 mAdapter.setConferenceableConnections(
1895 mIdByConference.get(conference),
1896 createConnectionIdList(conferenceableConnections));
1897 }
1898
1899 @Override
Santos Cordon823fd3c2014-08-07 18:35:18 -07001900 public void onDestroyed(Conference conference) {
1901 removeConference(conference);
1902 }
1903
1904 @Override
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001905 public void onConnectionCapabilitiesChanged(
1906 Conference conference,
1907 int connectionCapabilities) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001908 String id = mIdByConference.get(conference);
1909 Log.d(this, "call capabilities: conference: %s",
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001910 Connection.capabilitiesToString(connectionCapabilities));
1911 mAdapter.setConnectionCapabilities(id, connectionCapabilities);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001912 }
Rekha Kumar07366812015-03-24 16:42:31 -07001913
1914 @Override
Tyler Gunn720c6642016-03-22 09:02:47 -07001915 public void onConnectionPropertiesChanged(
1916 Conference conference,
1917 int connectionProperties) {
1918 String id = mIdByConference.get(conference);
1919 Log.d(this, "call capabilities: conference: %s",
1920 Connection.propertiesToString(connectionProperties));
1921 mAdapter.setConnectionProperties(id, connectionProperties);
1922 }
1923
1924 @Override
Rekha Kumar07366812015-03-24 16:42:31 -07001925 public void onVideoStateChanged(Conference c, int videoState) {
1926 String id = mIdByConference.get(c);
1927 Log.d(this, "onVideoStateChanged set video state %d", videoState);
1928 mAdapter.setVideoState(id, videoState);
1929 }
1930
1931 @Override
1932 public void onVideoProviderChanged(Conference c, Connection.VideoProvider videoProvider) {
1933 String id = mIdByConference.get(c);
1934 Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c,
1935 videoProvider);
1936 mAdapter.setVideoProvider(id, videoProvider);
1937 }
Andrew Lee0f51da32015-04-16 13:11:55 -07001938
1939 @Override
Andrew Leeedc625f2015-04-14 13:38:12 -07001940 public void onStatusHintsChanged(Conference conference, StatusHints statusHints) {
1941 String id = mIdByConference.get(conference);
Tyler Gunndee56a82016-03-23 16:06:34 -07001942 if (id != null) {
1943 mAdapter.setStatusHints(id, statusHints);
1944 }
Andrew Leeedc625f2015-04-14 13:38:12 -07001945 }
Santos Cordon6b7f9552015-05-27 17:21:45 -07001946
1947 @Override
Tyler Gunndee56a82016-03-23 16:06:34 -07001948 public void onExtrasChanged(Conference c, Bundle extras) {
1949 String id = mIdByConference.get(c);
1950 if (id != null) {
1951 mAdapter.putExtras(id, extras);
1952 }
1953 }
1954
1955 @Override
1956 public void onExtrasRemoved(Conference c, List<String> keys) {
1957 String id = mIdByConference.get(c);
1958 if (id != null) {
1959 mAdapter.removeExtras(id, keys);
1960 }
Santos Cordon6b7f9552015-05-27 17:21:45 -07001961 }
Tyler Gunn68a73a42018-10-03 15:38:57 -07001962
1963 @Override
1964 public void onConferenceStateChanged(Conference c, boolean isConference) {
1965 String id = mIdByConference.get(c);
1966 if (id != null) {
1967 mAdapter.setConferenceState(id, isConference);
1968 }
1969 }
1970
1971 @Override
Brad Ebingere0c12f42020-04-08 16:25:12 -07001972 public void onCallDirectionChanged(Conference c, int direction) {
1973 String id = mIdByConference.get(c);
1974 if (id != null) {
1975 mAdapter.setCallDirection(id, direction);
1976 }
1977 }
1978
1979 @Override
Tyler Gunn68a73a42018-10-03 15:38:57 -07001980 public void onAddressChanged(Conference c, Uri newAddress, int presentation) {
1981 String id = mIdByConference.get(c);
1982 if (id != null) {
1983 mAdapter.setAddress(id, newAddress, presentation);
1984 }
1985 }
1986
1987 @Override
1988 public void onCallerDisplayNameChanged(Conference c, String callerDisplayName,
1989 int presentation) {
1990 String id = mIdByConference.get(c);
1991 if (id != null) {
1992 mAdapter.setCallerDisplayName(id, callerDisplayName, presentation);
1993 }
1994 }
Hall Liuc9bc1c62019-04-16 14:00:55 -07001995
1996 @Override
1997 public void onConnectionEvent(Conference c, String event, Bundle extras) {
1998 String id = mIdByConference.get(c);
1999 if (id != null) {
2000 mAdapter.onConnectionEvent(id, event, extras);
2001 }
2002 }
Ravi Paluri80aa2142019-12-02 11:57:37 +05302003
2004 @Override
2005 public void onRingbackRequested(Conference c, boolean ringback) {
2006 String id = mIdByConference.get(c);
2007 Log.d(this, "Adapter conference onRingback %b", ringback);
2008 mAdapter.setRingbackRequested(id, ringback);
2009 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002010 };
2011
Ihab Awad542e0ea2014-05-16 10:22:16 -07002012 private final Connection.Listener mConnectionListener = new Connection.Listener() {
2013 @Override
2014 public void onStateChanged(Connection c, int state) {
2015 String id = mIdByConnection.get(c);
Ihab Awad42b30e12014-05-22 09:49:34 -07002016 Log.d(this, "Adapter set state %s %s", id, Connection.stateToString(state));
Ihab Awad542e0ea2014-05-16 10:22:16 -07002017 switch (state) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -07002018 case Connection.STATE_ACTIVE:
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002019 mAdapter.setActive(id);
Ihab Awad542e0ea2014-05-16 10:22:16 -07002020 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07002021 case Connection.STATE_DIALING:
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002022 mAdapter.setDialing(id);
Ihab Awad542e0ea2014-05-16 10:22:16 -07002023 break;
Tyler Gunnc96b5e02016-07-07 22:53:57 -07002024 case Connection.STATE_PULLING_CALL:
2025 mAdapter.setPulling(id);
2026 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07002027 case Connection.STATE_DISCONNECTED:
Ihab Awad542e0ea2014-05-16 10:22:16 -07002028 // Handled in onDisconnected()
2029 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07002030 case Connection.STATE_HOLDING:
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002031 mAdapter.setOnHold(id);
Ihab Awad542e0ea2014-05-16 10:22:16 -07002032 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07002033 case Connection.STATE_NEW:
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002034 // Nothing to tell Telecom
Ihab Awad542e0ea2014-05-16 10:22:16 -07002035 break;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07002036 case Connection.STATE_RINGING:
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002037 mAdapter.setRinging(id);
Ihab Awad542e0ea2014-05-16 10:22:16 -07002038 break;
2039 }
2040 }
2041
2042 @Override
Andrew Lee7f3d41f2014-09-11 17:33:16 -07002043 public void onDisconnected(Connection c, DisconnectCause disconnectCause) {
Ihab Awad542e0ea2014-05-16 10:22:16 -07002044 String id = mIdByConnection.get(c);
Andrew Lee26786392014-09-16 18:14:59 -07002045 Log.d(this, "Adapter set disconnected %s", disconnectCause);
Andrew Lee7f3d41f2014-09-11 17:33:16 -07002046 mAdapter.setDisconnected(id, disconnectCause);
Ihab Awad542e0ea2014-05-16 10:22:16 -07002047 }
2048
2049 @Override
Tyler Gunnaa07df82014-07-17 07:50:22 -07002050 public void onVideoStateChanged(Connection c, int videoState) {
2051 String id = mIdByConnection.get(c);
2052 Log.d(this, "Adapter set video state %d", videoState);
2053 mAdapter.setVideoState(id, videoState);
2054 }
2055
2056 @Override
Andrew Lee100e2932014-09-08 15:34:24 -07002057 public void onAddressChanged(Connection c, Uri address, int presentation) {
Sailesh Nepal61203862014-07-11 14:50:13 -07002058 String id = mIdByConnection.get(c);
Andrew Lee100e2932014-09-08 15:34:24 -07002059 mAdapter.setAddress(id, address, presentation);
Sailesh Nepal61203862014-07-11 14:50:13 -07002060 }
2061
2062 @Override
2063 public void onCallerDisplayNameChanged(
2064 Connection c, String callerDisplayName, int presentation) {
2065 String id = mIdByConnection.get(c);
2066 mAdapter.setCallerDisplayName(id, callerDisplayName, presentation);
Ihab Awad542e0ea2014-05-16 10:22:16 -07002067 }
2068
2069 @Override
Ihab Awad542e0ea2014-05-16 10:22:16 -07002070 public void onDestroyed(Connection c) {
2071 removeConnection(c);
2072 }
Ihab Awadf8358972014-05-28 16:46:42 -07002073
2074 @Override
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002075 public void onPostDialWait(Connection c, String remaining) {
Sailesh Nepal091768c2014-06-30 15:15:23 -07002076 String id = mIdByConnection.get(c);
2077 Log.d(this, "Adapter onPostDialWait %s, %s", c, remaining);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002078 mAdapter.onPostDialWait(id, remaining);
Sailesh Nepal091768c2014-06-30 15:15:23 -07002079 }
2080
2081 @Override
Nancy Chen27d1c2d2014-12-15 16:12:50 -08002082 public void onPostDialChar(Connection c, char nextChar) {
2083 String id = mIdByConnection.get(c);
2084 Log.d(this, "Adapter onPostDialChar %s, %s", c, nextChar);
2085 mAdapter.onPostDialChar(id, nextChar);
2086 }
2087
2088 @Override
Andrew Lee100e2932014-09-08 15:34:24 -07002089 public void onRingbackRequested(Connection c, boolean ringback) {
Ihab Awadf8358972014-05-28 16:46:42 -07002090 String id = mIdByConnection.get(c);
2091 Log.d(this, "Adapter onRingback %b", ringback);
Andrew Lee100e2932014-09-08 15:34:24 -07002092 mAdapter.setRingbackRequested(id, ringback);
Ihab Awadf8358972014-05-28 16:46:42 -07002093 }
Santos Cordonb6939982014-06-04 20:20:58 -07002094
2095 @Override
Ihab Awad5c9c86e2014-11-12 13:41:16 -08002096 public void onConnectionCapabilitiesChanged(Connection c, int capabilities) {
Santos Cordonb6939982014-06-04 20:20:58 -07002097 String id = mIdByConnection.get(c);
Ihab Awadb19a0bc2014-08-07 19:46:01 -07002098 Log.d(this, "capabilities: parcelableconnection: %s",
Ihab Awad5c9c86e2014-11-12 13:41:16 -08002099 Connection.capabilitiesToString(capabilities));
2100 mAdapter.setConnectionCapabilities(id, capabilities);
Santos Cordonb6939982014-06-04 20:20:58 -07002101 }
2102
Santos Cordonb6939982014-06-04 20:20:58 -07002103 @Override
Tyler Gunn720c6642016-03-22 09:02:47 -07002104 public void onConnectionPropertiesChanged(Connection c, int properties) {
2105 String id = mIdByConnection.get(c);
2106 Log.d(this, "properties: parcelableconnection: %s",
2107 Connection.propertiesToString(properties));
2108 mAdapter.setConnectionProperties(id, properties);
2109 }
2110
2111 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -07002112 public void onVideoProviderChanged(Connection c, Connection.VideoProvider videoProvider) {
Andrew Lee5ffbe8b82014-06-20 16:29:33 -07002113 String id = mIdByConnection.get(c);
Rekha Kumar07366812015-03-24 16:42:31 -07002114 Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c,
2115 videoProvider);
Ihab Awadb19a0bc2014-08-07 19:46:01 -07002116 mAdapter.setVideoProvider(id, videoProvider);
Andrew Lee5ffbe8b82014-06-20 16:29:33 -07002117 }
Sailesh Nepal33aaae42014-07-07 22:49:44 -07002118
2119 @Override
Sailesh Nepal001bbbb2014-07-15 14:40:39 -07002120 public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {
Sailesh Nepal33aaae42014-07-07 22:49:44 -07002121 String id = mIdByConnection.get(c);
Andrew Lee100e2932014-09-08 15:34:24 -07002122 mAdapter.setIsVoipAudioMode(id, isVoip);
Sailesh Nepal33aaae42014-07-07 22:49:44 -07002123 }
Sailesh Nepale7ef59a2014-07-08 21:48:22 -07002124
2125 @Override
Sailesh Nepal001bbbb2014-07-15 14:40:39 -07002126 public void onStatusHintsChanged(Connection c, StatusHints statusHints) {
Sailesh Nepale7ef59a2014-07-08 21:48:22 -07002127 String id = mIdByConnection.get(c);
2128 mAdapter.setStatusHints(id, statusHints);
2129 }
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07002130
2131 @Override
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002132 public void onConferenceablesChanged(
Tyler Gunndf2cbc82015-04-20 09:13:01 -07002133 Connection connection, List<Conferenceable> conferenceables) {
Ihab Awadb8e85c72014-08-23 20:34:57 -07002134 mAdapter.setConferenceableConnections(
2135 mIdByConnection.get(connection),
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002136 createIdList(conferenceables));
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002137 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002138
2139 @Override
2140 public void onConferenceChanged(Connection connection, Conference conference) {
2141 String id = mIdByConnection.get(connection);
2142 if (id != null) {
2143 String conferenceId = null;
2144 if (conference != null) {
2145 conferenceId = mIdByConference.get(conference);
2146 }
2147 mAdapter.setIsConferenced(id, conferenceId);
2148 }
2149 }
Anthony Lee17455a32015-04-24 15:25:29 -07002150
2151 @Override
2152 public void onConferenceMergeFailed(Connection connection) {
2153 String id = mIdByConnection.get(connection);
2154 if (id != null) {
2155 mAdapter.onConferenceMergeFailed(id);
2156 }
2157 }
Santos Cordon6b7f9552015-05-27 17:21:45 -07002158
2159 @Override
Tyler Gunndee56a82016-03-23 16:06:34 -07002160 public void onExtrasChanged(Connection c, Bundle extras) {
2161 String id = mIdByConnection.get(c);
Santos Cordon6b7f9552015-05-27 17:21:45 -07002162 if (id != null) {
Tyler Gunndee56a82016-03-23 16:06:34 -07002163 mAdapter.putExtras(id, extras);
Santos Cordon6b7f9552015-05-27 17:21:45 -07002164 }
2165 }
Brad Ebingerb32d4f82016-10-24 16:40:49 -07002166
Tyler Gunnf5035432017-01-09 09:43:12 -08002167 @Override
Tyler Gunndee56a82016-03-23 16:06:34 -07002168 public void onExtrasRemoved(Connection c, List<String> keys) {
2169 String id = mIdByConnection.get(c);
2170 if (id != null) {
2171 mAdapter.removeExtras(id, keys);
2172 }
2173 }
2174
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -08002175 @Override
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002176 public void onConnectionEvent(Connection connection, String event, Bundle extras) {
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -08002177 String id = mIdByConnection.get(connection);
2178 if (id != null) {
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002179 mAdapter.onConnectionEvent(id, event, extras);
Tyler Gunnbd1eb1f2016-02-16 14:36:20 -08002180 }
2181 }
Tyler Gunnf5035432017-01-09 09:43:12 -08002182
2183 @Override
Hall Liua98f58b52017-11-07 17:59:28 -08002184 public void onAudioRouteChanged(Connection c, int audioRoute, String bluetoothAddress) {
Tyler Gunnf5035432017-01-09 09:43:12 -08002185 String id = mIdByConnection.get(c);
2186 if (id != null) {
Hall Liua98f58b52017-11-07 17:59:28 -08002187 mAdapter.setAudioRoute(id, audioRoute, bluetoothAddress);
Tyler Gunnf5035432017-01-09 09:43:12 -08002188 }
2189 }
Hall Liub64ac4c2017-02-06 10:49:48 -08002190
2191 @Override
2192 public void onRttInitiationSuccess(Connection c) {
2193 String id = mIdByConnection.get(c);
2194 if (id != null) {
2195 mAdapter.onRttInitiationSuccess(id);
2196 }
2197 }
2198
2199 @Override
2200 public void onRttInitiationFailure(Connection c, int reason) {
2201 String id = mIdByConnection.get(c);
2202 if (id != null) {
2203 mAdapter.onRttInitiationFailure(id, reason);
2204 }
2205 }
2206
2207 @Override
2208 public void onRttSessionRemotelyTerminated(Connection c) {
2209 String id = mIdByConnection.get(c);
2210 if (id != null) {
2211 mAdapter.onRttSessionRemotelyTerminated(id);
2212 }
2213 }
2214
2215 @Override
2216 public void onRemoteRttRequest(Connection c) {
2217 String id = mIdByConnection.get(c);
2218 if (id != null) {
2219 mAdapter.onRemoteRttRequest(id);
2220 }
2221 }
Srikanth Chintalafcb15012017-05-04 20:58:34 +05302222
2223 @Override
2224 public void onPhoneAccountChanged(Connection c, PhoneAccountHandle pHandle) {
2225 String id = mIdByConnection.get(c);
2226 if (id != null) {
2227 mAdapter.onPhoneAccountChanged(id, pHandle);
2228 }
2229 }
Mengjun Leng25707742017-07-04 11:10:37 +08002230
2231 public void onConnectionTimeReset(Connection c) {
2232 String id = mIdByConnection.get(c);
2233 if (id != null) {
2234 mAdapter.resetConnectionTime(id);
2235 }
2236 }
Junhoedf3d822022-11-24 09:26:37 +00002237
2238 @Override
2239 public void onEndpointChanged(Connection c, CallEndpoint endpoint, Executor executor,
2240 OutcomeReceiver<Void, CallEndpointException> callback) {
2241 String id = mIdByConnection.get(c);
2242 if (id != null) {
2243 mAdapter.requestCallEndpointChange(id, endpoint, executor, callback);
2244 }
2245 }
yongnamcha8ec56242022-11-28 06:23:02 +00002246
2247 @Override
2248 public void onQueryLocation(Connection c, long timeoutMillis, @NonNull String provider,
2249 @NonNull @CallbackExecutor Executor executor,
2250 @NonNull OutcomeReceiver<Location, QueryLocationException> callback) {
2251 String id = mIdByConnection.get(c);
2252 if (id != null) {
2253 mAdapter.queryLocation(id, timeoutMillis, provider, executor, callback);
2254 }
2255 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002256 };
2257
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002258 /** {@inheritDoc} */
Ihab Awad542e0ea2014-05-16 10:22:16 -07002259 @Override
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002260 public final IBinder onBind(Intent intent) {
Hall Liueb7c9ea2021-03-09 20:24:50 -08002261 onBindClient(intent);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002262 return mBinder;
2263 }
2264
Santos Cordon29f2f2e2014-09-11 19:50:24 -07002265 /** {@inheritDoc} */
2266 @Override
2267 public boolean onUnbind(Intent intent) {
2268 endAllConnections();
2269 return super.onUnbind(intent);
2270 }
2271
Hall Liueb7c9ea2021-03-09 20:24:50 -08002272 /**
2273 * Used for testing to let the test suite know when the connection service has been bound.
2274 * @hide
2275 */
2276 @TestApi
2277 public void onBindClient(@Nullable Intent intent) {
2278 }
Ravi Paluri80aa2142019-12-02 11:57:37 +05302279
2280 /**
2281 * This can be used by telecom to either create a new outgoing conference call or attach
2282 * to an existing incoming conference call. In either case, telecom will cycle through a
2283 * set of services and call createConference until a connection service cancels the process
2284 * or completes it successfully.
2285 */
2286 private void createConference(
2287 final PhoneAccountHandle callManagerAccount,
2288 final String callId,
2289 final ConnectionRequest request,
2290 boolean isIncoming,
2291 boolean isUnknown) {
2292
2293 Conference conference = null;
2294 conference = isIncoming ? onCreateIncomingConference(callManagerAccount, request)
2295 : onCreateOutgoingConference(callManagerAccount, request);
2296
2297 Log.d(this, "createConference, conference: %s", conference);
2298 if (conference == null) {
2299 Log.i(this, "createConference, implementation returned null conference.");
2300 conference = Conference.createFailedConference(
2301 new DisconnectCause(DisconnectCause.ERROR, "IMPL_RETURNED_NULL_CONFERENCE"),
2302 request.getAccountHandle());
2303 }
Tyler Gunnc59fd0c2020-04-17 14:03:35 -07002304
2305 Bundle extras = request.getExtras();
2306 Bundle newExtras = new Bundle();
2307 newExtras.putString(Connection.EXTRA_ORIGINAL_CONNECTION_ID, callId);
2308 if (extras != null) {
2309 // If the request originated from a remote connection service, we will add some
2310 // tracking information that Telecom can use to keep informed of which package
2311 // made the remote request, and which remote connection service was used.
2312 if (extras.containsKey(Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME)) {
2313 newExtras.putString(
2314 Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME,
2315 extras.getString(
2316 Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME));
2317 newExtras.putParcelable(Connection.EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE,
2318 request.getAccountHandle());
2319 }
Ravi Paluri80aa2142019-12-02 11:57:37 +05302320 }
Tyler Gunnc59fd0c2020-04-17 14:03:35 -07002321 conference.putExtras(newExtras);
2322
Ravi Paluri80aa2142019-12-02 11:57:37 +05302323 mConferenceById.put(callId, conference);
2324 mIdByConference.put(conference, callId);
Tyler Gunn460360d2020-07-29 10:21:45 -07002325
Ravi Paluri80aa2142019-12-02 11:57:37 +05302326 conference.addListener(mConferenceListener);
Brad Ebinger0ae44ed2020-04-09 15:30:57 -07002327 ParcelableConference parcelableConference = new ParcelableConference.Builder(
2328 request.getAccountHandle(), conference.getState())
2329 .setConnectionCapabilities(conference.getConnectionCapabilities())
2330 .setConnectionProperties(conference.getConnectionProperties())
2331 .setVideoAttributes(conference.getVideoProvider() == null
2332 ? null : conference.getVideoProvider().getInterface(),
2333 conference.getVideoState())
2334 .setConnectTimeMillis(conference.getConnectTimeMillis(),
2335 conference.getConnectionStartElapsedRealtimeMillis())
2336 .setStatusHints(conference.getStatusHints())
2337 .setExtras(conference.getExtras())
2338 .setAddress(conference.getAddress(), conference.getAddressPresentation())
2339 .setCallerDisplayName(conference.getCallerDisplayName(),
2340 conference.getCallerDisplayNamePresentation())
2341 .setDisconnectCause(conference.getDisconnectCause())
2342 .setRingbackRequested(conference.isRingbackRequested())
2343 .build();
Ravi Paluri80aa2142019-12-02 11:57:37 +05302344 if (conference.getState() != Connection.STATE_DISCONNECTED) {
2345 conference.setTelecomCallId(callId);
2346 mAdapter.setVideoProvider(callId, conference.getVideoProvider());
2347 mAdapter.setVideoState(callId, conference.getVideoState());
2348 onConferenceAdded(conference);
2349 }
2350
2351 Log.d(this, "createConference, calling handleCreateConferenceSuccessful %s", callId);
2352 mAdapter.handleCreateConferenceComplete(
2353 callId,
2354 request,
2355 parcelableConference);
2356 }
2357
Sailesh Nepalc5b01572014-07-14 16:29:44 -07002358 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002359 * This can be used by telecom to either create a new outgoing call or attach to an existing
2360 * incoming call. In either case, telecom will cycle through a set of services and call
Sailesh Nepalc5b01572014-07-14 16:29:44 -07002361 * createConnection util a connection service cancels the process or completes it successfully.
2362 */
Ihab Awadf8b69882014-07-25 15:14:01 -07002363 private void createConnection(
2364 final PhoneAccountHandle callManagerAccount,
Ihab Awadb19a0bc2014-08-07 19:46:01 -07002365 final String callId,
Ihab Awadf8b69882014-07-25 15:14:01 -07002366 final ConnectionRequest request,
Yorke Leec3cf9822014-10-02 09:38:39 -07002367 boolean isIncoming,
2368 boolean isUnknown) {
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08002369 boolean isLegacyHandover = request.getExtras() != null &&
2370 request.getExtras().getBoolean(TelecomManager.EXTRA_IS_HANDOVER, false);
2371 boolean isHandover = request.getExtras() != null && request.getExtras().getBoolean(
2372 TelecomManager.EXTRA_IS_HANDOVER_CONNECTION, false);
Grace Jiae99fde92021-01-19 14:58:01 -08002373 boolean addSelfManaged = request.getExtras() != null && request.getExtras().getBoolean(
Grace Jia8b22bb42021-02-02 15:37:32 -08002374 PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, true);
Grace Jiae99fde92021-01-19 14:58:01 -08002375 Log.i(this, "createConnection, callManagerAccount: %s, callId: %s, request: %s, "
2376 + "isIncoming: %b, isUnknown: %b, isLegacyHandover: %b, isHandover: %b, "
2377 + " addSelfManaged: %b", callManagerAccount, callId, request, isIncoming,
2378 isUnknown, isLegacyHandover, isHandover, addSelfManaged);
Ihab Awad542e0ea2014-05-16 10:22:16 -07002379
Sanket Padawee29a2662017-12-01 13:59:27 -08002380 Connection connection = null;
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08002381 if (isHandover) {
2382 PhoneAccountHandle fromPhoneAccountHandle = request.getExtras() != null
2383 ? (PhoneAccountHandle) request.getExtras().getParcelable(
Hani Kazmi4f221e52022-06-20 09:38:26 +00002384 TelecomManager.EXTRA_HANDOVER_FROM_PHONE_ACCOUNT, android.telecom.PhoneAccountHandle.class) : null;
Sanket Padawee29a2662017-12-01 13:59:27 -08002385 if (!isIncoming) {
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08002386 connection = onCreateOutgoingHandoverConnection(fromPhoneAccountHandle, request);
Sanket Padawee29a2662017-12-01 13:59:27 -08002387 } else {
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08002388 connection = onCreateIncomingHandoverConnection(fromPhoneAccountHandle, request);
Sanket Padawee29a2662017-12-01 13:59:27 -08002389 }
2390 } else {
2391 connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
2392 : isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
2393 : onCreateOutgoingConnection(callManagerAccount, request);
2394 }
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07002395 Log.d(this, "createConnection, connection: %s", connection);
2396 if (connection == null) {
Tyler Gunnfba1a8e2017-12-19 15:23:59 -08002397 Log.i(this, "createConnection, implementation returned null connection.");
Andrew Lee7f3d41f2014-09-11 17:33:16 -07002398 connection = Connection.createFailedConnection(
Tyler Gunnfba1a8e2017-12-19 15:23:59 -08002399 new DisconnectCause(DisconnectCause.ERROR, "IMPL_RETURNED_NULL_CONNECTION"));
Tyler Gunnc59fd0c2020-04-17 14:03:35 -07002400 } else {
2401 try {
2402 Bundle extras = request.getExtras();
2403 if (extras != null) {
2404 // If the request originated from a remote connection service, we will add some
2405 // tracking information that Telecom can use to keep informed of which package
2406 // made the remote request, and which remote connection service was used.
2407 if (extras.containsKey(
2408 Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME)) {
2409 Bundle newExtras = new Bundle();
2410 newExtras.putString(
2411 Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME,
2412 extras.getString(
2413 Connection.EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME
2414 ));
2415 newExtras.putParcelable(Connection.EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE,
2416 request.getAccountHandle());
2417 connection.putExtras(newExtras);
2418 }
2419 }
2420 } catch (UnsupportedOperationException ose) {
2421 // Do nothing; if the ConnectionService reported a failure it will be an instance
2422 // of an immutable Connection which we cannot edit, so we're out of luck.
2423 }
Sailesh Nepalc5b01572014-07-14 16:29:44 -07002424 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002425
Tyler Gunnf2e08b42018-05-24 10:44:44 -07002426 boolean isSelfManaged =
2427 (connection.getConnectionProperties() & Connection.PROPERTY_SELF_MANAGED)
2428 == Connection.PROPERTY_SELF_MANAGED;
2429 // Self-managed Connections should always use voip audio mode; we default here so that the
2430 // local state within the ConnectionService matches the default we assume in Telecom.
2431 if (isSelfManaged) {
2432 connection.setAudioModeIsVoip(true);
2433 }
Tyler Gunnf0500bd2015-09-01 10:59:48 -07002434 connection.setTelecomCallId(callId);
Sungjae7f4137452020-09-16 17:01:54 +09002435 PhoneAccountHandle phoneAccountHandle = connection.getPhoneAccountHandle() == null
2436 ? request.getAccountHandle() : connection.getPhoneAccountHandle();
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07002437 if (connection.getState() != Connection.STATE_DISCONNECTED) {
Sungjae7f4137452020-09-16 17:01:54 +09002438 addConnection(phoneAccountHandle, callId, connection);
Ihab Awad6107bab2014-08-18 09:23:25 -07002439 }
2440
Andrew Lee100e2932014-09-08 15:34:24 -07002441 Uri address = connection.getAddress();
2442 String number = address == null ? "null" : address.getSchemeSpecificPart();
Tyler Gunn720c6642016-03-22 09:02:47 -07002443 Log.v(this, "createConnection, number: %s, state: %s, capabilities: %s, properties: %s",
Ihab Awadb19a0bc2014-08-07 19:46:01 -07002444 Connection.toLogSafePhoneNumber(number),
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07002445 Connection.stateToString(connection.getState()),
Tyler Gunn720c6642016-03-22 09:02:47 -07002446 Connection.capabilitiesToString(connection.getConnectionCapabilities()),
2447 Connection.propertiesToString(connection.getConnectionProperties()));
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002448
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07002449 Log.d(this, "createConnection, calling handleCreateConnectionSuccessful %s", callId);
Ihab Awad6107bab2014-08-18 09:23:25 -07002450 mAdapter.handleCreateConnectionComplete(
Ihab Awadb19a0bc2014-08-07 19:46:01 -07002451 callId,
Evan Charltonbf11f982014-07-20 22:06:28 -07002452 request,
2453 new ParcelableConnection(
Sungjae7f4137452020-09-16 17:01:54 +09002454 phoneAccountHandle,
Evan Charltonbf11f982014-07-20 22:06:28 -07002455 connection.getState(),
Ihab Awad5c9c86e2014-11-12 13:41:16 -08002456 connection.getConnectionCapabilities(),
Tyler Gunn720c6642016-03-22 09:02:47 -07002457 connection.getConnectionProperties(),
Christine Hallstrom2830ce92016-11-30 16:06:42 -08002458 connection.getSupportedAudioRoutes(),
Andrew Lee100e2932014-09-08 15:34:24 -07002459 connection.getAddress(),
2460 connection.getAddressPresentation(),
Evan Charltonbf11f982014-07-20 22:06:28 -07002461 connection.getCallerDisplayName(),
2462 connection.getCallerDisplayNamePresentation(),
Ihab Awadb19a0bc2014-08-07 19:46:01 -07002463 connection.getVideoProvider() == null ?
2464 null : connection.getVideoProvider().getInterface(),
Sailesh Nepal8b9d3ca2014-08-14 17:39:34 -07002465 connection.getVideoState(),
Andrew Lee100e2932014-09-08 15:34:24 -07002466 connection.isRingbackRequested(),
Sailesh Nepal8b9d3ca2014-08-14 17:39:34 -07002467 connection.getAudioModeIsVoip(),
Roshan Piuse927ec02015-07-15 15:47:21 -07002468 connection.getConnectTimeMillis(),
Tyler Gunnc9503d62020-01-27 10:30:51 -08002469 connection.getConnectionStartElapsedRealtimeMillis(),
Ihab Awad6107bab2014-08-18 09:23:25 -07002470 connection.getStatusHints(),
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07002471 connection.getDisconnectCause(),
Santos Cordon6b7f9552015-05-27 17:21:45 -07002472 createIdList(connection.getConferenceables()),
Tyler Gunnd57d76c2019-09-24 14:53:23 -07002473 connection.getExtras(),
2474 connection.getCallerNumberVerificationStatus()));
Tyler Gunnf5035432017-01-09 09:43:12 -08002475
Tyler Gunnf2e08b42018-05-24 10:44:44 -07002476 if (isIncoming && request.shouldShowIncomingCallUi() && isSelfManaged) {
Tyler Gunnf5035432017-01-09 09:43:12 -08002477 // Tell ConnectionService to show its incoming call UX.
2478 connection.onShowIncomingCallUi();
2479 }
Shriram Ganesh6bf35ac2014-12-11 17:53:38 -08002480 if (isUnknown) {
2481 triggerConferenceRecalculate();
2482 }
Evan Charltonbf11f982014-07-20 22:06:28 -07002483 }
2484
Tyler Gunn159f35c2017-03-02 09:28:37 -08002485 private void createConnectionFailed(final PhoneAccountHandle callManagerAccount,
2486 final String callId, final ConnectionRequest request,
2487 boolean isIncoming) {
Tyler Gunn44e01912017-01-31 10:49:05 -08002488
2489 Log.i(this, "createConnectionFailed %s", callId);
2490 if (isIncoming) {
Tyler Gunn159f35c2017-03-02 09:28:37 -08002491 onCreateIncomingConnectionFailed(callManagerAccount, request);
Tyler Gunn44e01912017-01-31 10:49:05 -08002492 } else {
Tyler Gunn159f35c2017-03-02 09:28:37 -08002493 onCreateOutgoingConnectionFailed(callManagerAccount, request);
Tyler Gunn44e01912017-01-31 10:49:05 -08002494 }
2495 }
2496
Ravi Paluri80aa2142019-12-02 11:57:37 +05302497 private void createConferenceFailed(final PhoneAccountHandle callManagerAccount,
2498 final String callId, final ConnectionRequest request,
2499 boolean isIncoming) {
2500
2501 Log.i(this, "createConferenceFailed %s", callId);
2502 if (isIncoming) {
2503 onCreateIncomingConferenceFailed(callManagerAccount, request);
2504 } else {
2505 onCreateOutgoingConferenceFailed(callManagerAccount, request);
2506 }
2507 }
2508
Sanket Padawe4cc8ed52017-12-04 16:22:20 -08002509 private void handoverFailed(final String callId, final ConnectionRequest request,
2510 int reason) {
2511
2512 Log.i(this, "handoverFailed %s", callId);
2513 onHandoverFailed(request, reason);
2514 }
2515
Tyler Gunn041a1fe2017-05-12 10:04:49 -07002516 /**
2517 * Called by Telecom when the creation of a new Connection has completed and it is now added
2518 * to Telecom.
2519 * @param callId The ID of the connection.
2520 */
2521 private void notifyCreateConnectionComplete(final String callId) {
2522 Log.i(this, "notifyCreateConnectionComplete %s", callId);
Tyler Gunn0a88f2e2017-06-16 20:20:34 -07002523 if (callId == null) {
2524 // This could happen if the connection fails quickly and is removed from the
2525 // ConnectionService before Telecom sends the create connection complete callback.
2526 Log.w(this, "notifyCreateConnectionComplete: callId is null.");
2527 return;
2528 }
Tyler Gunn041a1fe2017-05-12 10:04:49 -07002529 onCreateConnectionComplete(findConnectionForAction(callId,
2530 "notifyCreateConnectionComplete"));
2531 }
2532
Ravi Paluri80aa2142019-12-02 11:57:37 +05302533 /**
2534 * Called by Telecom when the creation of a new Conference has completed and it is now added
2535 * to Telecom.
2536 * @param callId The ID of the connection.
2537 */
2538 private void notifyCreateConferenceComplete(final String callId) {
2539 Log.i(this, "notifyCreateConferenceComplete %s", callId);
2540 if (callId == null) {
2541 // This could happen if the conference fails quickly and is removed from the
2542 // ConnectionService before Telecom sends the create conference complete callback.
2543 Log.w(this, "notifyCreateConferenceComplete: callId is null.");
2544 return;
2545 }
2546 onCreateConferenceComplete(findConferenceForAction(callId,
2547 "notifyCreateConferenceComplete"));
2548 }
2549
2550
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002551 private void abort(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002552 Log.i(this, "abort %s", callId);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002553 findConnectionForAction(callId, "abort").onAbort();
Ihab Awad542e0ea2014-05-16 10:22:16 -07002554 }
2555
Tyler Gunnbe74de02014-08-29 14:51:48 -07002556 private void answerVideo(String callId, int videoState) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002557 Log.i(this, "answerVideo %s", callId);
Ravi Paluri80aa2142019-12-02 11:57:37 +05302558 if (mConnectionById.containsKey(callId)) {
2559 findConnectionForAction(callId, "answer").onAnswer(videoState);
2560 } else {
2561 findConferenceForAction(callId, "answer").onAnswer(videoState);
2562 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002563 }
2564
Tyler Gunnbe74de02014-08-29 14:51:48 -07002565 private void answer(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002566 Log.i(this, "answer %s", callId);
Ravi Paluri80aa2142019-12-02 11:57:37 +05302567 if (mConnectionById.containsKey(callId)) {
2568 findConnectionForAction(callId, "answer").onAnswer();
2569 } else {
2570 findConferenceForAction(callId, "answer").onAnswer();
2571 }
Tyler Gunnbe74de02014-08-29 14:51:48 -07002572 }
2573
Pooja Jaind34698d2017-12-28 14:15:31 +05302574 private void deflect(String callId, Uri address) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002575 Log.i(this, "deflect %s", callId);
Pooja Jaind34698d2017-12-28 14:15:31 +05302576 findConnectionForAction(callId, "deflect").onDeflect(address);
2577 }
2578
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002579 private void reject(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002580 Log.i(this, "reject %s", callId);
Ravi Paluri80aa2142019-12-02 11:57:37 +05302581 if (mConnectionById.containsKey(callId)) {
2582 findConnectionForAction(callId, "reject").onReject();
2583 } else {
2584 findConferenceForAction(callId, "reject").onReject();
2585 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002586 }
2587
Bryce Lee81901682015-08-28 16:38:02 -07002588 private void reject(String callId, String rejectWithMessage) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002589 Log.i(this, "reject %s with message", callId);
Bryce Lee81901682015-08-28 16:38:02 -07002590 findConnectionForAction(callId, "reject").onReject(rejectWithMessage);
2591 }
2592
Tyler Gunnfacfdee2020-01-23 13:10:37 -08002593 private void reject(String callId, @android.telecom.Call.RejectReason int rejectReason) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002594 Log.i(this, "reject %s with reason %d", callId, rejectReason);
Tyler Gunnfacfdee2020-01-23 13:10:37 -08002595 findConnectionForAction(callId, "reject").onReject(rejectReason);
2596 }
2597
Ravi Palurif4b38e72020-02-05 12:35:41 +05302598 private void transfer(String callId, Uri number, boolean isConfirmationRequired) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002599 Log.i(this, "transfer %s", callId);
Ravi Palurif4b38e72020-02-05 12:35:41 +05302600 findConnectionForAction(callId, "transfer").onTransfer(number, isConfirmationRequired);
2601 }
2602
2603 private void consultativeTransfer(String callId, String otherCallId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002604 Log.i(this, "consultativeTransfer %s", callId);
Ravi Palurif4b38e72020-02-05 12:35:41 +05302605 Connection connection1 = findConnectionForAction(callId, "consultativeTransfer");
2606 Connection connection2 = findConnectionForAction(otherCallId, " consultativeTransfer");
2607 connection1.onTransfer(connection2);
2608 }
2609
Bryce Leecac50772015-11-17 15:13:29 -08002610 private void silence(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002611 Log.i(this, "silence %s", callId);
Bryce Leecac50772015-11-17 15:13:29 -08002612 findConnectionForAction(callId, "silence").onSilence();
2613 }
2614
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002615 private void disconnect(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002616 Log.i(this, "disconnect %s", callId);
Santos Cordon0159ac02014-08-21 14:28:11 -07002617 if (mConnectionById.containsKey(callId)) {
2618 findConnectionForAction(callId, "disconnect").onDisconnect();
2619 } else {
2620 findConferenceForAction(callId, "disconnect").onDisconnect();
2621 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002622 }
2623
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002624 private void hold(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002625 Log.i(this, "hold %s", callId);
Santos Cordon0159ac02014-08-21 14:28:11 -07002626 if (mConnectionById.containsKey(callId)) {
2627 findConnectionForAction(callId, "hold").onHold();
2628 } else {
2629 findConferenceForAction(callId, "hold").onHold();
2630 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002631 }
2632
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002633 private void unhold(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002634 Log.i(this, "unhold %s", callId);
Santos Cordon0159ac02014-08-21 14:28:11 -07002635 if (mConnectionById.containsKey(callId)) {
2636 findConnectionForAction(callId, "unhold").onUnhold();
2637 } else {
2638 findConferenceForAction(callId, "unhold").onUnhold();
2639 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002640 }
2641
Yorke Lee4af59352015-05-13 14:14:54 -07002642 private void onCallAudioStateChanged(String callId, CallAudioState callAudioState) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002643 Log.i(this, "onAudioStateChanged %s %s", callId, callAudioState);
Yorke Leea0d3ca92014-09-15 19:18:13 -07002644 if (mConnectionById.containsKey(callId)) {
Yorke Lee4af59352015-05-13 14:14:54 -07002645 findConnectionForAction(callId, "onCallAudioStateChanged").setCallAudioState(
2646 callAudioState);
Yorke Leea0d3ca92014-09-15 19:18:13 -07002647 } else {
Yorke Lee4af59352015-05-13 14:14:54 -07002648 findConferenceForAction(callId, "onCallAudioStateChanged").setCallAudioState(
2649 callAudioState);
Yorke Leea0d3ca92014-09-15 19:18:13 -07002650 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07002651 }
2652
Junhoedf3d822022-11-24 09:26:37 +00002653 private void onCallEndpointChanged(String callId, CallEndpoint callEndpoint) {
2654 Log.i(this, "onCallEndpointChanged %s %s", callId, callEndpoint);
2655 if (mConnectionById.containsKey(callId)) {
2656 findConnectionForAction(callId, "onCallEndpointChanged").setCallEndpoint(callEndpoint);
2657 } else {
2658 findConferenceForAction(callId, "onCallEndpointChanged").setCallEndpoint(callEndpoint);
2659 }
2660 }
2661
2662 private void onAvailableCallEndpointsChanged(String callId,
2663 List<CallEndpoint> availableCallEndpoints) {
2664 Log.i(this, "onAvailableCallEndpointsChanged %s", callId);
2665 if (mConnectionById.containsKey(callId)) {
2666 findConnectionForAction(callId, "onAvailableCallEndpointsChanged")
2667 .setAvailableCallEndpoints(availableCallEndpoints);
2668 } else {
2669 findConferenceForAction(callId, "onAvailableCallEndpointsChanged")
2670 .setAvailableCallEndpoints(availableCallEndpoints);
2671 }
2672 }
2673
2674 private void onMuteStateChanged(String callId, boolean isMuted) {
2675 Log.i(this, "onMuteStateChanged %s %s", callId, isMuted);
2676 if (mConnectionById.containsKey(callId)) {
2677 findConnectionForAction(callId, "onMuteStateChanged").setMuteState(isMuted);
2678 } else {
2679 findConferenceForAction(callId, "onMuteStateChanged").setMuteState(isMuted);
2680 }
2681 }
2682
Grace Jiae99fde92021-01-19 14:58:01 -08002683 private void onUsingAlternativeUi(String callId, boolean isUsingAlternativeUi) {
2684 Log.i(this, "onUsingAlternativeUi %s %s", callId, isUsingAlternativeUi);
2685 if (mConnectionById.containsKey(callId)) {
2686 findConnectionForAction(callId, "onUsingAlternativeUi")
2687 .onUsingAlternativeUi(isUsingAlternativeUi);
2688 }
2689 }
2690
2691 private void onTrackedByNonUiService(String callId, boolean isTracked) {
2692 Log.i(this, "onTrackedByNonUiService %s %s", callId, isTracked);
2693 if (mConnectionById.containsKey(callId)) {
2694 findConnectionForAction(callId, "onTrackedByNonUiService")
2695 .onTrackedByNonUiService(isTracked);
2696 }
2697 }
2698
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002699 private void playDtmfTone(String callId, char digit) {
Wenting Xiong7f9f3482020-08-27 18:16:06 +08002700 Log.i(this, "playDtmfTone %s %s", callId, Log.pii(digit));
Yorke Leea0d3ca92014-09-15 19:18:13 -07002701 if (mConnectionById.containsKey(callId)) {
2702 findConnectionForAction(callId, "playDtmfTone").onPlayDtmfTone(digit);
2703 } else {
2704 findConferenceForAction(callId, "playDtmfTone").onPlayDtmfTone(digit);
2705 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002706 }
2707
2708 private void stopDtmfTone(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002709 Log.i(this, "stopDtmfTone %s", callId);
Yorke Leea0d3ca92014-09-15 19:18:13 -07002710 if (mConnectionById.containsKey(callId)) {
2711 findConnectionForAction(callId, "stopDtmfTone").onStopDtmfTone();
2712 } else {
2713 findConferenceForAction(callId, "stopDtmfTone").onStopDtmfTone();
2714 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002715 }
2716
Santos Cordon823fd3c2014-08-07 18:35:18 -07002717 private void conference(String callId1, String callId2) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002718 Log.i(this, "conference %s, %s", callId1, callId2);
Santos Cordon980acb92014-05-31 10:31:19 -07002719
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002720 // Attempt to get second connection or conference.
Santos Cordon823fd3c2014-08-07 18:35:18 -07002721 Connection connection2 = findConnectionForAction(callId2, "conference");
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002722 Conference conference2 = getNullConference();
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07002723 if (connection2 == getNullConnection()) {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002724 conference2 = findConferenceForAction(callId2, "conference");
2725 if (conference2 == getNullConference()) {
2726 Log.w(this, "Connection2 or Conference2 missing in conference request %s.",
2727 callId2);
2728 return;
2729 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002730 }
Santos Cordonb6939982014-06-04 20:20:58 -07002731
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002732 // Attempt to get first connection or conference and perform merge.
Ihab Awad50e35062014-09-30 09:17:03 -07002733 Connection connection1 = findConnectionForAction(callId1, "conference");
2734 if (connection1 == getNullConnection()) {
2735 Conference conference1 = findConferenceForAction(callId1, "addConnection");
2736 if (conference1 == getNullConference()) {
2737 Log.w(this,
2738 "Connection1 or Conference1 missing in conference request %s.",
2739 callId1);
2740 } else {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002741 // Call 1 is a conference.
2742 if (connection2 != getNullConnection()) {
2743 // Call 2 is a connection so merge via call 1 (conference).
2744 conference1.onMerge(connection2);
2745 } else {
2746 // Call 2 is ALSO a conference; this should never happen.
2747 Log.wtf(this, "There can only be one conference and an attempt was made to " +
2748 "merge two conferences.");
2749 return;
2750 }
Ihab Awad50e35062014-09-30 09:17:03 -07002751 }
2752 } else {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08002753 // Call 1 is a connection.
2754 if (conference2 != getNullConference()) {
2755 // Call 2 is a conference, so merge via call 2.
2756 conference2.onMerge(connection1);
2757 } else {
2758 // Call 2 is a connection, so merge together.
2759 onConference(connection1, connection2);
2760 }
Ihab Awad50e35062014-09-30 09:17:03 -07002761 }
Santos Cordon980acb92014-05-31 10:31:19 -07002762 }
2763
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002764 private void splitFromConference(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002765 Log.i(this, "splitFromConference(%s)", callId);
Santos Cordon980acb92014-05-31 10:31:19 -07002766
2767 Connection connection = findConnectionForAction(callId, "splitFromConference");
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07002768 if (connection == getNullConnection()) {
Santos Cordon980acb92014-05-31 10:31:19 -07002769 Log.w(this, "Connection missing in conference request %s.", callId);
2770 return;
2771 }
2772
Santos Cordon0159ac02014-08-21 14:28:11 -07002773 Conference conference = connection.getConference();
2774 if (conference != null) {
2775 conference.onSeparate(connection);
2776 }
Santos Cordon980acb92014-05-31 10:31:19 -07002777 }
2778
Santos Cordona4868042014-09-04 17:39:22 -07002779 private void mergeConference(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002780 Log.i(this, "mergeConference(%s)", callId);
Santos Cordona4868042014-09-04 17:39:22 -07002781 Conference conference = findConferenceForAction(callId, "mergeConference");
2782 if (conference != null) {
2783 conference.onMerge();
2784 }
2785 }
2786
2787 private void swapConference(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002788 Log.i(this, "swapConference(%s)", callId);
Santos Cordona4868042014-09-04 17:39:22 -07002789 Conference conference = findConferenceForAction(callId, "swapConference");
2790 if (conference != null) {
2791 conference.onSwap();
2792 }
2793 }
2794
Ravi Paluri404babb2020-01-23 19:02:44 +05302795 private void addConferenceParticipants(String callId, List<Uri> participants) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002796 Log.i(this, "addConferenceParticipants(%s)", callId);
Ravi Paluri404babb2020-01-23 19:02:44 +05302797 if (mConnectionById.containsKey(callId)) {
2798 findConnectionForAction(callId, "addConferenceParticipants")
2799 .onAddConferenceParticipants(participants);
2800 } else {
2801 findConferenceForAction(callId, "addConferenceParticipants")
2802 .onAddConferenceParticipants(participants);
2803 }
2804 }
2805
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002806 /**
2807 * Notifies a {@link Connection} of a request to pull an external call.
2808 *
2809 * See {@link Call#pullExternalCall()}.
2810 *
2811 * @param callId The ID of the call to pull.
2812 */
2813 private void pullExternalCall(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002814 Log.i(this, "pullExternalCall(%s)", callId);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002815 Connection connection = findConnectionForAction(callId, "pullExternalCall");
2816 if (connection != null) {
2817 connection.onPullExternalCall();
2818 }
2819 }
2820
2821 /**
2822 * Notifies a {@link Connection} of a call event.
2823 *
2824 * See {@link Call#sendCallEvent(String, Bundle)}.
2825 *
2826 * @param callId The ID of the call receiving the event.
2827 * @param event The event.
2828 * @param extras Extras associated with the event.
2829 */
2830 private void sendCallEvent(String callId, String event, Bundle extras) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002831 Log.i(this, "sendCallEvent(%s, %s)", callId, event);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002832 Connection connection = findConnectionForAction(callId, "sendCallEvent");
2833 if (connection != null) {
2834 connection.onCallEvent(event, extras);
2835 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002836 }
2837
Hall Liu73903142021-02-18 18:41:41 -08002838 private void onCallFilteringCompleted(String callId, Connection.CallFilteringCompletionInfo
2839 callFilteringCompletionInfo) {
2840 Log.i(this, "onCallFilteringCompleted(%s, %s)", callId, callFilteringCompletionInfo);
Hall Liu49cabcc2021-01-15 11:41:48 -08002841 Connection connection = findConnectionForAction(callId, "onCallFilteringCompleted");
2842 if (connection != null) {
Hall Liu73903142021-02-18 18:41:41 -08002843 connection.onCallFilteringCompleted(callFilteringCompletionInfo);
Hall Liu49cabcc2021-01-15 11:41:48 -08002844 }
2845 }
2846
Tyler Gunndee56a82016-03-23 16:06:34 -07002847 /**
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08002848 * Notifies a {@link Connection} that a handover has completed.
2849 *
2850 * @param callId The ID of the call which completed handover.
2851 */
2852 private void notifyHandoverComplete(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002853 Log.i(this, "notifyHandoverComplete(%s)", callId);
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08002854 Connection connection = findConnectionForAction(callId, "notifyHandoverComplete");
2855 if (connection != null) {
2856 connection.onHandoverComplete();
2857 }
2858 }
2859
2860 /**
Tyler Gunndee56a82016-03-23 16:06:34 -07002861 * Notifies a {@link Connection} or {@link Conference} of a change to the extras from Telecom.
2862 * <p>
2863 * These extra changes can originate from Telecom itself, or from an {@link InCallService} via
2864 * the {@link android.telecom.Call#putExtra(String, boolean)},
2865 * {@link android.telecom.Call#putExtra(String, int)},
2866 * {@link android.telecom.Call#putExtra(String, String)},
2867 * {@link Call#removeExtras(List)}.
2868 *
2869 * @param callId The ID of the call receiving the event.
2870 * @param extras The new extras bundle.
2871 */
2872 private void handleExtrasChanged(String callId, Bundle extras) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002873 Log.i(this, "handleExtrasChanged(%s, %s)", callId, extras);
Tyler Gunndee56a82016-03-23 16:06:34 -07002874 if (mConnectionById.containsKey(callId)) {
2875 findConnectionForAction(callId, "handleExtrasChanged").handleExtrasChanged(extras);
2876 } else if (mConferenceById.containsKey(callId)) {
2877 findConferenceForAction(callId, "handleExtrasChanged").handleExtrasChanged(extras);
2878 }
2879 }
2880
Hall Liub64ac4c2017-02-06 10:49:48 -08002881 private void startRtt(String callId, Connection.RttTextStream rttTextStream) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002882 Log.i(this, "startRtt(%s)", callId);
Hall Liub64ac4c2017-02-06 10:49:48 -08002883 if (mConnectionById.containsKey(callId)) {
2884 findConnectionForAction(callId, "startRtt").onStartRtt(rttTextStream);
2885 } else if (mConferenceById.containsKey(callId)) {
2886 Log.w(this, "startRtt called on a conference.");
2887 }
2888 }
2889
2890 private void stopRtt(String callId) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002891 Log.i(this, "stopRtt(%s)", callId);
Hall Liub64ac4c2017-02-06 10:49:48 -08002892 if (mConnectionById.containsKey(callId)) {
2893 findConnectionForAction(callId, "stopRtt").onStopRtt();
2894 } else if (mConferenceById.containsKey(callId)) {
2895 Log.w(this, "stopRtt called on a conference.");
2896 }
2897 }
2898
2899 private void handleRttUpgradeResponse(String callId, Connection.RttTextStream rttTextStream) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002900 Log.i(this, "handleRttUpgradeResponse(%s, %s)", callId, rttTextStream == null);
Hall Liub64ac4c2017-02-06 10:49:48 -08002901 if (mConnectionById.containsKey(callId)) {
2902 findConnectionForAction(callId, "handleRttUpgradeResponse")
2903 .handleRttUpgradeResponse(rttTextStream);
2904 } else if (mConferenceById.containsKey(callId)) {
2905 Log.w(this, "handleRttUpgradeResponse called on a conference.");
2906 }
2907 }
2908
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002909 private void onPostDialContinue(String callId, boolean proceed) {
Tyler Gunnffbcd892020-05-04 15:01:59 -07002910 Log.i(this, "onPostDialContinue(%s)", callId);
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002911 findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
Evan Charlton6dea4ac2014-06-03 14:07:13 -07002912 }
2913
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002914 private void onAdapterAttached() {
Ihab Awad9c3f1882014-06-30 21:17:13 -07002915 if (mAreAccountsInitialized) {
Santos Cordon52d8a152014-06-17 19:08:45 -07002916 // No need to query again if we already did it.
2917 return;
2918 }
2919
Tyler Gunn4c69fb32019-05-17 10:49:16 -07002920 String callingPackage = getOpPackageName();
2921
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002922 mAdapter.queryRemoteConnectionServices(new RemoteServiceCallback.Stub() {
Santos Cordon52d8a152014-06-17 19:08:45 -07002923 @Override
2924 public void onResult(
2925 final List<ComponentName> componentNames,
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002926 final List<IBinder> services) {
Brad Ebinger0c3541b2016-11-01 14:11:38 -07002927 mHandler.post(new android.telecom.Logging.Runnable("oAA.qRCS.oR", null /*lock*/) {
Ihab Awad6107bab2014-08-18 09:23:25 -07002928 @Override
Brad Ebinger0c3541b2016-11-01 14:11:38 -07002929 public void loggedRun() {
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002930 for (int i = 0; i < componentNames.size() && i < services.size(); i++) {
Santos Cordon52d8a152014-06-17 19:08:45 -07002931 mRemoteConnectionManager.addConnectionService(
2932 componentNames.get(i),
Sailesh Nepal2a46b902014-07-04 17:21:07 -07002933 IConnectionService.Stub.asInterface(services.get(i)));
Santos Cordon52d8a152014-06-17 19:08:45 -07002934 }
Ihab Awad5d0410f2014-07-30 10:07:40 -07002935 onAccountsInitialized();
Sailesh Nepalc5b01572014-07-14 16:29:44 -07002936 Log.d(this, "remote connection services found: " + services);
Santos Cordon52d8a152014-06-17 19:08:45 -07002937 }
Brad Ebinger0c3541b2016-11-01 14:11:38 -07002938 }.prepare());
Santos Cordon52d8a152014-06-17 19:08:45 -07002939 }
2940
2941 @Override
2942 public void onError() {
Brad Ebinger0c3541b2016-11-01 14:11:38 -07002943 mHandler.post(new android.telecom.Logging.Runnable("oAA.qRCS.oE", null /*lock*/) {
Ihab Awad6107bab2014-08-18 09:23:25 -07002944 @Override
Brad Ebinger0c3541b2016-11-01 14:11:38 -07002945 public void loggedRun() {
Ihab Awad9c3f1882014-06-30 21:17:13 -07002946 mAreAccountsInitialized = true;
Santos Cordon52d8a152014-06-17 19:08:45 -07002947 }
Brad Ebinger0c3541b2016-11-01 14:11:38 -07002948 }.prepare());
Santos Cordon52d8a152014-06-17 19:08:45 -07002949 }
Tyler Gunn4c69fb32019-05-17 10:49:16 -07002950 }, callingPackage);
Santos Cordon52d8a152014-06-17 19:08:45 -07002951 }
2952
Ihab Awadf8b69882014-07-25 15:14:01 -07002953 /**
2954 * Ask some other {@code ConnectionService} to create a {@code RemoteConnection} given an
Santos Cordona663f862014-10-29 13:49:58 -07002955 * incoming request. This is used by {@code ConnectionService}s that are registered with
2956 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} and want to be able to manage
2957 * SIM-based incoming calls.
Ihab Awadf8b69882014-07-25 15:14:01 -07002958 *
2959 * @param connectionManagerPhoneAccount See description at
2960 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
2961 * @param request Details about the incoming call.
2962 * @return The {@code Connection} object to satisfy this call, or {@code null} to
2963 * not handle the call.
2964 */
Grace Jia41895152021-01-19 13:57:51 -08002965 public final @Nullable RemoteConnection createRemoteIncomingConnection(
2966 @NonNull PhoneAccountHandle connectionManagerPhoneAccount,
2967 @NonNull ConnectionRequest request) {
Ihab Awadf8b69882014-07-25 15:14:01 -07002968 return mRemoteConnectionManager.createRemoteConnection(
2969 connectionManagerPhoneAccount, request, true);
Santos Cordon52d8a152014-06-17 19:08:45 -07002970 }
2971
2972 /**
Ihab Awadf8b69882014-07-25 15:14:01 -07002973 * Ask some other {@code ConnectionService} to create a {@code RemoteConnection} given an
Santos Cordona663f862014-10-29 13:49:58 -07002974 * outgoing request. This is used by {@code ConnectionService}s that are registered with
2975 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} and want to be able to use the
2976 * SIM-based {@code ConnectionService} to place its outgoing calls.
Ihab Awadf8b69882014-07-25 15:14:01 -07002977 *
2978 * @param connectionManagerPhoneAccount See description at
2979 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
Cuihtlauac ALVARADO0b3b2a52016-09-13 14:49:41 +02002980 * @param request Details about the outgoing call.
Ihab Awadf8b69882014-07-25 15:14:01 -07002981 * @return The {@code Connection} object to satisfy this call, or {@code null} to
2982 * not handle the call.
2983 */
Grace Jia41895152021-01-19 13:57:51 -08002984 public final @Nullable RemoteConnection createRemoteOutgoingConnection(
2985 @NonNull PhoneAccountHandle connectionManagerPhoneAccount,
2986 @NonNull ConnectionRequest request) {
Ihab Awadf8b69882014-07-25 15:14:01 -07002987 return mRemoteConnectionManager.createRemoteConnection(
2988 connectionManagerPhoneAccount, request, false);
2989 }
2990
2991 /**
Grace Jia9a09c672020-08-04 12:52:09 -07002992 * Ask some other {@code ConnectionService} to create a {@code RemoteConference} given an
2993 * incoming request. This is used by {@code ConnectionService}s that are registered with
2994 * {@link PhoneAccount#CAPABILITY_ADHOC_CONFERENCE_CALLING}.
2995 *
2996 * @param connectionManagerPhoneAccount See description at
2997 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
2998 * @param request Details about the incoming conference call.
2999 * @return The {@code RemoteConference} object to satisfy this call, or {@code null} to not
3000 * handle the call.
3001 */
3002 public final @Nullable RemoteConference createRemoteIncomingConference(
3003 @Nullable PhoneAccountHandle connectionManagerPhoneAccount,
3004 @Nullable ConnectionRequest request) {
3005 return mRemoteConnectionManager.createRemoteConference(connectionManagerPhoneAccount,
3006 request, true);
3007 }
3008
3009 /**
3010 * Ask some other {@code ConnectionService} to create a {@code RemoteConference} given an
3011 * outgoing request. This is used by {@code ConnectionService}s that are registered with
3012 * {@link PhoneAccount#CAPABILITY_ADHOC_CONFERENCE_CALLING}.
3013 *
3014 * @param connectionManagerPhoneAccount See description at
3015 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
3016 * @param request Details about the outgoing conference call.
3017 * @return The {@code RemoteConference} object to satisfy this call, or {@code null} to not
3018 * handle the call.
3019 */
3020 public final @Nullable RemoteConference createRemoteOutgoingConference(
3021 @Nullable PhoneAccountHandle connectionManagerPhoneAccount,
3022 @Nullable ConnectionRequest request) {
3023 return mRemoteConnectionManager.createRemoteConference(connectionManagerPhoneAccount,
3024 request, false);
3025 }
3026
3027 /**
Santos Cordona663f862014-10-29 13:49:58 -07003028 * Indicates to the relevant {@code RemoteConnectionService} that the specified
3029 * {@link RemoteConnection}s should be merged into a conference call.
3030 * <p>
3031 * If the conference request is successful, the method {@link #onRemoteConferenceAdded} will
3032 * be invoked.
3033 *
3034 * @param remoteConnection1 The first of the remote connections to conference.
3035 * @param remoteConnection2 The second of the remote connections to conference.
Ihab Awadb8e85c72014-08-23 20:34:57 -07003036 */
3037 public final void conferenceRemoteConnections(
Santos Cordona663f862014-10-29 13:49:58 -07003038 RemoteConnection remoteConnection1,
3039 RemoteConnection remoteConnection2) {
3040 mRemoteConnectionManager.conferenceRemoteConnections(remoteConnection1, remoteConnection2);
Ihab Awadb8e85c72014-08-23 20:34:57 -07003041 }
3042
3043 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -07003044 * Adds a new conference call. When a conference call is created either as a result of an
3045 * explicit request via {@link #onConference} or otherwise, the connection service should supply
3046 * an instance of {@link Conference} by invoking this method. A conference call provided by this
3047 * method will persist until {@link Conference#destroy} is invoked on the conference instance.
3048 *
3049 * @param conference The new conference object.
3050 */
3051 public final void addConference(Conference conference) {
Rekha Kumar07366812015-03-24 16:42:31 -07003052 Log.d(this, "addConference: conference=%s", conference);
3053
Santos Cordon823fd3c2014-08-07 18:35:18 -07003054 String id = addConferenceInternal(conference);
3055 if (id != null) {
3056 List<String> connectionIds = new ArrayList<>(2);
3057 for (Connection connection : conference.getConnections()) {
3058 if (mIdByConnection.containsKey(connection)) {
3059 connectionIds.add(mIdByConnection.get(connection));
3060 }
3061 }
Tyler Gunnf0500bd2015-09-01 10:59:48 -07003062 conference.setTelecomCallId(id);
Brad Ebinger0ae44ed2020-04-09 15:30:57 -07003063 ParcelableConference parcelableConference = new ParcelableConference.Builder(
3064 conference.getPhoneAccountHandle(), conference.getState())
3065 .setConnectionCapabilities(conference.getConnectionCapabilities())
3066 .setConnectionProperties(conference.getConnectionProperties())
3067 .setConnectionIds(connectionIds)
3068 .setVideoAttributes(conference.getVideoProvider() == null
3069 ? null : conference.getVideoProvider().getInterface(),
3070 conference.getVideoState())
3071 .setConnectTimeMillis(conference.getConnectTimeMillis(),
3072 conference.getConnectionStartElapsedRealtimeMillis())
3073 .setStatusHints(conference.getStatusHints())
3074 .setExtras(conference.getExtras())
3075 .setAddress(conference.getAddress(), conference.getAddressPresentation())
3076 .setCallerDisplayName(conference.getCallerDisplayName(),
3077 conference.getCallerDisplayNamePresentation())
3078 .setDisconnectCause(conference.getDisconnectCause())
3079 .setRingbackRequested(conference.isRingbackRequested())
3080 .setCallDirection(conference.getCallDirection())
3081 .build();
Andrew Lee0f51da32015-04-16 13:11:55 -07003082
Santos Cordon823fd3c2014-08-07 18:35:18 -07003083 mAdapter.addConferenceCall(id, parcelableConference);
Rekha Kumar07366812015-03-24 16:42:31 -07003084 mAdapter.setVideoProvider(id, conference.getVideoProvider());
3085 mAdapter.setVideoState(id, conference.getVideoState());
Tyler Gunn10362372020-04-08 13:12:30 -07003086 // In some instances a conference can start its life as a standalone call with just a
3087 // single participant; ensure we signal to Telecom in this case.
3088 if (!conference.isMultiparty()) {
3089 mAdapter.setConferenceState(id, conference.isMultiparty());
3090 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07003091
3092 // Go through any child calls and set the parent.
3093 for (Connection connection : conference.getConnections()) {
3094 String connectionId = mIdByConnection.get(connection);
3095 if (connectionId != null) {
3096 mAdapter.setIsConferenced(connectionId, id);
3097 }
3098 }
Pengquan Meng70c9885332017-10-02 18:09:03 -07003099 onConferenceAdded(conference);
Santos Cordon823fd3c2014-08-07 18:35:18 -07003100 }
3101 }
3102
3103 /**
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07003104 * Adds a connection created by the {@link ConnectionService} and informs telecom of the new
3105 * connection.
3106 *
3107 * @param phoneAccountHandle The phone account handle for the connection.
3108 * @param connection The connection to add.
3109 */
3110 public final void addExistingConnection(PhoneAccountHandle phoneAccountHandle,
3111 Connection connection) {
Tyler Gunn78da7812017-05-09 14:34:57 -07003112 addExistingConnection(phoneAccountHandle, connection, null /* conference */);
3113 }
3114
3115 /**
Pengquan Meng731c1a32017-11-21 18:01:13 -08003116 * Call to inform Telecom that your {@link ConnectionService} has released call resources (e.g
3117 * microphone, camera).
3118 *
Pengquan Menge3bf7e22018-02-22 17:30:04 -08003119 * <p>
3120 * The {@link ConnectionService} will be disconnected when it failed to call this method within
3121 * 5 seconds after {@link #onConnectionServiceFocusLost()} is called.
3122 *
Pengquan Meng731c1a32017-11-21 18:01:13 -08003123 * @see ConnectionService#onConnectionServiceFocusLost()
3124 */
3125 public final void connectionServiceFocusReleased() {
3126 mAdapter.onConnectionServiceFocusReleased();
3127 }
3128
3129 /**
Tyler Gunn78da7812017-05-09 14:34:57 -07003130 * Adds a connection created by the {@link ConnectionService} and informs telecom of the new
Tyler Gunn5567d742019-10-31 13:04:37 -07003131 * connection, as well as adding that connection to the specified conference.
3132 * <p>
3133 * Note: This API is intended ONLY for use by the Telephony stack to provide an easy way to add
3134 * IMS conference participants to be added to a conference in a single step; this helps ensure
3135 * UI updates happen atomically, rather than adding the connection and then adding it to
3136 * the conference in another step.
Tyler Gunn78da7812017-05-09 14:34:57 -07003137 *
3138 * @param phoneAccountHandle The phone account handle for the connection.
3139 * @param connection The connection to add.
3140 * @param conference The parent conference of the new connection.
3141 * @hide
3142 */
Tyler Gunn5567d742019-10-31 13:04:37 -07003143 @SystemApi
3144 public final void addExistingConnection(@NonNull PhoneAccountHandle phoneAccountHandle,
3145 @NonNull Connection connection, @NonNull Conference conference) {
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07003146
Tyler Gunnf0500bd2015-09-01 10:59:48 -07003147 String id = addExistingConnectionInternal(phoneAccountHandle, connection);
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07003148 if (id != null) {
3149 List<String> emptyList = new ArrayList<>(0);
Tyler Gunn78da7812017-05-09 14:34:57 -07003150 String conferenceId = null;
3151 if (conference != null) {
3152 conferenceId = mIdByConference.get(conference);
3153 }
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07003154
3155 ParcelableConnection parcelableConnection = new ParcelableConnection(
3156 phoneAccountHandle,
3157 connection.getState(),
Ihab Awad5c9c86e2014-11-12 13:41:16 -08003158 connection.getConnectionCapabilities(),
Tyler Gunn720c6642016-03-22 09:02:47 -07003159 connection.getConnectionProperties(),
Christine Hallstrom2830ce92016-11-30 16:06:42 -08003160 connection.getSupportedAudioRoutes(),
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07003161 connection.getAddress(),
3162 connection.getAddressPresentation(),
3163 connection.getCallerDisplayName(),
3164 connection.getCallerDisplayNamePresentation(),
3165 connection.getVideoProvider() == null ?
3166 null : connection.getVideoProvider().getInterface(),
3167 connection.getVideoState(),
3168 connection.isRingbackRequested(),
3169 connection.getAudioModeIsVoip(),
Roshan Piuse927ec02015-07-15 15:47:21 -07003170 connection.getConnectTimeMillis(),
Tyler Gunnc9503d62020-01-27 10:30:51 -08003171 connection.getConnectionStartElapsedRealtimeMillis(),
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07003172 connection.getStatusHints(),
3173 connection.getDisconnectCause(),
Santos Cordon6b7f9552015-05-27 17:21:45 -07003174 emptyList,
Tyler Gunn78da7812017-05-09 14:34:57 -07003175 connection.getExtras(),
Tyler Gunn6986a632019-06-25 13:45:32 -07003176 conferenceId,
Tyler Gunnd57d76c2019-09-24 14:53:23 -07003177 connection.getCallDirection(),
3178 Connection.VERIFICATION_STATUS_NOT_VERIFIED);
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07003179 mAdapter.addExistingConnection(id, parcelableConnection);
3180 }
3181 }
3182
3183 /**
Ihab Awadf8b69882014-07-25 15:14:01 -07003184 * Returns all the active {@code Connection}s for which this {@code ConnectionService}
3185 * has taken responsibility.
3186 *
3187 * @return A collection of {@code Connection}s created by this {@code ConnectionService}.
Santos Cordonb6939982014-06-04 20:20:58 -07003188 */
Sailesh Nepal091768c2014-06-30 15:15:23 -07003189 public final Collection<Connection> getAllConnections() {
Santos Cordonb6939982014-06-04 20:20:58 -07003190 return mConnectionById.values();
3191 }
3192
3193 /**
Santos Cordona6018b92016-02-16 14:23:12 -08003194 * Returns all the active {@code Conference}s for which this {@code ConnectionService}
3195 * has taken responsibility.
3196 *
3197 * @return A collection of {@code Conference}s created by this {@code ConnectionService}.
3198 */
3199 public final Collection<Conference> getAllConferences() {
3200 return mConferenceById.values();
3201 }
3202
3203 /**
Ihab Awadf8b69882014-07-25 15:14:01 -07003204 * Create a {@code Connection} given an incoming request. This is used to attach to existing
3205 * incoming calls.
Evan Charltonbf11f982014-07-20 22:06:28 -07003206 *
Ihab Awadf8b69882014-07-25 15:14:01 -07003207 * @param connectionManagerPhoneAccount See description at
3208 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
3209 * @param request Details about the incoming call.
3210 * @return The {@code Connection} object to satisfy this call, or {@code null} to
3211 * not handle the call.
Ihab Awad542e0ea2014-05-16 10:22:16 -07003212 */
Ihab Awadf8b69882014-07-25 15:14:01 -07003213 public Connection onCreateIncomingConnection(
3214 PhoneAccountHandle connectionManagerPhoneAccount,
3215 ConnectionRequest request) {
3216 return null;
3217 }
Ravi Paluri80aa2142019-12-02 11:57:37 +05303218 /**
Grace Jia8587ee52020-07-10 15:42:32 -07003219 * Create a {@code Conference} given an incoming request. This is used to attach to an incoming
3220 * conference call initiated via
3221 * {@link TelecomManager#addNewIncomingConference(PhoneAccountHandle, Bundle)}.
Ravi Paluri80aa2142019-12-02 11:57:37 +05303222 *
3223 * @param connectionManagerPhoneAccount See description at
3224 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
Grace Jia8587ee52020-07-10 15:42:32 -07003225 * @param request Details about the incoming conference call.
Grace Jia41895152021-01-19 13:57:51 -08003226 * @return The {@code Conference} object to satisfy this call. If the conference attempt is
3227 * failed, the return value will be a result of an invocation of
3228 * {@link Connection#createFailedConnection(DisconnectCause)}.
3229 * Return {@code null} if the {@link ConnectionService} cannot handle the call.
Ravi Paluri80aa2142019-12-02 11:57:37 +05303230 */
3231 public @Nullable Conference onCreateIncomingConference(
Grace Jia41895152021-01-19 13:57:51 -08003232 @NonNull PhoneAccountHandle connectionManagerPhoneAccount,
3233 @NonNull ConnectionRequest request) {
Ravi Paluri80aa2142019-12-02 11:57:37 +05303234 return null;
3235 }
Sailesh Nepalc5b01572014-07-14 16:29:44 -07003236
3237 /**
Tyler Gunn041a1fe2017-05-12 10:04:49 -07003238 * Called after the {@link Connection} returned by
3239 * {@link #onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}
3240 * or {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)} has been
3241 * added to the {@link ConnectionService} and sent to Telecom.
3242 *
3243 * @param connection the {@link Connection}.
3244 * @hide
3245 */
3246 public void onCreateConnectionComplete(Connection connection) {
3247 }
3248
3249 /**
Ravi Paluri80aa2142019-12-02 11:57:37 +05303250 * Called after the {@link Conference} returned by
3251 * {@link #onCreateIncomingConference(PhoneAccountHandle, ConnectionRequest)}
3252 * or {@link #onCreateOutgoingConference(PhoneAccountHandle, ConnectionRequest)} has been
3253 * added to the {@link ConnectionService} and sent to Telecom.
3254 *
3255 * @param conference the {@link Conference}.
3256 * @hide
3257 */
3258 public void onCreateConferenceComplete(Conference conference) {
3259 }
3260
3261
3262 /**
Tyler Gunnf5035432017-01-09 09:43:12 -08003263 * Called by Telecom to inform the {@link ConnectionService} that its request to create a new
3264 * incoming {@link Connection} was denied.
3265 * <p>
3266 * Used when a self-managed {@link ConnectionService} attempts to create a new incoming
3267 * {@link Connection}, but Telecom has determined that the call cannot be allowed at this time.
3268 * The {@link ConnectionService} is responsible for silently rejecting the new incoming
3269 * {@link Connection}.
3270 * <p>
3271 * See {@link TelecomManager#isIncomingCallPermitted(PhoneAccountHandle)} for more information.
3272 *
Tyler Gunn159f35c2017-03-02 09:28:37 -08003273 * @param connectionManagerPhoneAccount See description at
3274 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
Tyler Gunnf5035432017-01-09 09:43:12 -08003275 * @param request The incoming connection request.
3276 */
Tyler Gunn159f35c2017-03-02 09:28:37 -08003277 public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount,
3278 ConnectionRequest request) {
Tyler Gunnf5035432017-01-09 09:43:12 -08003279 }
3280
3281 /**
3282 * Called by Telecom to inform the {@link ConnectionService} that its request to create a new
3283 * outgoing {@link Connection} was denied.
3284 * <p>
3285 * Used when a self-managed {@link ConnectionService} attempts to create a new outgoing
3286 * {@link Connection}, but Telecom has determined that the call cannot be placed at this time.
3287 * The {@link ConnectionService} is responisible for informing the user that the
3288 * {@link Connection} cannot be made at this time.
3289 * <p>
3290 * See {@link TelecomManager#isOutgoingCallPermitted(PhoneAccountHandle)} for more information.
3291 *
Tyler Gunn159f35c2017-03-02 09:28:37 -08003292 * @param connectionManagerPhoneAccount See description at
3293 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
Tyler Gunnf5035432017-01-09 09:43:12 -08003294 * @param request The outgoing connection request.
3295 */
Tyler Gunn159f35c2017-03-02 09:28:37 -08003296 public void onCreateOutgoingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount,
3297 ConnectionRequest request) {
Tyler Gunnf5035432017-01-09 09:43:12 -08003298 }
3299
3300 /**
Ravi Paluri80aa2142019-12-02 11:57:37 +05303301 * Called by Telecom to inform the {@link ConnectionService} that its request to create a new
3302 * incoming {@link Conference} was denied.
3303 * <p>
3304 * Used when a self-managed {@link ConnectionService} attempts to create a new incoming
3305 * {@link Conference}, but Telecom has determined that the call cannot be allowed at this time.
3306 * The {@link ConnectionService} is responsible for silently rejecting the new incoming
3307 * {@link Conference}.
3308 * <p>
3309 * See {@link TelecomManager#isIncomingCallPermitted(PhoneAccountHandle)} for more information.
3310 *
3311 * @param connectionManagerPhoneAccount See description at
3312 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
3313 * @param request The incoming connection request.
3314 */
3315 public void onCreateIncomingConferenceFailed(
3316 @Nullable PhoneAccountHandle connectionManagerPhoneAccount,
3317 @Nullable ConnectionRequest request) {
3318 }
3319
3320 /**
3321 * Called by Telecom to inform the {@link ConnectionService} that its request to create a new
3322 * outgoing {@link Conference} was denied.
3323 * <p>
3324 * Used when a self-managed {@link ConnectionService} attempts to create a new outgoing
3325 * {@link Conference}, but Telecom has determined that the call cannot be placed at this time.
3326 * The {@link ConnectionService} is responisible for informing the user that the
3327 * {@link Conference} cannot be made at this time.
3328 * <p>
3329 * See {@link TelecomManager#isOutgoingCallPermitted(PhoneAccountHandle)} for more information.
3330 *
3331 * @param connectionManagerPhoneAccount See description at
3332 * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
3333 * @param request The outgoing connection request.
3334 */
3335 public void onCreateOutgoingConferenceFailed(
Grace Jia41895152021-01-19 13:57:51 -08003336 @NonNull PhoneAccountHandle connectionManagerPhoneAccount,
3337 @NonNull ConnectionRequest request) {
Ravi Paluri80aa2142019-12-02 11:57:37 +05303338 }
3339
3340
3341 /**
Shriram Ganesh6bf35ac2014-12-11 17:53:38 -08003342 * Trigger recalculate functinality for conference calls. This is used when a Telephony
3343 * Connection is part of a conference controller but is not yet added to Connection
3344 * Service and hence cannot be added to the conference call.
3345 *
3346 * @hide
3347 */
3348 public void triggerConferenceRecalculate() {
3349 }
3350
3351 /**
Ihab Awadf8b69882014-07-25 15:14:01 -07003352 * Create a {@code Connection} given an outgoing request. This is used to initiate new
3353 * outgoing calls.
Sailesh Nepalc5b01572014-07-14 16:29:44 -07003354 *
Ihab Awadf8b69882014-07-25 15:14:01 -07003355 * @param connectionManagerPhoneAccount The connection manager account to use for managing
3356 * this call.
3357 * <p>
3358 * If this parameter is not {@code null}, it means that this {@code ConnectionService}
3359 * has registered one or more {@code PhoneAccount}s having
3360 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}. This parameter will contain
3361 * one of these {@code PhoneAccount}s, while the {@code request} will contain another
3362 * (usually but not always distinct) {@code PhoneAccount} to be used for actually
3363 * making the connection.
3364 * <p>
3365 * If this parameter is {@code null}, it means that this {@code ConnectionService} is
3366 * being asked to make a direct connection. The
3367 * {@link ConnectionRequest#getAccountHandle()} of parameter {@code request} will be
3368 * a {@code PhoneAccount} registered by this {@code ConnectionService} to use for
3369 * making the connection.
3370 * @param request Details about the outgoing call.
3371 * @return The {@code Connection} object to satisfy this call, or the result of an invocation
Andrew Lee7f3d41f2014-09-11 17:33:16 -07003372 * of {@link Connection#createFailedConnection(DisconnectCause)} to not handle the call.
Sailesh Nepalc5b01572014-07-14 16:29:44 -07003373 */
Ihab Awadf8b69882014-07-25 15:14:01 -07003374 public Connection onCreateOutgoingConnection(
3375 PhoneAccountHandle connectionManagerPhoneAccount,
3376 ConnectionRequest request) {
3377 return null;
3378 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07003379
3380 /**
Ravi Paluri80aa2142019-12-02 11:57:37 +05303381 * Create a {@code Conference} given an outgoing request. This is used to initiate new
Grace Jia8587ee52020-07-10 15:42:32 -07003382 * outgoing conference call requested via
3383 * {@link TelecomManager#startConference(List, Bundle)}.
Ravi Paluri80aa2142019-12-02 11:57:37 +05303384 *
3385 * @param connectionManagerPhoneAccount The connection manager account to use for managing
3386 * this call.
3387 * <p>
3388 * If this parameter is not {@code null}, it means that this {@code ConnectionService}
3389 * has registered one or more {@code PhoneAccount}s having
3390 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}. This parameter will contain
3391 * one of these {@code PhoneAccount}s, while the {@code request} will contain another
3392 * (usually but not always distinct) {@code PhoneAccount} to be used for actually
3393 * making the connection.
3394 * <p>
3395 * If this parameter is {@code null}, it means that this {@code ConnectionService} is
3396 * being asked to make a direct connection. The
3397 * {@link ConnectionRequest#getAccountHandle()} of parameter {@code request} will be
3398 * a {@code PhoneAccount} registered by this {@code ConnectionService} to use for
3399 * making the connection.
3400 * @param request Details about the outgoing call.
Grace Jia41895152021-01-19 13:57:51 -08003401 * @return The {@code Conference} object to satisfy this call. If the conference attempt is
3402 * failed, the return value will be a result of an invocation of
3403 * {@link Connection#createFailedConnection(DisconnectCause)}.
3404 * Return {@code null} if the {@link ConnectionService} cannot handle the call.
Ravi Paluri80aa2142019-12-02 11:57:37 +05303405 */
3406 public @Nullable Conference onCreateOutgoingConference(
Grace Jia41895152021-01-19 13:57:51 -08003407 @NonNull PhoneAccountHandle connectionManagerPhoneAccount,
3408 @NonNull ConnectionRequest request) {
Ravi Paluri80aa2142019-12-02 11:57:37 +05303409 return null;
3410 }
3411
3412
3413 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08003414 * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
3415 * outgoing handover {@link Connection}.
3416 * <p>
3417 * A call handover is the process where an ongoing call is transferred from one app (i.e.
3418 * {@link ConnectionService} to another app. The user could, for example, choose to continue a
3419 * mobile network call in a video calling app. The mobile network call via the Telephony stack
3420 * is referred to as the source of the handover, and the video calling app is referred to as the
3421 * destination.
3422 * <p>
3423 * When considering a handover scenario the <em>initiating</em> device is where a user initiated
3424 * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
3425 * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
3426 * device.
3427 * <p>
3428 * This method is called on the destination {@link ConnectionService} on <em>initiating</em>
3429 * device when the user initiates a handover request from one app to another. The user request
3430 * originates in the {@link InCallService} via
3431 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
3432 * <p>
3433 * For a full discussion of the handover process and the APIs involved, see
3434 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
3435 * <p>
3436 * Implementations of this method should return an instance of {@link Connection} which
3437 * represents the handover. If your app does not wish to accept a handover to it at this time,
3438 * you can return {@code null}. The code below shows an example of how this is done.
3439 * <pre>
3440 * {@code
3441 * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
3442 * fromPhoneAccountHandle, ConnectionRequest request) {
3443 * if (!isHandoverAvailable()) {
3444 * return null;
3445 * }
3446 * MyConnection connection = new MyConnection();
3447 * connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
3448 * connection.setVideoState(request.getVideoState());
3449 * return connection;
3450 * }
3451 * }
3452 * </pre>
3453 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07003454 * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
3455 * ConnectionService which needs to handover the call.
Tyler Gunn9d127732018-03-02 15:45:51 -08003456 * @param request Details about the call to handover.
3457 * @return {@link Connection} instance corresponding to the handover call.
Sanket Padawea8eddd42017-11-03 11:07:35 -07003458 */
3459 public Connection onCreateOutgoingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
3460 ConnectionRequest request) {
3461 return null;
3462 }
3463
3464 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08003465 * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
3466 * incoming handover {@link Connection}.
3467 * <p>
3468 * A call handover is the process where an ongoing call is transferred from one app (i.e.
3469 * {@link ConnectionService} to another app. The user could, for example, choose to continue a
3470 * mobile network call in a video calling app. The mobile network call via the Telephony stack
3471 * is referred to as the source of the handover, and the video calling app is referred to as the
3472 * destination.
3473 * <p>
3474 * When considering a handover scenario the <em>initiating</em> device is where a user initiated
3475 * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
3476 * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
3477 * device.
3478 * <p>
3479 * This method is called on the destination app on the <em>receiving</em> device when the
3480 * destination app calls {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to
3481 * accept an incoming handover from the <em>initiating</em> device.
3482 * <p>
3483 * For a full discussion of the handover process and the APIs involved, see
3484 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
3485 * <p>
3486 * Implementations of this method should return an instance of {@link Connection} which
3487 * represents the handover. The code below shows an example of how this is done.
3488 * <pre>
3489 * {@code
3490 * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
3491 * fromPhoneAccountHandle, ConnectionRequest request) {
3492 * // Given that your app requested to accept the handover, you should not return null here.
3493 * MyConnection connection = new MyConnection();
3494 * connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
3495 * connection.setVideoState(request.getVideoState());
3496 * return connection;
3497 * }
3498 * }
3499 * </pre>
3500 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07003501 * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
3502 * ConnectionService which needs to handover the call.
3503 * @param request Details about the call which needs to be handover.
Tyler Gunn9d127732018-03-02 15:45:51 -08003504 * @return {@link Connection} instance corresponding to the handover call.
Sanket Padawea8eddd42017-11-03 11:07:35 -07003505 */
3506 public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
3507 ConnectionRequest request) {
3508 return null;
3509 }
3510
3511 /**
3512 * Called by Telecom in response to a {@code TelecomManager#acceptHandover()}
3513 * invocation which failed.
Tyler Gunn9d127732018-03-02 15:45:51 -08003514 * <p>
3515 * For a full discussion of the handover process and the APIs involved, see
3516 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}
3517 *
3518 * @param request Details about the call which failed to handover.
3519 * @param error Reason for handover failure. Will be one of the
Sanket Padawea8eddd42017-11-03 11:07:35 -07003520 */
Tyler Gunn9d127732018-03-02 15:45:51 -08003521 public void onHandoverFailed(ConnectionRequest request,
3522 @Call.Callback.HandoverFailureErrors int error) {
Sanket Padawea8eddd42017-11-03 11:07:35 -07003523 return;
3524 }
3525
3526 /**
Roopa Sattiraju45de470c2022-01-27 21:31:35 -08003527 * Calls of this type are created using
3528 * {@link TelecomManager#addNewUnknownCall(PhoneAccountHandle, Bundle)}. Unknown calls
3529 * are used for representing calls which become known to the {@link ConnectionService}
3530 * midway through the call.
3531 *
3532 * For example, a call transferred from one device to answer would surface as an active
3533 * call in Telecom instead of going through a typical Ringing to Active transition, or
3534 * Dialing to Active transition.
3535 *
3536 * A {@link ConnectionService} can return {@code null} (the default behavior)
3537 * if it is not able to handle a request for the requested unknown connection.
3538 *
3539 * {@link TelecomManager#addNewIncomingCall(PhoneAccountHandle, android.os.Bundle)}.
Yorke Leec3cf9822014-10-02 09:38:39 -07003540 *
Etienne Ruffieuxb99333d2022-02-25 16:11:01 +00003541 * @param connectionManagerPhoneAccount The connection manager account to use for managing
3542 * this call
3543 * @param request Details about the outgoing call
3544 * @return The {@code Connection} object to satisfy this call, or the result of an invocation
3545 * of {@link Connection#createFailedConnection(DisconnectCause)} to not handle the call
Yorke Lee770ed6e2014-10-06 18:58:52 -07003546 * @hide
Yorke Leec3cf9822014-10-02 09:38:39 -07003547 */
Etienne Ruffieuxb99333d2022-02-25 16:11:01 +00003548 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
Roopa Sattiraju45de470c2022-01-27 21:31:35 -08003549 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
3550 public @Nullable Connection onCreateUnknownConnection(
3551 @NonNull PhoneAccountHandle connectionManagerPhoneAccount,
3552 @NonNull ConnectionRequest request) {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07003553 return null;
Yorke Leec3cf9822014-10-02 09:38:39 -07003554 }
3555
3556 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -07003557 * Conference two specified connections. Invoked when the user has made a request to merge the
3558 * specified connections into a conference call. In response, the connection service should
3559 * create an instance of {@link Conference} and pass it into {@link #addConference}.
Santos Cordonb6939982014-06-04 20:20:58 -07003560 *
Santos Cordon823fd3c2014-08-07 18:35:18 -07003561 * @param connection1 A connection to merge into a conference call.
3562 * @param connection2 A connection to merge into a conference call.
Santos Cordonb6939982014-06-04 20:20:58 -07003563 */
Santos Cordon823fd3c2014-08-07 18:35:18 -07003564 public void onConference(Connection connection1, Connection connection2) {}
Santos Cordonb6939982014-06-04 20:20:58 -07003565
Santos Cordona663f862014-10-29 13:49:58 -07003566 /**
Pengquan Meng70c9885332017-10-02 18:09:03 -07003567 * Called when a connection is added.
3568 * @hide
3569 */
3570 public void onConnectionAdded(Connection connection) {}
3571
3572 /**
3573 * Called when a connection is removed.
3574 * @hide
3575 */
3576 public void onConnectionRemoved(Connection connection) {}
3577
3578 /**
3579 * Called when a conference is added.
3580 * @hide
3581 */
3582 public void onConferenceAdded(Conference conference) {}
3583
3584 /**
3585 * Called when a conference is removed.
3586 * @hide
3587 */
3588 public void onConferenceRemoved(Conference conference) {}
3589
3590 /**
Santos Cordona663f862014-10-29 13:49:58 -07003591 * Indicates that a remote conference has been created for existing {@link RemoteConnection}s.
3592 * When this method is invoked, this {@link ConnectionService} should create its own
3593 * representation of the conference call and send it to telecom using {@link #addConference}.
3594 * <p>
3595 * This is only relevant to {@link ConnectionService}s which are registered with
3596 * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}.
3597 *
3598 * @param conference The remote conference call.
3599 */
Ihab Awadb8e85c72014-08-23 20:34:57 -07003600 public void onRemoteConferenceAdded(RemoteConference conference) {}
3601
Santos Cordon823fd3c2014-08-07 18:35:18 -07003602 /**
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07003603 * Called when an existing connection is added remotely.
3604 * @param connection The existing connection which was added.
3605 */
3606 public void onRemoteExistingConnectionAdded(RemoteConnection connection) {}
3607
3608 /**
Pengquan Meng731c1a32017-11-21 18:01:13 -08003609 * Called when the {@link ConnectionService} has lost the call focus.
3610 * The {@link ConnectionService} should release the call resources and invokes
3611 * {@link ConnectionService#connectionServiceFocusReleased()} to inform telecom that it has
3612 * released the call resources.
3613 */
3614 public void onConnectionServiceFocusLost() {}
3615
3616 /**
3617 * Called when the {@link ConnectionService} has gained the call focus. The
3618 * {@link ConnectionService} can acquire the call resources at this time.
3619 */
3620 public void onConnectionServiceFocusGained() {}
3621
3622 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -07003623 * @hide
3624 */
3625 public boolean containsConference(Conference conference) {
3626 return mIdByConference.containsKey(conference);
3627 }
3628
Ihab Awadb8e85c72014-08-23 20:34:57 -07003629 /** {@hide} */
3630 void addRemoteConference(RemoteConference remoteConference) {
3631 onRemoteConferenceAdded(remoteConference);
3632 }
3633
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07003634 /** {@hide} */
3635 void addRemoteExistingConnection(RemoteConnection remoteConnection) {
3636 onRemoteExistingConnectionAdded(remoteConnection);
3637 }
3638
Ihab Awad5d0410f2014-07-30 10:07:40 -07003639 private void onAccountsInitialized() {
3640 mAreAccountsInitialized = true;
3641 for (Runnable r : mPreInitializationConnectionRequests) {
3642 r.run();
3643 }
3644 mPreInitializationConnectionRequests.clear();
3645 }
3646
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07003647 /**
Tyler Gunnf0500bd2015-09-01 10:59:48 -07003648 * Adds an existing connection to the list of connections, identified by a new call ID unique
3649 * to this connection service.
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07003650 *
3651 * @param connection The connection.
Tyler Gunnf0500bd2015-09-01 10:59:48 -07003652 * @return The ID of the connection (e.g. the call-id).
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07003653 */
Tyler Gunnf0500bd2015-09-01 10:59:48 -07003654 private String addExistingConnectionInternal(PhoneAccountHandle handle, Connection connection) {
3655 String id;
Tyler Gunncd6ccfd2016-10-17 15:48:19 -07003656
3657 if (connection.getExtras() != null && connection.getExtras()
3658 .containsKey(Connection.EXTRA_ORIGINAL_CONNECTION_ID)) {
3659 id = connection.getExtras().getString(Connection.EXTRA_ORIGINAL_CONNECTION_ID);
3660 Log.d(this, "addExistingConnectionInternal - conn %s reusing original id %s",
3661 connection.getTelecomCallId(), id);
3662 } else if (handle == null) {
Tyler Gunnf0500bd2015-09-01 10:59:48 -07003663 // If no phone account handle was provided, we cannot be sure the call ID is unique,
3664 // so just use a random UUID.
3665 id = UUID.randomUUID().toString();
3666 } else {
3667 // Phone account handle was provided, so use the ConnectionService class name as a
3668 // prefix for a unique incremental call ID.
3669 id = handle.getComponentName().getClassName() + "@" + getNextCallId();
3670 }
Pengquan Meng70c9885332017-10-02 18:09:03 -07003671 addConnection(handle, id, connection);
Tyler Gunn4a57b9b2014-10-30 14:27:48 -07003672 return id;
3673 }
3674
Pengquan Meng70c9885332017-10-02 18:09:03 -07003675 private void addConnection(PhoneAccountHandle handle, String callId, Connection connection) {
Tyler Gunnf0500bd2015-09-01 10:59:48 -07003676 connection.setTelecomCallId(callId);
Ihab Awad542e0ea2014-05-16 10:22:16 -07003677 mConnectionById.put(callId, connection);
3678 mIdByConnection.put(connection, callId);
3679 connection.addConnectionListener(mConnectionListener);
Santos Cordon823fd3c2014-08-07 18:35:18 -07003680 connection.setConnectionService(this);
Pengquan Meng70c9885332017-10-02 18:09:03 -07003681 connection.setPhoneAccountHandle(handle);
3682 onConnectionAdded(connection);
Ihab Awad542e0ea2014-05-16 10:22:16 -07003683 }
3684
Anthony Lee30e65842014-11-06 16:30:53 -08003685 /** {@hide} */
3686 protected void removeConnection(Connection connection) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07003687 connection.unsetConnectionService(this);
Ihab Awad542e0ea2014-05-16 10:22:16 -07003688 connection.removeConnectionListener(mConnectionListener);
Chenjie Luoe370b532016-05-12 16:59:43 -07003689 String id = mIdByConnection.get(connection);
3690 if (id != null) {
3691 mConnectionById.remove(id);
3692 mIdByConnection.remove(connection);
3693 mAdapter.removeCall(id);
Pengquan Meng70c9885332017-10-02 18:09:03 -07003694 onConnectionRemoved(connection);
Chenjie Luoe370b532016-05-12 16:59:43 -07003695 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07003696 }
3697
Santos Cordon823fd3c2014-08-07 18:35:18 -07003698 private String addConferenceInternal(Conference conference) {
Tyler Gunncd6ccfd2016-10-17 15:48:19 -07003699 String originalId = null;
3700 if (conference.getExtras() != null && conference.getExtras()
3701 .containsKey(Connection.EXTRA_ORIGINAL_CONNECTION_ID)) {
3702 originalId = conference.getExtras().getString(Connection.EXTRA_ORIGINAL_CONNECTION_ID);
3703 Log.d(this, "addConferenceInternal: conf %s reusing original id %s",
3704 conference.getTelecomCallId(),
3705 originalId);
3706 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07003707 if (mIdByConference.containsKey(conference)) {
3708 Log.w(this, "Re-adding an existing conference: %s.", conference);
3709 } else if (conference != null) {
Tyler Gunnf0500bd2015-09-01 10:59:48 -07003710 // Conferences do not (yet) have a PhoneAccountHandle associated with them, so we
3711 // cannot determine a ConnectionService class name to associate with the ID, so use
3712 // a unique UUID (for now).
Tyler Gunncd6ccfd2016-10-17 15:48:19 -07003713 String id = originalId == null ? UUID.randomUUID().toString() : originalId;
Santos Cordon823fd3c2014-08-07 18:35:18 -07003714 mConferenceById.put(id, conference);
3715 mIdByConference.put(conference, id);
3716 conference.addListener(mConferenceListener);
3717 return id;
3718 }
3719
3720 return null;
3721 }
3722
3723 private void removeConference(Conference conference) {
3724 if (mIdByConference.containsKey(conference)) {
3725 conference.removeListener(mConferenceListener);
3726
3727 String id = mIdByConference.get(conference);
3728 mConferenceById.remove(id);
3729 mIdByConference.remove(conference);
3730 mAdapter.removeCall(id);
Pengquan Meng70c9885332017-10-02 18:09:03 -07003731
3732 onConferenceRemoved(conference);
Santos Cordon823fd3c2014-08-07 18:35:18 -07003733 }
3734 }
3735
Ihab Awad542e0ea2014-05-16 10:22:16 -07003736 private Connection findConnectionForAction(String callId, String action) {
Tyler Gunn0a88f2e2017-06-16 20:20:34 -07003737 if (callId != null && mConnectionById.containsKey(callId)) {
Ihab Awad542e0ea2014-05-16 10:22:16 -07003738 return mConnectionById.get(callId);
3739 }
Ihab Awad60ac30b2014-05-20 22:32:12 -07003740 Log.w(this, "%s - Cannot find Connection %s", action, callId);
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07003741 return getNullConnection();
3742 }
3743
3744 static synchronized Connection getNullConnection() {
3745 if (sNullConnection == null) {
3746 sNullConnection = new Connection() {};
3747 }
3748 return sNullConnection;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07003749 }
Santos Cordon0159ac02014-08-21 14:28:11 -07003750
3751 private Conference findConferenceForAction(String conferenceId, String action) {
3752 if (mConferenceById.containsKey(conferenceId)) {
3753 return mConferenceById.get(conferenceId);
3754 }
3755 Log.w(this, "%s - Cannot find conference %s", action, conferenceId);
3756 return getNullConference();
3757 }
3758
Ihab Awadb8e85c72014-08-23 20:34:57 -07003759 private List<String> createConnectionIdList(List<Connection> connections) {
3760 List<String> ids = new ArrayList<>();
3761 for (Connection c : connections) {
3762 if (mIdByConnection.containsKey(c)) {
3763 ids.add(mIdByConnection.get(c));
3764 }
3765 }
3766 Collections.sort(ids);
3767 return ids;
3768 }
3769
Tyler Gunn6d76ca02014-11-17 15:49:51 -08003770 /**
3771 * Builds a list of {@link Connection} and {@link Conference} IDs based on the list of
Tyler Gunndf2cbc82015-04-20 09:13:01 -07003772 * {@link Conferenceable}s passed in.
Tyler Gunn6d76ca02014-11-17 15:49:51 -08003773 *
Tyler Gunndf2cbc82015-04-20 09:13:01 -07003774 * @param conferenceables The {@link Conferenceable} connections and conferences.
Tyler Gunn6d76ca02014-11-17 15:49:51 -08003775 * @return List of string conference and call Ids.
3776 */
Tyler Gunndf2cbc82015-04-20 09:13:01 -07003777 private List<String> createIdList(List<Conferenceable> conferenceables) {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08003778 List<String> ids = new ArrayList<>();
Tyler Gunndf2cbc82015-04-20 09:13:01 -07003779 for (Conferenceable c : conferenceables) {
Tyler Gunn6d76ca02014-11-17 15:49:51 -08003780 // Only allow Connection and Conference conferenceables.
3781 if (c instanceof Connection) {
3782 Connection connection = (Connection) c;
3783 if (mIdByConnection.containsKey(connection)) {
3784 ids.add(mIdByConnection.get(connection));
3785 }
3786 } else if (c instanceof Conference) {
3787 Conference conference = (Conference) c;
3788 if (mIdByConference.containsKey(conference)) {
3789 ids.add(mIdByConference.get(conference));
3790 }
3791 }
3792 }
3793 Collections.sort(ids);
3794 return ids;
3795 }
3796
Santos Cordon0159ac02014-08-21 14:28:11 -07003797 private Conference getNullConference() {
3798 if (sNullConference == null) {
3799 sNullConference = new Conference(null) {};
3800 }
3801 return sNullConference;
3802 }
Santos Cordon29f2f2e2014-09-11 19:50:24 -07003803
3804 private void endAllConnections() {
3805 // Unbound from telecomm. We should end all connections and conferences.
3806 for (Connection connection : mIdByConnection.keySet()) {
3807 // only operate on top-level calls. Conference calls will be removed on their own.
3808 if (connection.getConference() == null) {
3809 connection.onDisconnect();
3810 }
3811 }
3812 for (Conference conference : mIdByConference.keySet()) {
3813 conference.onDisconnect();
3814 }
3815 }
Tyler Gunnf0500bd2015-09-01 10:59:48 -07003816
3817 /**
3818 * Retrieves the next call ID as maintainted by the connection service.
3819 *
3820 * @return The call ID.
3821 */
3822 private int getNextCallId() {
Brad Ebingerb32d4f82016-10-24 16:40:49 -07003823 synchronized (mIdSyncRoot) {
Tyler Gunnf0500bd2015-09-01 10:59:48 -07003824 return ++mId;
3825 }
3826 }
Brad Ebinger99f17ce2019-09-11 18:06:51 -07003827
3828 /**
3829 * Returns this handler, ONLY FOR TESTING.
3830 * @hide
3831 */
3832 @VisibleForTesting
3833 public Handler getHandler() {
3834 return mHandler;
3835 }
Tyler Gunnc7e07b92021-04-06 11:40:57 -07003836
3837 /**
3838 * Sets this {@link ConnectionService} ready for testing purposes.
3839 * @hide
3840 */
3841 @VisibleForTesting
3842 public void setReadyForTest() {
3843 mAreAccountsInitialized = true;
3844 }
Santos Cordon980acb92014-05-31 10:31:19 -07003845}