blob: 1822cee89eaa9afae26f6516cb5cef167efc45b2 [file] [log] [blame]
Ihab Awade63fadb2014-07-09 21:52:04 -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 Awade63fadb2014-07-09 21:52:04 -070018
Hall Liu95d55872017-01-25 17:12:49 -080019import android.annotation.IntDef;
20import android.annotation.Nullable;
Andrew Leeda80c872015-04-15 14:09:50 -070021import android.annotation.SystemApi;
Mathew Inwood42346d12018-08-01 11:33:05 +010022import android.annotation.UnsupportedAppUsage;
Ihab Awade63fadb2014-07-09 21:52:04 -070023import android.net.Uri;
Tyler Gunn6e3ecc42018-11-12 11:30:56 -080024import android.os.Build;
Nancy Chen10798dc2014-08-08 14:00:25 -070025import android.os.Bundle;
Andrew Lee011728f2015-04-23 15:47:06 -070026import android.os.Handler;
Hall Liu95d55872017-01-25 17:12:49 -080027import android.os.ParcelFileDescriptor;
Ihab Awade63fadb2014-07-09 21:52:04 -070028
Hall Liu95d55872017-01-25 17:12:49 -080029import java.io.IOException;
30import java.io.InputStreamReader;
31import java.io.OutputStreamWriter;
Hall Liu95d55872017-01-25 17:12:49 -080032import java.lang.annotation.Retention;
33import java.lang.annotation.RetentionPolicy;
34import java.nio.charset.StandardCharsets;
Ihab Awade63fadb2014-07-09 21:52:04 -070035import java.util.ArrayList;
Tyler Gunn071be6f2016-05-10 14:52:33 -070036import java.util.Arrays;
Ihab Awade63fadb2014-07-09 21:52:04 -070037import java.util.Collections;
38import java.util.List;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070039import java.util.Map;
Ihab Awade63fadb2014-07-09 21:52:04 -070040import java.util.Objects;
Jay Shrauner229e3822014-08-15 09:23:07 -070041import java.util.concurrent.CopyOnWriteArrayList;
Ihab Awade63fadb2014-07-09 21:52:04 -070042
43/**
44 * Represents an ongoing phone call that the in-call app should present to the user.
45 */
46public final class Call {
47 /**
48 * The state of a {@code Call} when newly created.
49 */
50 public static final int STATE_NEW = 0;
51
52 /**
53 * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
54 */
55 public static final int STATE_DIALING = 1;
56
57 /**
58 * The state of an incoming {@code Call} when ringing locally, but not yet connected.
59 */
60 public static final int STATE_RINGING = 2;
61
62 /**
63 * The state of a {@code Call} when in a holding state.
64 */
65 public static final int STATE_HOLDING = 3;
66
67 /**
68 * The state of a {@code Call} when actively supporting conversation.
69 */
70 public static final int STATE_ACTIVE = 4;
71
72 /**
73 * The state of a {@code Call} when no further voice or other communication is being
74 * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
75 * is no longer active, and the local data transport has or inevitably will release resources
76 * associated with this {@code Call}.
77 */
78 public static final int STATE_DISCONNECTED = 7;
79
Nancy Chen5da0fd52014-07-08 14:16:17 -070080 /**
Santos Cordone3c507b2015-04-23 14:44:19 -070081 * The state of an outgoing {@code Call} when waiting on user to select a
82 * {@link PhoneAccount} through which to place the call.
Nancy Chen5da0fd52014-07-08 14:16:17 -070083 */
Santos Cordone3c507b2015-04-23 14:44:19 -070084 public static final int STATE_SELECT_PHONE_ACCOUNT = 8;
85
86 /**
87 * @hide
88 * @deprecated use STATE_SELECT_PHONE_ACCOUNT.
89 */
90 @Deprecated
91 @SystemApi
92 public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT;
Nancy Chen5da0fd52014-07-08 14:16:17 -070093
Nancy Chene20930f2014-08-07 16:17:21 -070094 /**
Nancy Chene9b7a8e2014-08-08 14:26:27 -070095 * The initial state of an outgoing {@code Call}.
96 * Common transitions are to {@link #STATE_DIALING} state for a successful call or
97 * {@link #STATE_DISCONNECTED} if it failed.
Nancy Chene20930f2014-08-07 16:17:21 -070098 */
99 public static final int STATE_CONNECTING = 9;
100
Nancy Chen513c8922014-09-17 14:47:20 -0700101 /**
Tyler Gunn4afc6af2014-10-07 10:14:55 -0700102 * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
103 * call has not yet been disconnected by the underlying {@code ConnectionService}. The next
104 * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
105 */
106 public static final int STATE_DISCONNECTING = 10;
107
108 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700109 * The state of an external call which is in the process of being pulled from a remote device to
110 * the local device.
111 * <p>
112 * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
113 * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
114 * <p>
115 * An {@link InCallService} will only see this state if it has the
116 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
117 * manifest.
118 */
119 public static final int STATE_PULLING_CALL = 11;
120
121 /**
Nancy Chen513c8922014-09-17 14:47:20 -0700122 * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
123 * extras. Used to pass the phone accounts to display on the front end to the user in order to
124 * select phone accounts to (for example) place a call.
Hall Liu34d9e242018-11-21 17:05:58 -0800125 * @deprecated Use the list from {@link #EXTRA_SUGGESTED_PHONE_ACCOUNTS} instead.
Nancy Chen513c8922014-09-17 14:47:20 -0700126 */
Hall Liu34d9e242018-11-21 17:05:58 -0800127 @Deprecated
Nancy Chen513c8922014-09-17 14:47:20 -0700128 public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
129
mike dooley4af561f2016-12-20 08:55:17 -0800130 /**
Hall Liu34d9e242018-11-21 17:05:58 -0800131 * Key for extra used to pass along a list of {@link PhoneAccountSuggestion}s to the in-call
132 * UI when a call enters the {@link #STATE_SELECT_PHONE_ACCOUNT} state. The list included here
133 * will have the same length and be in the same order as the list passed with
134 * {@link #AVAILABLE_PHONE_ACCOUNTS}.
135 */
136 public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS =
137 "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS";
138
139 /**
mike dooley91217422017-03-09 12:58:42 -0800140 * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC)
141 * when the last outgoing emergency call was made. This is used to identify potential emergency
142 * callbacks.
mike dooley4af561f2016-12-20 08:55:17 -0800143 */
144 public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
145 "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
146
Usman Abdullah47b392d2019-03-06 15:54:56 -0800147
148 /**
149 * Extra key used to indicate whether a {@link CallScreeningService} has requested to silence
150 * the ringtone for a call. If the {@link InCallService} declares
151 * {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} in its manifest, it should not
152 * play a ringtone for an incoming call with this extra key set.
153 */
154 public static final String EXTRA_SILENT_RINGING_REQUESTED =
155 "android.telecom.extra.SILENT_RINGING_REQUESTED";
156
Tyler Gunn8bf76572017-04-06 15:30:08 -0700157 /**
158 * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
159 * Telecom that the user has requested that the current {@link Call} should be handed over
160 * to another {@link ConnectionService}.
161 * <p>
162 * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
163 * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
164 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700165 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
166 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700167 */
168 public static final String EVENT_REQUEST_HANDOVER =
169 "android.telecom.event.REQUEST_HANDOVER";
170
171 /**
172 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
173 * {@link PhoneAccountHandle} to which a call should be handed over to.
174 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700175 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
176 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700177 */
178 public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
179 "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
180
181 /**
182 * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
183 * video state of the call when it is handed over to the new {@link PhoneAccount}.
184 * <p>
185 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
186 * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
187 * {@link VideoProfile#STATE_TX_ENABLED}.
188 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700189 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
190 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700191 */
192 public static final String EXTRA_HANDOVER_VIDEO_STATE =
193 "android.telecom.extra.HANDOVER_VIDEO_STATE";
194
195 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700196 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Used by the
197 * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra
198 * information to the handover {@link ConnectionService} specified by
199 * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}.
200 * <p>
201 * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the
202 * {@link ConnectionService} via the request extras when
203 * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
204 * is called to initate the handover.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700205 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700206 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
207 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700208 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700209 public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700210
211 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700212 * Call event sent from Telecom to the handover {@link ConnectionService} via
213 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
214 * to the {@link ConnectionService} has completed successfully.
215 * <p>
216 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700217 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700218 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
219 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700220 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700221 public static final String EVENT_HANDOVER_COMPLETE =
222 "android.telecom.event.HANDOVER_COMPLETE";
Tyler Gunn34a2b312017-06-23 08:32:00 -0700223
224 /**
225 * Call event sent from Telecom to the handover destination {@link ConnectionService} via
226 * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the
227 * source connection has disconnected. The {@link Bundle} parameter for the call event will be
228 * {@code null}.
229 * <p>
230 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
231 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700232 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
233 * APIs instead.
Tyler Gunn34a2b312017-06-23 08:32:00 -0700234 */
235 public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
236 "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
237
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700238 /**
239 * Call event sent from Telecom to the handover {@link ConnectionService} via
240 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
241 * to the {@link ConnectionService} has failed.
242 * <p>
243 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
244 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700245 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
246 * APIs instead.
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700247 */
248 public static final String EVENT_HANDOVER_FAILED =
249 "android.telecom.event.HANDOVER_FAILED";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700250
Ihab Awade63fadb2014-07-09 21:52:04 -0700251 public static class Details {
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -0800252 /** @hide */
253 @Retention(RetentionPolicy.SOURCE)
254 @IntDef(
255 prefix = { "DIRECTION_" },
256 value = {DIRECTION_UNKNOWN, DIRECTION_INCOMING, DIRECTION_OUTGOING})
257 public @interface CallDirection {}
258
259 /**
260 * Indicates that the call is neither and incoming nor an outgoing call. This can be the
261 * case for calls reported directly by a {@link ConnectionService} in special cases such as
262 * call handovers.
263 */
264 public static final int DIRECTION_UNKNOWN = -1;
265
266 /**
267 * Indicates that the call is an incoming call.
268 */
269 public static final int DIRECTION_INCOMING = 0;
270
271 /**
272 * Indicates that the call is an outgoing call.
273 */
274 public static final int DIRECTION_OUTGOING = 1;
275
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800276
277 /** Call can currently be put on hold or unheld. */
278 public static final int CAPABILITY_HOLD = 0x00000001;
279
280 /** Call supports the hold feature. */
281 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
282
283 /**
284 * Calls within a conference can be merged. A {@link ConnectionService} has the option to
285 * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
286 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
287 * capability allows a merge button to be shown while the conference call is in the foreground
288 * of the in-call UI.
289 * <p>
290 * This is only intended for use by a {@link Conference}.
291 */
292 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
293
294 /**
295 * Calls within a conference can be swapped between foreground and background.
296 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
297 * <p>
298 * This is only intended for use by a {@link Conference}.
299 */
300 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
301
302 /**
303 * @hide
304 */
Andrew Lee2378ea72015-04-29 14:38:11 -0700305 public static final int CAPABILITY_UNUSED_1 = 0x00000010;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800306
307 /** Call supports responding via text option. */
308 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
309
310 /** Call can be muted. */
311 public static final int CAPABILITY_MUTE = 0x00000040;
312
313 /**
314 * Call supports conference call management. This capability only applies to {@link Conference}
315 * calls which can have {@link Connection}s as children.
316 */
317 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
318
319 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700320 * Local device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800321 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700322 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800323
324 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700325 * Local device supports transmitting video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800326 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700327 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800328
329 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700330 * Local device supports bidirectional video calling.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800331 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700332 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700333 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800334
335 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700336 * Remote device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800337 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700338 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
339
340 /**
341 * Remote device supports transmitting video.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700342 */
343 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
344
345 /**
346 * Remote device supports bidirectional video calling.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700347 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700348 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700349 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800350
351 /**
352 * Call is able to be separated from its parent {@code Conference}, if any.
353 */
354 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
355
356 /**
357 * Call is able to be individually disconnected when in a {@code Conference}.
358 */
359 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
360
361 /**
Dong Zhou89f41eb2015-03-15 11:59:49 -0500362 * Speed up audio setup for MT call.
363 * @hide
364 */
Tyler Gunn96d6c402015-03-18 12:39:23 -0700365 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
366
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700367 /**
368 * Call can be upgraded to a video call.
Rekha Kumar07366812015-03-24 16:42:31 -0700369 * @hide
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800370 * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
371 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call
372 * whether or not video calling is supported.
Rekha Kumar07366812015-03-24 16:42:31 -0700373 */
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800374 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
Rekha Kumar07366812015-03-24 16:42:31 -0700375 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
376
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700377 /**
378 * For video calls, indicates whether the outgoing video for the call can be paused using
Yorke Lee32f24732015-05-12 16:18:03 -0700379 * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700380 */
381 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
382
Bryce Lee81901682015-08-28 16:38:02 -0700383 /**
384 * Call sends responses through connection.
385 * @hide
386 */
Tyler Gunnf97a0092016-01-19 15:59:34 -0800387 public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;
388
389 /**
390 * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
391 * <p>
392 * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
393 * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
394 * downgraded from a video call back to a VideoState of
395 * {@link VideoProfile#STATE_AUDIO_ONLY}.
396 * <p>
397 * Intuitively, a call which can be downgraded to audio should also have local and remote
398 * video
399 * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
400 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
401 */
402 public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
Bryce Lee81901682015-08-28 16:38:02 -0700403
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700404 /**
405 * When set for an external call, indicates that this {@code Call} can be pulled from a
406 * remote device to the current device.
407 * <p>
408 * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
409 * <p>
410 * An {@link InCallService} will only see calls with this capability if it has the
411 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
412 * in its manifest.
413 * <p>
414 * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
Tyler Gunn720c6642016-03-22 09:02:47 -0700415 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700416 */
417 public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
418
Pooja Jaind34698d2017-12-28 14:15:31 +0530419 /** Call supports the deflect feature. */
420 public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
421
Tyler Gunnd11a3152015-03-18 13:09:14 -0700422 //******************************************************************************************
Pooja Jaind34698d2017-12-28 14:15:31 +0530423 // Next CAPABILITY value: 0x02000000
Andrew Lee2378ea72015-04-29 14:38:11 -0700424 //******************************************************************************************
425
426 /**
427 * Whether the call is currently a conference.
428 */
429 public static final int PROPERTY_CONFERENCE = 0x00000001;
430
431 /**
432 * Whether the call is a generic conference, where we do not know the precise state of
433 * participants in the conference (eg. on CDMA).
434 */
435 public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
436
437 /**
438 * Whether the call is made while the device is in emergency callback mode.
439 */
440 public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
441
442 /**
443 * Connection is using WIFI.
444 */
445 public static final int PROPERTY_WIFI = 0x00000008;
446
447 /**
Tyler Gunn6b6ae552018-10-11 10:42:10 -0700448 * When set, the UI should indicate to the user that a call is using high definition
449 * audio.
450 * <p>
451 * The underlying {@link ConnectionService} is responsible for reporting this
452 * property. It is important to note that this property is not intended to report the
453 * actual audio codec being used for a Call, but whether the call should be indicated
454 * to the user as high definition.
455 * <p>
456 * The Android Telephony stack reports this property for calls based on a number
457 * of factors, including which audio codec is used and whether a call is using an HD
458 * codec end-to-end. Some mobile operators choose to suppress display of an HD indication,
459 * and in these cases this property will not be set for a call even if the underlying audio
460 * codec is in fact "high definition".
Andrew Lee2378ea72015-04-29 14:38:11 -0700461 */
462 public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
463
Tony Maka68dcce2015-12-17 09:31:18 +0000464 /**
Tony Mak53b5df42016-05-19 13:40:38 +0100465 * Whether the call is associated with the work profile.
466 */
467 public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;
468
469 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700470 * When set, indicates that this {@code Call} does not actually exist locally for the
471 * {@link ConnectionService}.
472 * <p>
473 * Consider, for example, a scenario where a user has two phones with the same phone number.
474 * When a user places a call on one device, the telephony stack can represent that call on
475 * the other device by adding it to the {@link ConnectionService} with the
Tyler Gunn720c6642016-03-22 09:02:47 -0700476 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700477 * <p>
478 * An {@link InCallService} will only see calls with this property if it has the
479 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
480 * in its manifest.
481 * <p>
Tyler Gunn720c6642016-03-22 09:02:47 -0700482 * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700483 */
484 public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
485
Brad Ebinger15847072016-05-18 11:08:36 -0700486 /**
487 * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
488 */
489 public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
490
Tyler Gunn24e18332017-02-10 09:42:49 -0800491 /**
492 * Indicates that the call is from a self-managed {@link ConnectionService}.
493 * <p>
494 * See also {@link Connection#PROPERTY_SELF_MANAGED}
495 */
496 public static final int PROPERTY_SELF_MANAGED = 0x00000100;
497
Eric Erfanianec881872017-12-06 16:27:53 -0800498 /**
499 * Indicates the call used Assisted Dialing.
500 * See also {@link Connection#PROPERTY_ASSISTED_DIALING_USED}
501 * @hide
502 */
503 public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200;
504
Hall Liue9041242018-02-09 16:40:03 -0800505 /**
506 * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
507 * {@link RttCall} object that is used to send and receive text.
508 */
509 public static final int PROPERTY_RTT = 0x00000400;
510
Tyler Gunn5bd90852018-09-21 09:37:07 -0700511 /**
512 * Indicates that the call has been identified as the network as an emergency call. This
513 * property may be set for both incoming and outgoing calls which the network identifies as
514 * emergency calls.
515 */
516 public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 0x00000800;
517
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700518 /**
519 * Indicates that the call is using VoIP audio mode.
520 * <p>
521 * When this property is set, the {@link android.media.AudioManager} audio mode for this
522 * call will be {@link android.media.AudioManager#MODE_IN_COMMUNICATION}. When this
523 * property is not set, the audio mode for this call will be
524 * {@link android.media.AudioManager#MODE_IN_CALL}.
525 * <p>
526 * This property reflects changes made using {@link Connection#setAudioModeIsVoip(boolean)}.
527 * <p>
528 * You can use this property to determine whether an un-answered incoming call or a held
529 * call will use VoIP audio mode (if the call does not currently have focus, the system
530 * audio mode may not reflect the mode the call will use).
531 */
532 public static final int PROPERTY_VOIP_AUDIO_MODE = 0x00001000;
533
Andrew Lee2378ea72015-04-29 14:38:11 -0700534 //******************************************************************************************
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700535 // Next PROPERTY value: 0x00002000
Tyler Gunnd11a3152015-03-18 13:09:14 -0700536 //******************************************************************************************
Tyler Gunn068085b2015-02-06 13:56:52 -0800537
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800538 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700539 private final Uri mHandle;
540 private final int mHandlePresentation;
541 private final String mCallerDisplayName;
542 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700543 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700544 private final int mCallCapabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700545 private final int mCallProperties;
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800546 private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700547 private final DisconnectCause mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700548 private final long mConnectTimeMillis;
549 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700550 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700551 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700552 private final Bundle mExtras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700553 private final Bundle mIntentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700554 private final long mCreationTimeMillis;
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -0800555 private final @CallDirection int mCallDirection;
Ihab Awade63fadb2014-07-09 21:52:04 -0700556
557 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800558 * Whether the supplied capabilities supports the specified capability.
559 *
560 * @param capabilities A bit field of capabilities.
561 * @param capability The capability to check capabilities for.
562 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800563 */
564 public static boolean can(int capabilities, int capability) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800565 return (capabilities & capability) == capability;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800566 }
567
568 /**
569 * Whether the capabilities of this {@code Details} supports the specified capability.
570 *
571 * @param capability The capability to check capabilities for.
572 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800573 */
574 public boolean can(int capability) {
575 return can(mCallCapabilities, capability);
576 }
577
578 /**
579 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
580 *
581 * @param capabilities A capability bit field.
582 * @return A human readable string representation.
583 */
584 public static String capabilitiesToString(int capabilities) {
585 StringBuilder builder = new StringBuilder();
586 builder.append("[Capabilities:");
587 if (can(capabilities, CAPABILITY_HOLD)) {
588 builder.append(" CAPABILITY_HOLD");
589 }
590 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
591 builder.append(" CAPABILITY_SUPPORT_HOLD");
592 }
593 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
594 builder.append(" CAPABILITY_MERGE_CONFERENCE");
595 }
596 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
597 builder.append(" CAPABILITY_SWAP_CONFERENCE");
598 }
599 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
600 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
601 }
602 if (can(capabilities, CAPABILITY_MUTE)) {
603 builder.append(" CAPABILITY_MUTE");
604 }
605 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
606 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
607 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700608 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
609 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
610 }
611 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
612 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
613 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700614 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
615 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800616 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700617 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
618 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
619 }
620 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
621 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
622 }
Tyler Gunnf97a0092016-01-19 15:59:34 -0800623 if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
624 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
625 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700626 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
627 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800628 }
Dong Zhou89f41eb2015-03-15 11:59:49 -0500629 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
Tyler Gunnd11a3152015-03-18 13:09:14 -0700630 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
Dong Zhou89f41eb2015-03-15 11:59:49 -0500631 }
Rekha Kumar07366812015-03-24 16:42:31 -0700632 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
633 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
634 }
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700635 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
636 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
637 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700638 if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
639 builder.append(" CAPABILITY_CAN_PULL_CALL");
640 }
Pooja Jaind34698d2017-12-28 14:15:31 +0530641 if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
642 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
643 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800644 builder.append("]");
645 return builder.toString();
646 }
647
648 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700649 * Whether the supplied properties includes the specified property.
650 *
651 * @param properties A bit field of properties.
652 * @param property The property to check properties for.
653 * @return Whether the specified property is supported.
654 */
655 public static boolean hasProperty(int properties, int property) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800656 return (properties & property) == property;
Andrew Lee2378ea72015-04-29 14:38:11 -0700657 }
658
659 /**
660 * Whether the properties of this {@code Details} includes the specified property.
661 *
662 * @param property The property to check properties for.
663 * @return Whether the specified property is supported.
664 */
665 public boolean hasProperty(int property) {
666 return hasProperty(mCallProperties, property);
667 }
668
669 /**
670 * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
671 *
672 * @param properties A property bit field.
673 * @return A human readable string representation.
674 */
675 public static String propertiesToString(int properties) {
676 StringBuilder builder = new StringBuilder();
677 builder.append("[Properties:");
678 if (hasProperty(properties, PROPERTY_CONFERENCE)) {
679 builder.append(" PROPERTY_CONFERENCE");
680 }
681 if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
682 builder.append(" PROPERTY_GENERIC_CONFERENCE");
683 }
684 if (hasProperty(properties, PROPERTY_WIFI)) {
685 builder.append(" PROPERTY_WIFI");
686 }
687 if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
688 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
689 }
690 if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
Yorke Leebe2a4a22015-06-12 10:10:55 -0700691 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
Andrew Lee2378ea72015-04-29 14:38:11 -0700692 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700693 if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
694 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
695 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700696 if (hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
Brad Ebinger15847072016-05-18 11:08:36 -0700697 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
698 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700699 if (hasProperty(properties, PROPERTY_ASSISTED_DIALING_USED)) {
Eric Erfanianec881872017-12-06 16:27:53 -0800700 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
701 }
Tyler Gunn5bd90852018-09-21 09:37:07 -0700702 if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
703 builder.append(" PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL");
704 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700705 if (hasProperty(properties, PROPERTY_RTT)) {
706 builder.append(" PROPERTY_RTT");
707 }
708 if (hasProperty(properties, PROPERTY_VOIP_AUDIO_MODE)) {
709 builder.append(" PROPERTY_VOIP_AUDIO_MODE");
710 }
Andrew Lee2378ea72015-04-29 14:38:11 -0700711 builder.append("]");
712 return builder.toString();
713 }
714
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800715 /** {@hide} */
716 public String getTelecomCallId() {
717 return mTelecomCallId;
718 }
719
Andrew Lee2378ea72015-04-29 14:38:11 -0700720 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700721 * @return The handle (e.g., phone number) to which the {@code Call} is currently
722 * connected.
723 */
724 public Uri getHandle() {
725 return mHandle;
726 }
727
728 /**
729 * @return The presentation requirements for the handle. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700730 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700731 */
732 public int getHandlePresentation() {
733 return mHandlePresentation;
734 }
735
736 /**
Tyler Gunn7e45b722018-12-04 12:56:45 -0800737 * The display name for the caller.
738 * <p>
739 * This is the name as reported by the {@link ConnectionService} associated with this call.
Tyler Gunn7e45b722018-12-04 12:56:45 -0800740 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700741 * @return The display name for the caller.
742 */
743 public String getCallerDisplayName() {
744 return mCallerDisplayName;
745 }
746
747 /**
748 * @return The presentation requirements for the caller display name. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700749 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700750 */
751 public int getCallerDisplayNamePresentation() {
752 return mCallerDisplayNamePresentation;
753 }
754
755 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700756 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
757 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700758 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700759 public PhoneAccountHandle getAccountHandle() {
760 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -0700761 }
762
763 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800764 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
765 * {@code CAPABILITY_*} constants in this class.
Ihab Awade63fadb2014-07-09 21:52:04 -0700766 */
Ihab Awad5d0410f2014-07-30 10:07:40 -0700767 public int getCallCapabilities() {
768 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700769 }
770
771 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700772 * @return A bitmask of the properties of the {@code Call}, as defined by the various
773 * {@code PROPERTY_*} constants in this class.
Andrew Lee223ad142014-08-27 16:33:08 -0700774 */
775 public int getCallProperties() {
776 return mCallProperties;
777 }
778
779 /**
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800780 * @return a bitmask of the audio routes available for the call.
781 *
782 * @hide
783 */
784 public int getSupportedAudioRoutes() {
785 return mSupportedAudioRoutes;
786 }
787
788 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700789 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
Nancy Chenf4cf77c2014-09-19 10:53:21 -0700790 * by {@link android.telecom.DisconnectCause}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700791 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700792 public DisconnectCause getDisconnectCause() {
793 return mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700794 }
795
796 /**
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700797 * Returns the time the {@link Call} connected (i.e. became active). This information is
798 * updated periodically, but user interfaces should not rely on this to display the "call
799 * time clock". For the time when the call was first added to Telecom, see
800 * {@link #getCreationTimeMillis()}.
801 *
802 * @return The time the {@link Call} connected in milliseconds since the epoch.
Ihab Awade63fadb2014-07-09 21:52:04 -0700803 */
Jay Shrauner164a0ac2015-04-14 18:16:10 -0700804 public final long getConnectTimeMillis() {
Ihab Awade63fadb2014-07-09 21:52:04 -0700805 return mConnectTimeMillis;
806 }
807
808 /**
809 * @return Information about any calling gateway the {@code Call} may be using.
810 */
811 public GatewayInfo getGatewayInfo() {
812 return mGatewayInfo;
813 }
814
Andrew Lee7a341382014-07-15 17:05:08 -0700815 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -0700816 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -0700817 */
818 public int getVideoState() {
819 return mVideoState;
820 }
821
Ihab Awad5d0410f2014-07-30 10:07:40 -0700822 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700823 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
Ihab Awad5d0410f2014-07-30 10:07:40 -0700824 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -0700825 */
826 public StatusHints getStatusHints() {
827 return mStatusHints;
828 }
829
Nancy Chen10798dc2014-08-08 14:00:25 -0700830 /**
Santos Cordon6b7f9552015-05-27 17:21:45 -0700831 * @return The extras associated with this call.
Nancy Chen10798dc2014-08-08 14:00:25 -0700832 */
833 public Bundle getExtras() {
834 return mExtras;
835 }
836
Santos Cordon6b7f9552015-05-27 17:21:45 -0700837 /**
838 * @return The extras used with the original intent to place this call.
839 */
840 public Bundle getIntentExtras() {
841 return mIntentExtras;
842 }
843
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700844 /**
845 * Returns the time when the call was first created and added to Telecom. This is the same
846 * time that is logged as the start time in the Call Log (see
847 * {@link android.provider.CallLog.Calls#DATE}). To determine when the call was connected
848 * (became active), see {@link #getConnectTimeMillis()}.
849 *
850 * @return The creation time of the call, in millis since the epoch.
851 */
852 public long getCreationTimeMillis() {
853 return mCreationTimeMillis;
854 }
855
Tyler Gunn7e45b722018-12-04 12:56:45 -0800856 /**
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -0800857 * Indicates whether the call is an incoming or outgoing call.
858 * @return The call's direction.
859 */
860 public @CallDirection int getCallDirection() {
861 return mCallDirection;
862 }
863
Ihab Awade63fadb2014-07-09 21:52:04 -0700864 @Override
865 public boolean equals(Object o) {
866 if (o instanceof Details) {
867 Details d = (Details) o;
868 return
869 Objects.equals(mHandle, d.mHandle) &&
870 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
871 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
872 Objects.equals(mCallerDisplayNamePresentation,
873 d.mCallerDisplayNamePresentation) &&
Evan Charlton8c8a0622014-07-20 12:31:00 -0700874 Objects.equals(mAccountHandle, d.mAccountHandle) &&
Ihab Awad5d0410f2014-07-30 10:07:40 -0700875 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Andrew Lee223ad142014-08-27 16:33:08 -0700876 Objects.equals(mCallProperties, d.mCallProperties) &&
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700877 Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
Ihab Awade63fadb2014-07-09 21:52:04 -0700878 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Andrew Lee85f5d422014-07-11 17:22:03 -0700879 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Evan Charlton5b49ade2014-07-15 17:03:20 -0700880 Objects.equals(mVideoState, d.mVideoState) &&
Nancy Chen10798dc2014-08-08 14:00:25 -0700881 Objects.equals(mStatusHints, d.mStatusHints) &&
Tyler Gunn1e9bfc62015-08-19 11:18:58 -0700882 areBundlesEqual(mExtras, d.mExtras) &&
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700883 areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
Tyler Gunn7e45b722018-12-04 12:56:45 -0800884 Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis) &&
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -0800885 Objects.equals(mCallDirection, d.mCallDirection);
Ihab Awade63fadb2014-07-09 21:52:04 -0700886 }
887 return false;
888 }
889
890 @Override
891 public int hashCode() {
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700892 return Objects.hash(mHandle,
893 mHandlePresentation,
894 mCallerDisplayName,
895 mCallerDisplayNamePresentation,
896 mAccountHandle,
897 mCallCapabilities,
898 mCallProperties,
899 mDisconnectCause,
900 mConnectTimeMillis,
901 mGatewayInfo,
902 mVideoState,
903 mStatusHints,
904 mExtras,
905 mIntentExtras,
Tyler Gunn7e45b722018-12-04 12:56:45 -0800906 mCreationTimeMillis,
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -0800907 mCallDirection);
Ihab Awade63fadb2014-07-09 21:52:04 -0700908 }
909
910 /** {@hide} */
911 public Details(
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800912 String telecomCallId,
Ihab Awade63fadb2014-07-09 21:52:04 -0700913 Uri handle,
914 int handlePresentation,
915 String callerDisplayName,
916 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -0700917 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -0700918 int capabilities,
Andrew Lee223ad142014-08-27 16:33:08 -0700919 int properties,
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700920 DisconnectCause disconnectCause,
Ihab Awade63fadb2014-07-09 21:52:04 -0700921 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -0700922 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -0700923 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -0700924 StatusHints statusHints,
Santos Cordon6b7f9552015-05-27 17:21:45 -0700925 Bundle extras,
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700926 Bundle intentExtras,
Tyler Gunn7e45b722018-12-04 12:56:45 -0800927 long creationTimeMillis,
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -0800928 int callDirection) {
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800929 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700930 mHandle = handle;
931 mHandlePresentation = handlePresentation;
932 mCallerDisplayName = callerDisplayName;
933 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700934 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700935 mCallCapabilities = capabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700936 mCallProperties = properties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700937 mDisconnectCause = disconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700938 mConnectTimeMillis = connectTimeMillis;
939 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700940 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700941 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700942 mExtras = extras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700943 mIntentExtras = intentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700944 mCreationTimeMillis = creationTimeMillis;
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -0800945 mCallDirection = callDirection;
Ihab Awade63fadb2014-07-09 21:52:04 -0700946 }
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800947
948 /** {@hide} */
949 public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
950 return new Details(
951 parcelableCall.getId(),
952 parcelableCall.getHandle(),
953 parcelableCall.getHandlePresentation(),
954 parcelableCall.getCallerDisplayName(),
955 parcelableCall.getCallerDisplayNamePresentation(),
956 parcelableCall.getAccountHandle(),
957 parcelableCall.getCapabilities(),
958 parcelableCall.getProperties(),
959 parcelableCall.getDisconnectCause(),
960 parcelableCall.getConnectTimeMillis(),
961 parcelableCall.getGatewayInfo(),
962 parcelableCall.getVideoState(),
963 parcelableCall.getStatusHints(),
964 parcelableCall.getExtras(),
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700965 parcelableCall.getIntentExtras(),
Tyler Gunn7e45b722018-12-04 12:56:45 -0800966 parcelableCall.getCreationTimeMillis(),
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -0800967 parcelableCall.getCallDirection());
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800968 }
Santos Cordon3c20d632016-02-25 16:12:35 -0800969
970 @Override
971 public String toString() {
972 StringBuilder sb = new StringBuilder();
Tyler Gunne0caec72018-11-30 14:21:18 -0800973 sb.append("[id: ");
974 sb.append(mTelecomCallId);
975 sb.append(", pa: ");
Santos Cordon3c20d632016-02-25 16:12:35 -0800976 sb.append(mAccountHandle);
977 sb.append(", hdl: ");
Tyler Gunne0caec72018-11-30 14:21:18 -0800978 sb.append(Log.piiHandle(mHandle));
979 sb.append(", hdlPres: ");
980 sb.append(mHandlePresentation);
981 sb.append(", videoState: ");
982 sb.append(VideoProfile.videoStateToString(mVideoState));
Santos Cordon3c20d632016-02-25 16:12:35 -0800983 sb.append(", caps: ");
984 sb.append(capabilitiesToString(mCallCapabilities));
985 sb.append(", props: ");
Tyler Gunn720c6642016-03-22 09:02:47 -0700986 sb.append(propertiesToString(mCallProperties));
Santos Cordon3c20d632016-02-25 16:12:35 -0800987 sb.append("]");
988 return sb.toString();
989 }
Ihab Awade63fadb2014-07-09 21:52:04 -0700990 }
991
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -0700992 /**
993 * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
994 * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
995 * implementation.
996 * <p>
997 * You can handle these callbacks by extending the {@link Callback} class and overriding the
998 * callbacks that your {@link InCallService} is interested in. The callback methods include the
999 * {@link Call} for which the callback applies, allowing reuse of a single instance of your
1000 * {@link Callback} implementation, if desired.
1001 * <p>
1002 * Use {@link Call#registerCallback(Callback)} to register your callback(s). Ensure
1003 * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
1004 * (typically in {@link InCallService#onCallRemoved(Call)}).
1005 * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
1006 * reach your implementation of {@link Callback}, so it is important to register your callback
1007 * as soon as your {@link InCallService} is notified of a new call via
1008 * {@link InCallService#onCallAdded(Call)}.
1009 */
Andrew Leeda80c872015-04-15 14:09:50 -07001010 public static abstract class Callback {
Ihab Awade63fadb2014-07-09 21:52:04 -07001011 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001012 * @hide
1013 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001014 @IntDef(prefix = { "HANDOVER_" },
1015 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
Tyler Gunn5c60d712018-03-16 09:53:44 -07001016 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
Tyler Gunn9d127732018-03-02 15:45:51 -08001017 HANDOVER_FAILURE_UNKNOWN})
Sanket Padawea8eddd42017-11-03 11:07:35 -07001018 @Retention(RetentionPolicy.SOURCE)
1019 public @interface HandoverFailureErrors {}
1020
1021 /**
1022 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
Tyler Gunn9d127732018-03-02 15:45:51 -08001023 * to handover the call to rejects the handover request.
1024 * <p>
1025 * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
1026 * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
1027 * {@code null} {@link Connection} from
1028 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1029 * ConnectionRequest)}.
1030 * <p>
1031 * For more information on call handovers, see
1032 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001033 */
1034 public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
1035
1036 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001037 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1038 * is initiated but the source or destination app does not support handover.
1039 * <p>
1040 * Will be returned when a handover is requested via
1041 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
1042 * {@link PhoneAccountHandle} does not declare
1043 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}. May also be returned when a handover is
1044 * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
1045 * {@link Details#getAccountHandle()}) does not declare
1046 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
1047 * <p>
1048 * For more information on call handovers, see
1049 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001050 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001051 public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001052
1053 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001054 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
1055 * user rejects the handover request.
1056 * <p>
1057 * For more information on call handovers, see
1058 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001059 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001060 public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001061
Sanket Padawe85291f62017-12-01 13:59:27 -08001062 /**
1063 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
1064 * is ongoing emergency call.
Tyler Gunn9d127732018-03-02 15:45:51 -08001065 * <p>
1066 * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
1067 * called on an emergency call, or if any other call is an emergency call.
1068 * <p>
1069 * Handovers are not permitted while there are ongoing emergency calls.
1070 * <p>
1071 * For more information on call handovers, see
1072 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawe85291f62017-12-01 13:59:27 -08001073 */
Tyler Gunn5c60d712018-03-16 09:53:44 -07001074 public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
Sanket Padawe85291f62017-12-01 13:59:27 -08001075
Tyler Gunn9d127732018-03-02 15:45:51 -08001076 /**
1077 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1078 * fails for an unknown reason.
1079 * <p>
1080 * For more information on call handovers, see
1081 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
1082 */
1083 public static final int HANDOVER_FAILURE_UNKNOWN = 5;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001084
1085 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001086 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
1087 *
Ihab Awade63fadb2014-07-09 21:52:04 -07001088 * @param call The {@code Call} invoking this method.
1089 * @param state The new state of the {@code Call}.
1090 */
1091 public void onStateChanged(Call call, int state) {}
1092
1093 /**
1094 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
1095 *
1096 * @param call The {@code Call} invoking this method.
1097 * @param parent The new parent of the {@code Call}.
1098 */
1099 public void onParentChanged(Call call, Call parent) {}
1100
1101 /**
1102 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
1103 *
1104 * @param call The {@code Call} invoking this method.
1105 * @param children The new children of the {@code Call}.
1106 */
1107 public void onChildrenChanged(Call call, List<Call> children) {}
1108
1109 /**
1110 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
1111 *
1112 * @param call The {@code Call} invoking this method.
1113 * @param details A {@code Details} object describing the {@code Call}.
1114 */
1115 public void onDetailsChanged(Call call, Details details) {}
1116
1117 /**
1118 * Invoked when the text messages that can be used as responses to the incoming
1119 * {@code Call} are loaded from the relevant database.
1120 * See {@link #getCannedTextResponses()}.
1121 *
1122 * @param call The {@code Call} invoking this method.
1123 * @param cannedTextResponses The text messages useable as responses.
1124 */
1125 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
1126
1127 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001128 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
1129 * character. This causes the post-dial signals to stop pending user confirmation. An
1130 * implementation should present this choice to the user and invoke
1131 * {@link #postDialContinue(boolean)} when the user makes the choice.
1132 *
1133 * @param call The {@code Call} invoking this method.
1134 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
1135 */
1136 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
1137
1138 /**
Andrew Lee50aca232014-07-22 16:41:54 -07001139 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -07001140 *
1141 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -07001142 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001143 */
Andrew Lee50aca232014-07-22 16:41:54 -07001144 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -07001145
1146 /**
1147 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
1148 * up their UI for the {@code Call} in response to state transitions. Specifically,
1149 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
1150 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
1151 * clients should wait for this method to be invoked.
1152 *
1153 * @param call The {@code Call} being destroyed.
1154 */
1155 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001156
1157 /**
1158 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
1159 * conferenced.
1160 *
1161 * @param call The {@code Call} being updated.
1162 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
1163 * conferenced.
1164 */
1165 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001166
1167 /**
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001168 * Invoked when a {@link Call} receives an event from its associated {@link Connection}.
1169 * <p>
1170 * Where possible, the Call should make an attempt to handle {@link Connection} events which
1171 * are part of the {@code android.telecom.*} namespace. The Call should ignore any events
1172 * it does not wish to handle. Unexpected events should be handled gracefully, as it is
1173 * possible that a {@link ConnectionService} has defined its own Connection events which a
1174 * Call is not aware of.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001175 * <p>
1176 * See {@link Connection#sendConnectionEvent(String, Bundle)}.
1177 *
1178 * @param call The {@code Call} receiving the event.
1179 * @param event The event.
1180 * @param extras Extras associated with the connection event.
1181 */
1182 public void onConnectionEvent(Call call, String event, Bundle extras) {}
Hall Liu95d55872017-01-25 17:12:49 -08001183
1184 /**
1185 * Invoked when the RTT mode changes for this call.
1186 * @param call The call whose RTT mode has changed.
1187 * @param mode the new RTT mode, one of
1188 * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
1189 * or {@link RttCall#RTT_MODE_VCO}
1190 */
1191 public void onRttModeChanged(Call call, int mode) {}
1192
1193 /**
1194 * Invoked when the call's RTT status changes, either from off to on or from on to off.
1195 * @param call The call whose RTT status has changed.
1196 * @param enabled whether RTT is now enabled or disabled
1197 * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
1198 * on, null otherwise.
1199 */
1200 public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
1201
1202 /**
1203 * Invoked when the remote end of the connection has requested that an RTT communication
1204 * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
1205 * with the same ID that this method is invoked with.
1206 * @param call The call which the RTT request was placed on
1207 * @param id The ID of the request.
1208 */
1209 public void onRttRequest(Call call, int id) {}
Hall Liu57006aa2017-02-06 10:49:48 -08001210
1211 /**
1212 * Invoked when the RTT session failed to initiate for some reason, including rejection
1213 * by the remote party.
1214 * @param call The call which the RTT initiation failure occurred on.
1215 * @param reason One of the status codes defined in
1216 * {@link android.telecom.Connection.RttModifyStatus}, with the exception of
1217 * {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
1218 */
1219 public void onRttInitiationFailure(Call call, int reason) {}
Sanket Padawea8eddd42017-11-03 11:07:35 -07001220
1221 /**
1222 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1223 * has completed successfully.
Tyler Gunn9d127732018-03-02 15:45:51 -08001224 * <p>
1225 * For a full discussion of the handover process and the APIs involved, see
1226 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1227 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001228 * @param call The call which had initiated handover.
1229 */
1230 public void onHandoverComplete(Call call) {}
1231
1232 /**
1233 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1234 * has failed.
Tyler Gunn9d127732018-03-02 15:45:51 -08001235 * <p>
1236 * For a full discussion of the handover process and the APIs involved, see
1237 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1238 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001239 * @param call The call which had initiated handover.
Tyler Gunn9d127732018-03-02 15:45:51 -08001240 * @param failureReason Error reason for failure.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001241 */
1242 public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
Hall Liu95d55872017-01-25 17:12:49 -08001243 }
1244
1245 /**
1246 * A class that holds the state that describes the state of the RTT channel to the remote
1247 * party, if it is active.
1248 */
1249 public static final class RttCall {
Hall Liu07094df2017-02-28 15:17:44 -08001250 /** @hide */
Hall Liu95d55872017-01-25 17:12:49 -08001251 @Retention(RetentionPolicy.SOURCE)
1252 @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
1253 public @interface RttAudioMode {}
1254
1255 /**
1256 * For metrics use. Default value in the proto.
1257 * @hide
1258 */
1259 public static final int RTT_MODE_INVALID = 0;
1260
1261 /**
1262 * Indicates that there should be a bidirectional audio stream between the two parties
1263 * on the call.
1264 */
1265 public static final int RTT_MODE_FULL = 1;
1266
1267 /**
1268 * Indicates that the local user should be able to hear the audio stream from the remote
1269 * user, but not vice versa. Equivalent to muting the microphone.
1270 */
1271 public static final int RTT_MODE_HCO = 2;
1272
1273 /**
1274 * Indicates that the remote user should be able to hear the audio stream from the local
1275 * user, but not vice versa. Equivalent to setting the volume to zero.
1276 */
1277 public static final int RTT_MODE_VCO = 3;
1278
1279 private static final int READ_BUFFER_SIZE = 1000;
1280
1281 private InputStreamReader mReceiveStream;
1282 private OutputStreamWriter mTransmitStream;
1283 private int mRttMode;
1284 private final InCallAdapter mInCallAdapter;
Hall Liu57006aa2017-02-06 10:49:48 -08001285 private final String mTelecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001286 private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
1287
1288 /**
1289 * @hide
1290 */
Hall Liu57006aa2017-02-06 10:49:48 -08001291 public RttCall(String telecomCallId, InputStreamReader receiveStream,
1292 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
1293 mTelecomCallId = telecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001294 mReceiveStream = receiveStream;
1295 mTransmitStream = transmitStream;
1296 mRttMode = mode;
1297 mInCallAdapter = inCallAdapter;
1298 }
1299
1300 /**
1301 * Returns the current RTT audio mode.
1302 * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
1303 * {@link #RTT_MODE_HCO}.
1304 */
1305 public int getRttAudioMode() {
1306 return mRttMode;
1307 }
1308
1309 /**
1310 * Sets the RTT audio mode. The requested mode change will be communicated through
1311 * {@link Callback#onRttModeChanged(Call, int)}.
1312 * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
1313 * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
1314 */
1315 public void setRttMode(@RttAudioMode int mode) {
Hall Liu57006aa2017-02-06 10:49:48 -08001316 mInCallAdapter.setRttMode(mTelecomCallId, mode);
Hall Liu95d55872017-01-25 17:12:49 -08001317 }
1318
1319 /**
1320 * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
1321 * RTT transmits text in real-time, this method should be called once for each character
1322 * the user enters into the device.
1323 *
1324 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1325 * lead to interleaved text.
1326 * @param input The message to send to the remote user.
1327 */
1328 public void write(String input) throws IOException {
1329 mTransmitStream.write(input);
1330 mTransmitStream.flush();
1331 }
1332
1333 /**
1334 * Reads a string from the remote user, blocking if there is no data available. Returns
1335 * {@code null} if the RTT conversation has been terminated and there is no further data
1336 * to read.
1337 *
1338 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1339 * lead to interleaved text.
1340 * @return A string containing text sent by the remote user, or {@code null} if the
1341 * conversation has been terminated or if there was an error while reading.
1342 */
Hall Liub1c8a772017-07-17 17:04:41 -07001343 public String read() {
1344 try {
1345 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1346 if (numRead < 0) {
1347 return null;
1348 }
1349 return new String(mReadBuffer, 0, numRead);
1350 } catch (IOException e) {
1351 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
Jeff Sharkey90396362017-06-12 16:26:53 -06001352 return null;
Hall Liuffa4a812017-03-02 16:11:00 -08001353 }
Hall Liuffa4a812017-03-02 16:11:00 -08001354 }
1355
1356 /**
1357 * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
1358 * be read.
1359 * @return A string containing text entered by the user, or {@code null} if the user has
1360 * not entered any new text yet.
1361 */
1362 public String readImmediately() throws IOException {
1363 if (mReceiveStream.ready()) {
Hall Liub1c8a772017-07-17 17:04:41 -07001364 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1365 if (numRead < 0) {
1366 return null;
1367 }
1368 return new String(mReadBuffer, 0, numRead);
Hall Liuffa4a812017-03-02 16:11:00 -08001369 } else {
Hall Liu95d55872017-01-25 17:12:49 -08001370 return null;
1371 }
1372 }
Hall Liue9041242018-02-09 16:40:03 -08001373
1374 /**
1375 * Closes the underlying file descriptors
1376 * @hide
1377 */
1378 public void close() {
1379 try {
1380 mReceiveStream.close();
1381 } catch (IOException e) {
1382 // ignore
1383 }
1384 try {
1385 mTransmitStream.close();
1386 } catch (IOException e) {
1387 // ignore
1388 }
1389 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001390 }
1391
Andrew Leeda80c872015-04-15 14:09:50 -07001392 /**
1393 * @deprecated Use {@code Call.Callback} instead.
1394 * @hide
1395 */
1396 @Deprecated
1397 @SystemApi
1398 public static abstract class Listener extends Callback { }
1399
Ihab Awade63fadb2014-07-09 21:52:04 -07001400 private final Phone mPhone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001401 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001402 private final InCallAdapter mInCallAdapter;
Santos Cordon823fd3c2014-08-07 18:35:18 -07001403 private final List<String> mChildrenIds = new ArrayList<>();
Ihab Awade63fadb2014-07-09 21:52:04 -07001404 private final List<Call> mChildren = new ArrayList<>();
1405 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Andrew Lee011728f2015-04-23 15:47:06 -07001406 private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001407 private final List<Call> mConferenceableCalls = new ArrayList<>();
1408 private final List<Call> mUnmodifiableConferenceableCalls =
1409 Collections.unmodifiableList(mConferenceableCalls);
1410
Santos Cordon823fd3c2014-08-07 18:35:18 -07001411 private boolean mChildrenCached;
1412 private String mParentId = null;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001413 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -07001414 private List<String> mCannedTextResponses = null;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001415 private String mCallingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001416 private int mTargetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07001417 private String mRemainingPostDialSequence;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001418 private VideoCallImpl mVideoCallImpl;
Hall Liu95d55872017-01-25 17:12:49 -08001419 private RttCall mRttCall;
Ihab Awade63fadb2014-07-09 21:52:04 -07001420 private Details mDetails;
Tyler Gunndee56a82016-03-23 16:06:34 -07001421 private Bundle mExtras;
Ihab Awade63fadb2014-07-09 21:52:04 -07001422
1423 /**
1424 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
1425 *
1426 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
1427 * remaining or this {@code Call} is not in a post-dial state.
1428 */
1429 public String getRemainingPostDialSequence() {
1430 return mRemainingPostDialSequence;
1431 }
1432
1433 /**
1434 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001435 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -07001436 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001437 public void answer(@VideoProfile.VideoState int videoState) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001438 mInCallAdapter.answerCall(mTelecomCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -07001439 }
1440
1441 /**
Pooja Jaind34698d2017-12-28 14:15:31 +05301442 * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
1443 *
1444 * @param address The address to which the call will be deflected.
1445 */
1446 public void deflect(Uri address) {
1447 mInCallAdapter.deflectCall(mTelecomCallId, address);
1448 }
1449
1450 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001451 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
1452 *
1453 * @param rejectWithMessage Whether to reject with a text message.
1454 * @param textMessage An optional text message with which to respond.
1455 */
1456 public void reject(boolean rejectWithMessage, String textMessage) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001457 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
Ihab Awade63fadb2014-07-09 21:52:04 -07001458 }
1459
1460 /**
1461 * Instructs this {@code Call} to disconnect.
1462 */
1463 public void disconnect() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001464 mInCallAdapter.disconnectCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001465 }
1466
1467 /**
1468 * Instructs this {@code Call} to go on hold.
1469 */
1470 public void hold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001471 mInCallAdapter.holdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001472 }
1473
1474 /**
1475 * Instructs this {@link #STATE_HOLDING} call to release from hold.
1476 */
1477 public void unhold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001478 mInCallAdapter.unholdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001479 }
1480
1481 /**
1482 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
1483 *
1484 * Any other currently playing DTMF tone in the specified call is immediately stopped.
1485 *
1486 * @param digit A character representing the DTMF digit for which to play the tone. This
1487 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
1488 */
1489 public void playDtmfTone(char digit) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001490 mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
Ihab Awade63fadb2014-07-09 21:52:04 -07001491 }
1492
1493 /**
1494 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
1495 * currently playing.
1496 *
1497 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
1498 * currently playing, this method will do nothing.
1499 */
1500 public void stopDtmfTone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001501 mInCallAdapter.stopDtmfTone(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001502 }
1503
1504 /**
1505 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
1506 *
1507 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
1508 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -07001509 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001510 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -07001511 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
1512 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001513 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
Andrew Leeda80c872015-04-15 14:09:50 -07001514 * {@code Call} will pause playing the tones and notify callbacks via
1515 * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
Ihab Awade63fadb2014-07-09 21:52:04 -07001516 * should display to the user an indication of this state and an affordance to continue
1517 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
1518 * app should invoke the {@link #postDialContinue(boolean)} method.
1519 *
1520 * @param proceed Whether or not to continue with the post-dial sequence.
1521 */
1522 public void postDialContinue(boolean proceed) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001523 mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
Ihab Awade63fadb2014-07-09 21:52:04 -07001524 }
1525
1526 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -07001527 * Notifies this {@code Call} that an account has been selected and to proceed with placing
Nancy Chen36c62f32014-10-21 18:36:39 -07001528 * an outgoing call. Optionally sets this account as the default account.
Nancy Chen5da0fd52014-07-08 14:16:17 -07001529 */
Nancy Chen36c62f32014-10-21 18:36:39 -07001530 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
1531 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
Nancy Chen5da0fd52014-07-08 14:16:17 -07001532
1533 }
1534
1535 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001536 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001537 *
1538 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -07001539 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001540 public void conference(Call callToConferenceWith) {
1541 if (callToConferenceWith != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001542 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001543 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001544 }
1545
1546 /**
1547 * Instructs this {@code Call} to split from any conference call with which it may be
1548 * connected.
1549 */
1550 public void splitFromConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001551 mInCallAdapter.splitFromConference(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001552 }
1553
1554 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001555 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001556 */
1557 public void mergeConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001558 mInCallAdapter.mergeConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001559 }
1560
1561 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001562 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001563 */
1564 public void swapConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001565 mInCallAdapter.swapConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001566 }
1567
1568 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001569 * Initiates a request to the {@link ConnectionService} to pull an external call to the local
1570 * device.
1571 * <p>
1572 * Calls to this method are ignored if the call does not have the
1573 * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
1574 * <p>
1575 * An {@link InCallService} will only see calls which support this method if it has the
1576 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
1577 * in its manifest.
1578 */
1579 public void pullExternalCall() {
1580 // If this isn't an external call, ignore the request.
1581 if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
1582 return;
1583 }
1584
1585 mInCallAdapter.pullExternalCall(mTelecomCallId);
1586 }
1587
1588 /**
1589 * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
1590 * the {@link ConnectionService}.
1591 * <p>
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001592 * Call events are used to communicate point in time information from an {@link InCallService}
1593 * to a {@link ConnectionService}. A {@link ConnectionService} implementation could define
1594 * events which enable the {@link InCallService}, for example, toggle a unique feature of the
1595 * {@link ConnectionService}.
1596 * <p>
1597 * A {@link ConnectionService} can communicate to the {@link InCallService} using
1598 * {@link Connection#sendConnectionEvent(String, Bundle)}.
1599 * <p>
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001600 * Events are exposed to {@link ConnectionService} implementations via
1601 * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
1602 * <p>
1603 * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001604 * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
1605 * ignore some events altogether.
1606 * <p>
1607 * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
1608 * conflicts between {@link InCallService} implementations. Further, {@link InCallService}
1609 * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
1610 * they define their own event types in this namespace. When defining a custom event type,
1611 * ensure the contents of the extras {@link Bundle} is clearly defined. Extra keys for this
1612 * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
1613 * <p>
1614 * When defining events and the associated extras, it is important to keep their behavior
1615 * consistent when the associated {@link InCallService} is updated. Support for deprecated
1616 * events/extras should me maintained to ensure backwards compatibility with older
1617 * {@link ConnectionService} implementations which were built to support the older behavior.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001618 *
1619 * @param event The connection event.
1620 * @param extras Bundle containing extra information associated with the event.
1621 */
1622 public void sendCallEvent(String event, Bundle extras) {
Sanket Padawef6a9e5b2018-01-05 14:26:16 -08001623 mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001624 }
1625
1626 /**
Hall Liu95d55872017-01-25 17:12:49 -08001627 * Sends an RTT upgrade request to the remote end of the connection. Success is not
1628 * guaranteed, and notification of success will be via the
1629 * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1630 */
1631 public void sendRttRequest() {
Hall Liu57006aa2017-02-06 10:49:48 -08001632 mInCallAdapter.sendRttRequest(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001633 }
1634
1635 /**
1636 * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
1637 * callback.
1638 * The ID used here should be the same as the ID that was received via the callback.
1639 * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
1640 * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
1641 */
1642 public void respondToRttRequest(int id, boolean accept) {
Hall Liu57006aa2017-02-06 10:49:48 -08001643 mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
Hall Liu95d55872017-01-25 17:12:49 -08001644 }
1645
1646 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001647 * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
1648 * by {@code toHandle}. The videoState specified indicates the desired video state after the
1649 * handover.
1650 * <p>
Tyler Gunn9d127732018-03-02 15:45:51 -08001651 * A call handover is the process where an ongoing call is transferred from one app (i.e.
1652 * {@link ConnectionService} to another app. The user could, for example, choose to continue a
1653 * mobile network call in a video calling app. The mobile network call via the Telephony stack
1654 * is referred to as the source of the handover, and the video calling app is referred to as the
1655 * destination.
1656 * <p>
1657 * When considering a handover scenario the device this method is called on is considered the
1658 * <em>initiating</em> device (since the user initiates the handover from this device), and the
1659 * other device is considered the <em>receiving</em> device.
1660 * <p>
1661 * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
1662 * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
1663 * and invoke
1664 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1665 * ConnectionRequest)} to inform the destination app that a request has been made to handover a
1666 * call to it. The app returns an instance of {@link Connection} to represent the handover call
1667 * At this point the app should display UI to indicate to the user that a call
1668 * handover is in process.
1669 * <p>
1670 * The destination app is responsible for communicating the handover request from the
1671 * <em>initiating</em> device to the <em>receiving</em> device.
1672 * <p>
1673 * When the app on the <em>receiving</em> device receives the handover request, it calls
1674 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
1675 * process from the <em>initiating</em> device to the <em>receiving</em> device. At this point
1676 * the destination app on the <em>receiving</em> device should show UI to allow the user to
1677 * choose whether they want to continue their call in the destination app.
1678 * <p>
1679 * When the destination app on the <em>receiving</em> device calls
1680 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
1681 * {@link ConnectionService} and call
1682 * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
1683 * ConnectionRequest)} to inform it of the handover request. The app returns an instance of
1684 * {@link Connection} to represent the handover call.
1685 * <p>
1686 * If the user of the <em>receiving</em> device accepts the handover, the app calls
1687 * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
1688 * original call. If the user rejects the handover, the app calls
1689 * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
1690 * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
1691 * <p>
1692 * Telecom will only allow handovers from {@link PhoneAccount}s which declare
1693 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}. Similarly, the {@link PhoneAccount}
1694 * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
1695 * <p>
1696 * Errors in the handover process are reported to the {@link InCallService} via
1697 * {@link Callback#onHandoverFailed(Call, int)}. Errors in the handover process are reported to
1698 * the involved {@link ConnectionService}s via
1699 * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001700 *
1701 * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
1702 * this call to.
Tyler Gunn9d127732018-03-02 15:45:51 -08001703 * @param videoState Indicates the video state desired after the handover (see the
1704 * {@code STATE_*} constants defined in {@link VideoProfile}).
Sanket Padawea8eddd42017-11-03 11:07:35 -07001705 * @param extras Bundle containing extra information to be passed to the
1706 * {@link ConnectionService}
1707 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001708 public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
1709 Bundle extras) {
Sanket Padawea8eddd42017-11-03 11:07:35 -07001710 mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
1711 }
1712
1713 /**
Hall Liu95d55872017-01-25 17:12:49 -08001714 * Terminate the RTT session on this call. The resulting state change will be notified via
1715 * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1716 */
1717 public void stopRtt() {
Hall Liu57006aa2017-02-06 10:49:48 -08001718 mInCallAdapter.stopRtt(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001719 }
1720
1721 /**
Tyler Gunndee56a82016-03-23 16:06:34 -07001722 * Adds some extras to this {@link Call}. Existing keys are replaced and new ones are
1723 * added.
1724 * <p>
1725 * No assumptions should be made as to how an In-Call UI or service will handle these
1726 * extras. Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
1727 *
1728 * @param extras The extras to add.
1729 */
1730 public final void putExtras(Bundle extras) {
1731 if (extras == null) {
1732 return;
1733 }
1734
1735 if (mExtras == null) {
1736 mExtras = new Bundle();
1737 }
1738 mExtras.putAll(extras);
1739 mInCallAdapter.putExtras(mTelecomCallId, extras);
1740 }
1741
1742 /**
1743 * Adds a boolean extra to this {@link Call}.
1744 *
1745 * @param key The extra key.
1746 * @param value The value.
1747 * @hide
1748 */
1749 public final void putExtra(String key, boolean value) {
1750 if (mExtras == null) {
1751 mExtras = new Bundle();
1752 }
1753 mExtras.putBoolean(key, value);
1754 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1755 }
1756
1757 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001758 * Adds an integer extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001759 *
1760 * @param key The extra key.
1761 * @param value The value.
1762 * @hide
1763 */
1764 public final void putExtra(String key, int value) {
1765 if (mExtras == null) {
1766 mExtras = new Bundle();
1767 }
1768 mExtras.putInt(key, value);
1769 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1770 }
1771
1772 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001773 * Adds a string extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001774 *
1775 * @param key The extra key.
1776 * @param value The value.
1777 * @hide
1778 */
1779 public final void putExtra(String key, String value) {
1780 if (mExtras == null) {
1781 mExtras = new Bundle();
1782 }
1783 mExtras.putString(key, value);
1784 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1785 }
1786
1787 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001788 * Removes extras from this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001789 *
1790 * @param keys The keys of the extras to remove.
1791 */
1792 public final void removeExtras(List<String> keys) {
1793 if (mExtras != null) {
1794 for (String key : keys) {
1795 mExtras.remove(key);
1796 }
1797 if (mExtras.size() == 0) {
1798 mExtras = null;
1799 }
1800 }
1801 mInCallAdapter.removeExtras(mTelecomCallId, keys);
1802 }
1803
1804 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001805 * Removes extras from this {@link Call}.
1806 *
1807 * @param keys The keys of the extras to remove.
1808 */
1809 public final void removeExtras(String ... keys) {
1810 removeExtras(Arrays.asList(keys));
1811 }
1812
1813 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001814 * Obtains the parent of this {@code Call} in a conference, if any.
1815 *
1816 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
1817 * child of any conference {@code Call}s.
1818 */
1819 public Call getParent() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001820 if (mParentId != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001821 return mPhone.internalGetCallByTelecomId(mParentId);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001822 }
1823 return null;
Ihab Awade63fadb2014-07-09 21:52:04 -07001824 }
1825
1826 /**
1827 * Obtains the children of this conference {@code Call}, if any.
1828 *
1829 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
1830 * {@code List} otherwise.
1831 */
1832 public List<Call> getChildren() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001833 if (!mChildrenCached) {
1834 mChildrenCached = true;
1835 mChildren.clear();
1836
1837 for(String id : mChildrenIds) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001838 Call call = mPhone.internalGetCallByTelecomId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001839 if (call == null) {
1840 // At least one child was still not found, so do not save true for "cached"
1841 mChildrenCached = false;
1842 } else {
1843 mChildren.add(call);
1844 }
1845 }
1846 }
1847
Ihab Awade63fadb2014-07-09 21:52:04 -07001848 return mUnmodifiableChildren;
1849 }
1850
1851 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001852 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
1853 *
1854 * @return The list of conferenceable {@code Call}s.
1855 */
1856 public List<Call> getConferenceableCalls() {
1857 return mUnmodifiableConferenceableCalls;
1858 }
1859
1860 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001861 * Obtains the state of this {@code Call}.
1862 *
1863 * @return A state value, chosen from the {@code STATE_*} constants.
1864 */
1865 public int getState() {
1866 return mState;
1867 }
1868
1869 /**
1870 * Obtains a list of canned, pre-configured message responses to present to the user as
1871 * ways of rejecting this {@code Call} using via a text message.
1872 *
1873 * @see #reject(boolean, String)
1874 *
1875 * @return A list of canned text message responses.
1876 */
1877 public List<String> getCannedTextResponses() {
1878 return mCannedTextResponses;
1879 }
1880
1881 /**
1882 * Obtains an object that can be used to display video from this {@code Call}.
1883 *
Andrew Lee50aca232014-07-22 16:41:54 -07001884 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001885 */
Andrew Lee50aca232014-07-22 16:41:54 -07001886 public InCallService.VideoCall getVideoCall() {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001887 return mVideoCallImpl;
Ihab Awade63fadb2014-07-09 21:52:04 -07001888 }
1889
1890 /**
1891 * Obtains an object containing call details.
1892 *
1893 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
1894 * result may be {@code null}.
1895 */
1896 public Details getDetails() {
1897 return mDetails;
1898 }
1899
1900 /**
Hall Liu95d55872017-01-25 17:12:49 -08001901 * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
1902 * receive RTT text data, as well as to change the RTT mode.
1903 * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
1904 */
1905 public @Nullable RttCall getRttCall() {
1906 return mRttCall;
1907 }
1908
1909 /**
1910 * Returns whether this call has an active RTT connection.
1911 * @return true if there is a connection, false otherwise.
1912 */
1913 public boolean isRttActive() {
Hall Liue9041242018-02-09 16:40:03 -08001914 return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
Hall Liu95d55872017-01-25 17:12:49 -08001915 }
1916
1917 /**
Andrew Leeda80c872015-04-15 14:09:50 -07001918 * Registers a callback to this {@code Call}.
1919 *
1920 * @param callback A {@code Callback}.
1921 */
1922 public void registerCallback(Callback callback) {
Andrew Lee011728f2015-04-23 15:47:06 -07001923 registerCallback(callback, new Handler());
1924 }
1925
1926 /**
1927 * Registers a callback to this {@code Call}.
1928 *
1929 * @param callback A {@code Callback}.
1930 * @param handler A handler which command and status changes will be delivered to.
1931 */
1932 public void registerCallback(Callback callback, Handler handler) {
1933 unregisterCallback(callback);
Roshan Pius1ca62072015-07-07 17:34:51 -07001934 // Don't allow new callback registration if the call is already being destroyed.
1935 if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07001936 mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
1937 }
Andrew Leeda80c872015-04-15 14:09:50 -07001938 }
1939
1940 /**
1941 * Unregisters a callback from this {@code Call}.
1942 *
1943 * @param callback A {@code Callback}.
1944 */
1945 public void unregisterCallback(Callback callback) {
Roshan Pius1ca62072015-07-07 17:34:51 -07001946 // Don't allow callback deregistration if the call is already being destroyed.
1947 if (callback != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07001948 for (CallbackRecord<Callback> record : mCallbackRecords) {
1949 if (record.getCallback() == callback) {
1950 mCallbackRecords.remove(record);
1951 break;
1952 }
1953 }
Andrew Leeda80c872015-04-15 14:09:50 -07001954 }
1955 }
1956
Santos Cordon3c20d632016-02-25 16:12:35 -08001957 @Override
1958 public String toString() {
1959 return new StringBuilder().
1960 append("Call [id: ").
1961 append(mTelecomCallId).
1962 append(", state: ").
1963 append(stateToString(mState)).
1964 append(", details: ").
1965 append(mDetails).
1966 append("]").toString();
1967 }
1968
1969 /**
1970 * @param state An integer value of a {@code STATE_*} constant.
1971 * @return A string representation of the value.
1972 */
1973 private static String stateToString(int state) {
1974 switch (state) {
1975 case STATE_NEW:
1976 return "NEW";
1977 case STATE_RINGING:
1978 return "RINGING";
1979 case STATE_DIALING:
1980 return "DIALING";
1981 case STATE_ACTIVE:
1982 return "ACTIVE";
1983 case STATE_HOLDING:
1984 return "HOLDING";
1985 case STATE_DISCONNECTED:
1986 return "DISCONNECTED";
1987 case STATE_CONNECTING:
1988 return "CONNECTING";
1989 case STATE_DISCONNECTING:
1990 return "DISCONNECTING";
1991 case STATE_SELECT_PHONE_ACCOUNT:
1992 return "SELECT_PHONE_ACCOUNT";
1993 default:
1994 Log.w(Call.class, "Unknown state %d", state);
1995 return "UNKNOWN";
1996 }
1997 }
1998
Andrew Leeda80c872015-04-15 14:09:50 -07001999 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002000 * Adds a listener to this {@code Call}.
2001 *
2002 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002003 * @deprecated Use {@link #registerCallback} instead.
2004 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002005 */
Andrew Leeda80c872015-04-15 14:09:50 -07002006 @Deprecated
2007 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002008 public void addListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002009 registerCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002010 }
2011
2012 /**
2013 * Removes a listener from this {@code Call}.
2014 *
2015 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002016 * @deprecated Use {@link #unregisterCallback} instead.
2017 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002018 */
Andrew Leeda80c872015-04-15 14:09:50 -07002019 @Deprecated
2020 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002021 public void removeListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002022 unregisterCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002023 }
2024
2025 /** {@hide} */
Tyler Gunn159f35c2017-03-02 09:28:37 -08002026 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
2027 int targetSdkVersion) {
Ihab Awade63fadb2014-07-09 21:52:04 -07002028 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002029 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002030 mInCallAdapter = inCallAdapter;
2031 mState = STATE_NEW;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002032 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002033 mTargetSdkVersion = targetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07002034 }
2035
2036 /** {@hide} */
Tyler Gunnb88b3112016-11-09 10:19:23 -08002037 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
Tyler Gunn159f35c2017-03-02 09:28:37 -08002038 String callingPackage, int targetSdkVersion) {
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002039 mPhone = phone;
2040 mTelecomCallId = telecomCallId;
2041 mInCallAdapter = inCallAdapter;
2042 mState = state;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002043 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002044 mTargetSdkVersion = targetSdkVersion;
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002045 }
2046
2047 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002048 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002049 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002050 }
2051
2052 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002053 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Tyler Gunnb88b3112016-11-09 10:19:23 -08002054
Ihab Awade63fadb2014-07-09 21:52:04 -07002055 // First, we update the internal state as far as possible before firing any updates.
Sailesh Nepal1bef3392016-01-24 18:21:53 -08002056 Details details = Details.createFromParcelableCall(parcelableCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07002057 boolean detailsChanged = !Objects.equals(mDetails, details);
2058 if (detailsChanged) {
2059 mDetails = details;
2060 }
2061
2062 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -07002063 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
2064 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
2065 mCannedTextResponses =
2066 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Yorke Leee886f632015-08-04 13:43:31 -07002067 cannedTextResponsesChanged = true;
Ihab Awade63fadb2014-07-09 21:52:04 -07002068 }
2069
Tyler Gunn159f35c2017-03-02 09:28:37 -08002070 VideoCallImpl newVideoCallImpl = parcelableCall.getVideoCallImpl(mCallingPackage,
2071 mTargetSdkVersion);
Tyler Gunn75958422015-04-15 14:23:42 -07002072 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() &&
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002073 !Objects.equals(mVideoCallImpl, newVideoCallImpl);
Andrew Lee50aca232014-07-22 16:41:54 -07002074 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002075 mVideoCallImpl = newVideoCallImpl;
2076 }
2077 if (mVideoCallImpl != null) {
2078 mVideoCallImpl.setVideoState(getDetails().getVideoState());
Ihab Awade63fadb2014-07-09 21:52:04 -07002079 }
2080
Santos Cordone3c507b2015-04-23 14:44:19 -07002081 int state = parcelableCall.getState();
Ihab Awade63fadb2014-07-09 21:52:04 -07002082 boolean stateChanged = mState != state;
2083 if (stateChanged) {
2084 mState = state;
2085 }
2086
Santos Cordon823fd3c2014-08-07 18:35:18 -07002087 String parentId = parcelableCall.getParentCallId();
2088 boolean parentChanged = !Objects.equals(mParentId, parentId);
2089 if (parentChanged) {
2090 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002091 }
2092
Santos Cordon823fd3c2014-08-07 18:35:18 -07002093 List<String> childCallIds = parcelableCall.getChildCallIds();
2094 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
2095 if (childrenChanged) {
2096 mChildrenIds.clear();
2097 mChildrenIds.addAll(parcelableCall.getChildCallIds());
2098 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -07002099 }
2100
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002101 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
2102 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
2103 for (String otherId : conferenceableCallIds) {
2104 if (callIdMap.containsKey(otherId)) {
2105 conferenceableCalls.add(callIdMap.get(otherId));
2106 }
2107 }
2108
2109 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
2110 mConferenceableCalls.clear();
2111 mConferenceableCalls.addAll(conferenceableCalls);
2112 fireConferenceableCallsChanged();
2113 }
2114
Hall Liu95d55872017-01-25 17:12:49 -08002115 boolean isRttChanged = false;
2116 boolean rttModeChanged = false;
Hall Liue9041242018-02-09 16:40:03 -08002117 if (parcelableCall.getIsRttCallChanged()
2118 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
Hall Liu95d55872017-01-25 17:12:49 -08002119 ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
2120 InputStreamReader receiveStream = new InputStreamReader(
2121 new ParcelFileDescriptor.AutoCloseInputStream(
2122 parcelableRttCall.getReceiveStream()),
2123 StandardCharsets.UTF_8);
2124 OutputStreamWriter transmitStream = new OutputStreamWriter(
2125 new ParcelFileDescriptor.AutoCloseOutputStream(
2126 parcelableRttCall.getTransmitStream()),
2127 StandardCharsets.UTF_8);
Hall Liu57006aa2017-02-06 10:49:48 -08002128 RttCall newRttCall = new Call.RttCall(mTelecomCallId,
Hall Liu95d55872017-01-25 17:12:49 -08002129 receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
2130 if (mRttCall == null) {
2131 isRttChanged = true;
2132 } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
2133 rttModeChanged = true;
2134 }
2135 mRttCall = newRttCall;
2136 } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
2137 && parcelableCall.getIsRttCallChanged()) {
2138 isRttChanged = true;
2139 mRttCall = null;
2140 }
2141
Ihab Awade63fadb2014-07-09 21:52:04 -07002142 // Now we fire updates, ensuring that any client who listens to any of these notifications
2143 // gets the most up-to-date state.
2144
2145 if (stateChanged) {
2146 fireStateChanged(mState);
2147 }
2148 if (detailsChanged) {
2149 fireDetailsChanged(mDetails);
2150 }
2151 if (cannedTextResponsesChanged) {
2152 fireCannedTextResponsesLoaded(mCannedTextResponses);
2153 }
Andrew Lee50aca232014-07-22 16:41:54 -07002154 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002155 fireVideoCallChanged(mVideoCallImpl);
Ihab Awade63fadb2014-07-09 21:52:04 -07002156 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002157 if (parentChanged) {
2158 fireParentChanged(getParent());
2159 }
2160 if (childrenChanged) {
2161 fireChildrenChanged(getChildren());
2162 }
Hall Liu95d55872017-01-25 17:12:49 -08002163 if (isRttChanged) {
2164 fireOnIsRttChanged(mRttCall != null, mRttCall);
2165 }
2166 if (rttModeChanged) {
2167 fireOnRttModeChanged(mRttCall.getRttAudioMode());
2168 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002169
2170 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
2171 // remove ourselves from the Phone. Note that we do this after completing all state updates
2172 // so a client can cleanly transition all their UI to the state appropriate for a
2173 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
2174 if (mState == STATE_DISCONNECTED) {
2175 fireCallDestroyed();
Ihab Awade63fadb2014-07-09 21:52:04 -07002176 }
2177 }
2178
2179 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002180 final void internalSetPostDialWait(String remaining) {
2181 mRemainingPostDialSequence = remaining;
2182 firePostDialWait(mRemainingPostDialSequence);
2183 }
2184
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07002185 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -07002186 final void internalSetDisconnected() {
2187 if (mState != Call.STATE_DISCONNECTED) {
2188 mState = Call.STATE_DISCONNECTED;
2189 fireStateChanged(mState);
2190 fireCallDestroyed();
Santos Cordonf30d7e92014-08-26 09:54:33 -07002191 }
2192 }
2193
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002194 /** {@hide} */
2195 final void internalOnConnectionEvent(String event, Bundle extras) {
2196 fireOnConnectionEvent(event, extras);
2197 }
2198
Hall Liu95d55872017-01-25 17:12:49 -08002199 /** {@hide} */
2200 final void internalOnRttUpgradeRequest(final int requestId) {
2201 for (CallbackRecord<Callback> record : mCallbackRecords) {
2202 final Call call = this;
2203 final Callback callback = record.getCallback();
2204 record.getHandler().post(() -> callback.onRttRequest(call, requestId));
2205 }
2206 }
2207
Hall Liu57006aa2017-02-06 10:49:48 -08002208 /** @hide */
2209 final void internalOnRttInitiationFailure(int reason) {
2210 for (CallbackRecord<Callback> record : mCallbackRecords) {
2211 final Call call = this;
2212 final Callback callback = record.getCallback();
2213 record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
2214 }
2215 }
2216
Sanket Padawe85291f62017-12-01 13:59:27 -08002217 /** {@hide} */
2218 final void internalOnHandoverFailed(int error) {
2219 for (CallbackRecord<Callback> record : mCallbackRecords) {
2220 final Call call = this;
2221 final Callback callback = record.getCallback();
2222 record.getHandler().post(() -> callback.onHandoverFailed(call, error));
2223 }
2224 }
2225
Tyler Gunn858bfaf2018-01-22 15:17:54 -08002226 /** {@hide} */
2227 final void internalOnHandoverComplete() {
2228 for (CallbackRecord<Callback> record : mCallbackRecords) {
2229 final Call call = this;
2230 final Callback callback = record.getCallback();
2231 record.getHandler().post(() -> callback.onHandoverComplete(call));
2232 }
2233 }
2234
Andrew Lee011728f2015-04-23 15:47:06 -07002235 private void fireStateChanged(final int newState) {
2236 for (CallbackRecord<Callback> record : mCallbackRecords) {
2237 final Call call = this;
2238 final Callback callback = record.getCallback();
2239 record.getHandler().post(new Runnable() {
2240 @Override
2241 public void run() {
2242 callback.onStateChanged(call, newState);
2243 }
2244 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002245 }
2246 }
2247
Andrew Lee011728f2015-04-23 15:47:06 -07002248 private void fireParentChanged(final Call newParent) {
2249 for (CallbackRecord<Callback> record : mCallbackRecords) {
2250 final Call call = this;
2251 final Callback callback = record.getCallback();
2252 record.getHandler().post(new Runnable() {
2253 @Override
2254 public void run() {
2255 callback.onParentChanged(call, newParent);
2256 }
2257 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002258 }
2259 }
2260
Andrew Lee011728f2015-04-23 15:47:06 -07002261 private void fireChildrenChanged(final List<Call> children) {
2262 for (CallbackRecord<Callback> record : mCallbackRecords) {
2263 final Call call = this;
2264 final Callback callback = record.getCallback();
2265 record.getHandler().post(new Runnable() {
2266 @Override
2267 public void run() {
2268 callback.onChildrenChanged(call, children);
2269 }
2270 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002271 }
2272 }
2273
Andrew Lee011728f2015-04-23 15:47:06 -07002274 private void fireDetailsChanged(final Details details) {
2275 for (CallbackRecord<Callback> record : mCallbackRecords) {
2276 final Call call = this;
2277 final Callback callback = record.getCallback();
2278 record.getHandler().post(new Runnable() {
2279 @Override
2280 public void run() {
2281 callback.onDetailsChanged(call, details);
2282 }
2283 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002284 }
2285 }
2286
Andrew Lee011728f2015-04-23 15:47:06 -07002287 private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
2288 for (CallbackRecord<Callback> record : mCallbackRecords) {
2289 final Call call = this;
2290 final Callback callback = record.getCallback();
2291 record.getHandler().post(new Runnable() {
2292 @Override
2293 public void run() {
2294 callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
2295 }
2296 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002297 }
2298 }
2299
Andrew Lee011728f2015-04-23 15:47:06 -07002300 private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
2301 for (CallbackRecord<Callback> record : mCallbackRecords) {
2302 final Call call = this;
2303 final Callback callback = record.getCallback();
2304 record.getHandler().post(new Runnable() {
2305 @Override
2306 public void run() {
2307 callback.onVideoCallChanged(call, videoCall);
2308 }
2309 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002310 }
2311 }
2312
Andrew Lee011728f2015-04-23 15:47:06 -07002313 private void firePostDialWait(final String remainingPostDialSequence) {
2314 for (CallbackRecord<Callback> record : mCallbackRecords) {
2315 final Call call = this;
2316 final Callback callback = record.getCallback();
2317 record.getHandler().post(new Runnable() {
2318 @Override
2319 public void run() {
2320 callback.onPostDialWait(call, remainingPostDialSequence);
2321 }
2322 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002323 }
2324 }
2325
2326 private void fireCallDestroyed() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002327 /**
2328 * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
2329 * onCallRemoved callback, we remove this call from the Phone's record
2330 * only once all of the registered onCallDestroyed callbacks are executed.
2331 * All the callbacks get removed from our records as a part of this operation
2332 * since onCallDestroyed is the final callback.
2333 */
2334 final Call call = this;
2335 if (mCallbackRecords.isEmpty()) {
2336 // No callbacks registered, remove the call from Phone's record.
2337 mPhone.internalRemoveCall(call);
2338 }
2339 for (final CallbackRecord<Callback> record : mCallbackRecords) {
Andrew Lee011728f2015-04-23 15:47:06 -07002340 final Callback callback = record.getCallback();
2341 record.getHandler().post(new Runnable() {
2342 @Override
2343 public void run() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002344 boolean isFinalRemoval = false;
2345 RuntimeException toThrow = null;
2346 try {
2347 callback.onCallDestroyed(call);
2348 } catch (RuntimeException e) {
2349 toThrow = e;
2350 }
2351 synchronized(Call.this) {
2352 mCallbackRecords.remove(record);
2353 if (mCallbackRecords.isEmpty()) {
2354 isFinalRemoval = true;
2355 }
2356 }
2357 if (isFinalRemoval) {
2358 mPhone.internalRemoveCall(call);
2359 }
2360 if (toThrow != null) {
2361 throw toThrow;
2362 }
Andrew Lee011728f2015-04-23 15:47:06 -07002363 }
2364 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002365 }
2366 }
2367
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002368 private void fireConferenceableCallsChanged() {
Andrew Lee011728f2015-04-23 15:47:06 -07002369 for (CallbackRecord<Callback> record : mCallbackRecords) {
2370 final Call call = this;
2371 final Callback callback = record.getCallback();
2372 record.getHandler().post(new Runnable() {
2373 @Override
2374 public void run() {
2375 callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
2376 }
2377 });
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002378 }
2379 }
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002380
2381 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002382 * Notifies listeners of an incoming connection event.
2383 * <p>
2384 * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
2385 *
2386 * @param event
2387 * @param extras
2388 */
2389 private void fireOnConnectionEvent(final String event, final Bundle extras) {
2390 for (CallbackRecord<Callback> record : mCallbackRecords) {
2391 final Call call = this;
2392 final Callback callback = record.getCallback();
2393 record.getHandler().post(new Runnable() {
2394 @Override
2395 public void run() {
2396 callback.onConnectionEvent(call, event, extras);
2397 }
2398 });
2399 }
2400 }
2401
2402 /**
Hall Liu95d55872017-01-25 17:12:49 -08002403 * Notifies listeners of an RTT on/off change
2404 *
2405 * @param enabled True if RTT is now enabled, false otherwise
2406 */
2407 private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
2408 for (CallbackRecord<Callback> record : mCallbackRecords) {
2409 final Call call = this;
2410 final Callback callback = record.getCallback();
2411 record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
2412 }
2413 }
2414
2415 /**
2416 * Notifies listeners of a RTT mode change
2417 *
2418 * @param mode The new RTT mode
2419 */
2420 private void fireOnRttModeChanged(final int mode) {
2421 for (CallbackRecord<Callback> record : mCallbackRecords) {
2422 final Call call = this;
2423 final Callback callback = record.getCallback();
2424 record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
2425 }
2426 }
2427
2428 /**
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002429 * Determines if two bundles are equal.
2430 *
2431 * @param bundle The original bundle.
2432 * @param newBundle The bundle to compare with.
2433 * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
2434 */
2435 private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
2436 if (bundle == null || newBundle == null) {
2437 return bundle == newBundle;
2438 }
2439
2440 if (bundle.size() != newBundle.size()) {
2441 return false;
2442 }
2443
2444 for(String key : bundle.keySet()) {
2445 if (key != null) {
2446 final Object value = bundle.get(key);
2447 final Object newValue = newBundle.get(key);
2448 if (!Objects.equals(value, newValue)) {
2449 return false;
2450 }
2451 }
2452 }
2453 return true;
2454 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002455}