blob: 8b894126234f3e8a63b8172f73d2e0cac0619943 [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;
Ravi Paluri404babb2020-01-23 19:02:44 +053020import android.annotation.NonNull;
Hall Liu95d55872017-01-25 17:12:49 -080021import android.annotation.Nullable;
Andrew Leeda80c872015-04-15 14:09:50 -070022import android.annotation.SystemApi;
Hall Liu6dfa2492019-10-01 17:20:39 -070023import android.annotation.TestApi;
Artur Satayev53ada2a2019-12-10 17:47:56 +000024import android.compat.annotation.UnsupportedAppUsage;
Ihab Awade63fadb2014-07-09 21:52:04 -070025import android.net.Uri;
Tyler Gunn6e3ecc42018-11-12 11:30:56 -080026import android.os.Build;
Nancy Chen10798dc2014-08-08 14:00:25 -070027import android.os.Bundle;
Andrew Lee011728f2015-04-23 15:47:06 -070028import android.os.Handler;
Hall Liu95d55872017-01-25 17:12:49 -080029import android.os.ParcelFileDescriptor;
Ihab Awade63fadb2014-07-09 21:52:04 -070030
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -080031import com.android.internal.telecom.IVideoProvider;
32
Hall Liu95d55872017-01-25 17:12:49 -080033import java.io.IOException;
34import java.io.InputStreamReader;
35import java.io.OutputStreamWriter;
Hall Liu95d55872017-01-25 17:12:49 -080036import java.lang.annotation.Retention;
37import java.lang.annotation.RetentionPolicy;
38import java.nio.charset.StandardCharsets;
Ihab Awade63fadb2014-07-09 21:52:04 -070039import java.util.ArrayList;
Tyler Gunn071be6f2016-05-10 14:52:33 -070040import java.util.Arrays;
Ihab Awade63fadb2014-07-09 21:52:04 -070041import java.util.Collections;
42import java.util.List;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070043import java.util.Map;
Ihab Awade63fadb2014-07-09 21:52:04 -070044import java.util.Objects;
Jay Shrauner229e3822014-08-15 09:23:07 -070045import java.util.concurrent.CopyOnWriteArrayList;
Ihab Awade63fadb2014-07-09 21:52:04 -070046
47/**
48 * Represents an ongoing phone call that the in-call app should present to the user.
49 */
50public final class Call {
51 /**
52 * The state of a {@code Call} when newly created.
53 */
54 public static final int STATE_NEW = 0;
55
56 /**
57 * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
58 */
59 public static final int STATE_DIALING = 1;
60
61 /**
62 * The state of an incoming {@code Call} when ringing locally, but not yet connected.
63 */
64 public static final int STATE_RINGING = 2;
65
66 /**
67 * The state of a {@code Call} when in a holding state.
68 */
69 public static final int STATE_HOLDING = 3;
70
71 /**
72 * The state of a {@code Call} when actively supporting conversation.
73 */
74 public static final int STATE_ACTIVE = 4;
75
76 /**
77 * The state of a {@code Call} when no further voice or other communication is being
78 * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
79 * is no longer active, and the local data transport has or inevitably will release resources
80 * associated with this {@code Call}.
81 */
82 public static final int STATE_DISCONNECTED = 7;
83
Nancy Chen5da0fd52014-07-08 14:16:17 -070084 /**
Santos Cordone3c507b2015-04-23 14:44:19 -070085 * The state of an outgoing {@code Call} when waiting on user to select a
86 * {@link PhoneAccount} through which to place the call.
Nancy Chen5da0fd52014-07-08 14:16:17 -070087 */
Santos Cordone3c507b2015-04-23 14:44:19 -070088 public static final int STATE_SELECT_PHONE_ACCOUNT = 8;
89
90 /**
91 * @hide
92 * @deprecated use STATE_SELECT_PHONE_ACCOUNT.
93 */
94 @Deprecated
95 @SystemApi
96 public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT;
Nancy Chen5da0fd52014-07-08 14:16:17 -070097
Nancy Chene20930f2014-08-07 16:17:21 -070098 /**
Nancy Chene9b7a8e2014-08-08 14:26:27 -070099 * The initial state of an outgoing {@code Call}.
100 * Common transitions are to {@link #STATE_DIALING} state for a successful call or
101 * {@link #STATE_DISCONNECTED} if it failed.
Nancy Chene20930f2014-08-07 16:17:21 -0700102 */
103 public static final int STATE_CONNECTING = 9;
104
Nancy Chen513c8922014-09-17 14:47:20 -0700105 /**
Tyler Gunn4afc6af2014-10-07 10:14:55 -0700106 * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
107 * call has not yet been disconnected by the underlying {@code ConnectionService}. The next
108 * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
109 */
110 public static final int STATE_DISCONNECTING = 10;
111
112 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700113 * The state of an external call which is in the process of being pulled from a remote device to
114 * the local device.
115 * <p>
116 * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
117 * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
118 * <p>
119 * An {@link InCallService} will only see this state if it has the
120 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
121 * manifest.
122 */
123 public static final int STATE_PULLING_CALL = 11;
124
125 /**
Hall Liu6dfa2492019-10-01 17:20:39 -0700126 * The state of a call that is active with the network, but the audio from the call is
127 * being intercepted by an app on the local device. Telecom does not hold audio focus in this
128 * state, and the call will be invisible to the user except for a persistent notification.
129 */
130 public static final int STATE_AUDIO_PROCESSING = 12;
131
132 /**
133 * The state of a call that is being presented to the user after being in
134 * {@link #STATE_AUDIO_PROCESSING}. The call is still active with the network in this case, and
135 * Telecom will hold audio focus and play a ringtone if appropriate.
136 */
137 public static final int STATE_SIMULATED_RINGING = 13;
138
139 /**
Nancy Chen513c8922014-09-17 14:47:20 -0700140 * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
141 * extras. Used to pass the phone accounts to display on the front end to the user in order to
142 * select phone accounts to (for example) place a call.
Hall Liu34d9e242018-11-21 17:05:58 -0800143 * @deprecated Use the list from {@link #EXTRA_SUGGESTED_PHONE_ACCOUNTS} instead.
Nancy Chen513c8922014-09-17 14:47:20 -0700144 */
Hall Liu34d9e242018-11-21 17:05:58 -0800145 @Deprecated
Nancy Chen513c8922014-09-17 14:47:20 -0700146 public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
147
mike dooley4af561f2016-12-20 08:55:17 -0800148 /**
Hall Liu34d9e242018-11-21 17:05:58 -0800149 * Key for extra used to pass along a list of {@link PhoneAccountSuggestion}s to the in-call
150 * UI when a call enters the {@link #STATE_SELECT_PHONE_ACCOUNT} state. The list included here
151 * will have the same length and be in the same order as the list passed with
152 * {@link #AVAILABLE_PHONE_ACCOUNTS}.
153 */
154 public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS =
155 "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS";
156
157 /**
mike dooley91217422017-03-09 12:58:42 -0800158 * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC)
159 * when the last outgoing emergency call was made. This is used to identify potential emergency
160 * callbacks.
mike dooley4af561f2016-12-20 08:55:17 -0800161 */
162 public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
163 "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
164
Usman Abdullahb0dc29a2019-03-06 15:54:56 -0800165
166 /**
167 * Extra key used to indicate whether a {@link CallScreeningService} has requested to silence
168 * the ringtone for a call. If the {@link InCallService} declares
169 * {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} in its manifest, it should not
170 * play a ringtone for an incoming call with this extra key set.
171 */
172 public static final String EXTRA_SILENT_RINGING_REQUESTED =
173 "android.telecom.extra.SILENT_RINGING_REQUESTED";
174
Tyler Gunn8bf76572017-04-06 15:30:08 -0700175 /**
176 * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
177 * Telecom that the user has requested that the current {@link Call} should be handed over
178 * to another {@link ConnectionService}.
179 * <p>
180 * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
181 * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
182 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700183 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
184 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700185 */
186 public static final String EVENT_REQUEST_HANDOVER =
187 "android.telecom.event.REQUEST_HANDOVER";
188
189 /**
190 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
191 * {@link PhoneAccountHandle} to which a call should be handed over to.
192 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700193 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
194 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700195 */
196 public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
197 "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
198
199 /**
200 * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
201 * video state of the call when it is handed over to the new {@link PhoneAccount}.
202 * <p>
203 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
204 * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
205 * {@link VideoProfile#STATE_TX_ENABLED}.
206 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700207 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
208 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700209 */
210 public static final String EXTRA_HANDOVER_VIDEO_STATE =
211 "android.telecom.extra.HANDOVER_VIDEO_STATE";
212
213 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700214 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Used by the
215 * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra
216 * information to the handover {@link ConnectionService} specified by
217 * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}.
218 * <p>
219 * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the
220 * {@link ConnectionService} via the request extras when
221 * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
222 * is called to initate the handover.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700223 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700224 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
225 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700226 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700227 public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700228
229 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700230 * Call event sent from Telecom to the handover {@link ConnectionService} via
231 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
232 * to the {@link ConnectionService} has completed successfully.
233 * <p>
234 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700235 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700236 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
237 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700238 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700239 public static final String EVENT_HANDOVER_COMPLETE =
240 "android.telecom.event.HANDOVER_COMPLETE";
Tyler Gunn34a2b312017-06-23 08:32:00 -0700241
242 /**
243 * Call event sent from Telecom to the handover destination {@link ConnectionService} via
244 * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the
245 * source connection has disconnected. The {@link Bundle} parameter for the call event will be
246 * {@code null}.
247 * <p>
248 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
249 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700250 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
251 * APIs instead.
Tyler Gunn34a2b312017-06-23 08:32:00 -0700252 */
253 public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
254 "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
255
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700256 /**
257 * Call event sent from Telecom to the handover {@link ConnectionService} via
258 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
259 * to the {@link ConnectionService} has failed.
260 * <p>
261 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
262 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700263 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
264 * APIs instead.
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700265 */
266 public static final String EVENT_HANDOVER_FAILED =
267 "android.telecom.event.HANDOVER_FAILED";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700268
Tyler Gunnfacfdee2020-01-23 13:10:37 -0800269
270 /**
271 * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
272 * call because they have declined to answer it. This typically means that they are unable
273 * to answer the call at this time and would prefer it be sent to voicemail.
274 */
275 public static final int REJECT_REASON_DECLINED = 1;
276
277 /**
278 * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
279 * call because it is an unwanted call. This allows the user to indicate that they are
280 * rejecting a call because it is likely a nuisance call.
281 */
282 public static final int REJECT_REASON_UNWANTED = 2;
283
284 /**
285 * @hide
286 */
287 @IntDef(prefix = { "REJECT_REASON_" },
288 value = {REJECT_REASON_DECLINED, REJECT_REASON_UNWANTED})
289 @Retention(RetentionPolicy.SOURCE)
290 public @interface RejectReason {};
291
Ihab Awade63fadb2014-07-09 21:52:04 -0700292 public static class Details {
Tyler Gunn94f8f112018-12-17 09:56:11 -0800293 /** @hide */
294 @Retention(RetentionPolicy.SOURCE)
295 @IntDef(
296 prefix = { "DIRECTION_" },
297 value = {DIRECTION_UNKNOWN, DIRECTION_INCOMING, DIRECTION_OUTGOING})
298 public @interface CallDirection {}
299
300 /**
301 * Indicates that the call is neither and incoming nor an outgoing call. This can be the
302 * case for calls reported directly by a {@link ConnectionService} in special cases such as
303 * call handovers.
304 */
305 public static final int DIRECTION_UNKNOWN = -1;
306
307 /**
308 * Indicates that the call is an incoming call.
309 */
310 public static final int DIRECTION_INCOMING = 0;
311
312 /**
313 * Indicates that the call is an outgoing call.
314 */
315 public static final int DIRECTION_OUTGOING = 1;
316
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800317 /** Call can currently be put on hold or unheld. */
318 public static final int CAPABILITY_HOLD = 0x00000001;
319
320 /** Call supports the hold feature. */
321 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
322
323 /**
324 * Calls within a conference can be merged. A {@link ConnectionService} has the option to
325 * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
326 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
327 * capability allows a merge button to be shown while the conference call is in the foreground
328 * of the in-call UI.
329 * <p>
330 * This is only intended for use by a {@link Conference}.
331 */
332 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
333
334 /**
335 * Calls within a conference can be swapped between foreground and background.
336 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
337 * <p>
338 * This is only intended for use by a {@link Conference}.
339 */
340 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
341
342 /**
343 * @hide
344 */
Andrew Lee2378ea72015-04-29 14:38:11 -0700345 public static final int CAPABILITY_UNUSED_1 = 0x00000010;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800346
347 /** Call supports responding via text option. */
348 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
349
350 /** Call can be muted. */
351 public static final int CAPABILITY_MUTE = 0x00000040;
352
353 /**
354 * Call supports conference call management. This capability only applies to {@link Conference}
355 * calls which can have {@link Connection}s as children.
356 */
357 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
358
359 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700360 * Local device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800361 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700362 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800363
364 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700365 * Local device supports transmitting video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800366 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700367 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800368
369 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700370 * Local device supports bidirectional video calling.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800371 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700372 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700373 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800374
375 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700376 * Remote device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800377 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700378 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
379
380 /**
381 * Remote device supports transmitting video.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700382 */
383 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
384
385 /**
386 * Remote device supports bidirectional video calling.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700387 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700388 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700389 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800390
391 /**
392 * Call is able to be separated from its parent {@code Conference}, if any.
393 */
394 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
395
396 /**
397 * Call is able to be individually disconnected when in a {@code Conference}.
398 */
399 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
400
401 /**
Dong Zhou89f41eb2015-03-15 11:59:49 -0500402 * Speed up audio setup for MT call.
403 * @hide
404 */
Tyler Gunn96d6c402015-03-18 12:39:23 -0700405 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
406
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700407 /**
408 * Call can be upgraded to a video call.
Rekha Kumar07366812015-03-24 16:42:31 -0700409 * @hide
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800410 * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
411 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call
412 * whether or not video calling is supported.
Rekha Kumar07366812015-03-24 16:42:31 -0700413 */
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800414 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
Rekha Kumar07366812015-03-24 16:42:31 -0700415 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
416
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700417 /**
418 * For video calls, indicates whether the outgoing video for the call can be paused using
Yorke Lee32f24732015-05-12 16:18:03 -0700419 * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700420 */
421 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
422
Bryce Lee81901682015-08-28 16:38:02 -0700423 /**
424 * Call sends responses through connection.
425 * @hide
426 */
Tyler Gunnf97a0092016-01-19 15:59:34 -0800427 public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;
428
429 /**
430 * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
431 * <p>
432 * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
433 * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
434 * downgraded from a video call back to a VideoState of
435 * {@link VideoProfile#STATE_AUDIO_ONLY}.
436 * <p>
437 * Intuitively, a call which can be downgraded to audio should also have local and remote
438 * video
439 * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
440 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
441 */
442 public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
Bryce Lee81901682015-08-28 16:38:02 -0700443
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700444 /**
445 * When set for an external call, indicates that this {@code Call} can be pulled from a
446 * remote device to the current device.
447 * <p>
448 * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
449 * <p>
450 * An {@link InCallService} will only see calls with this capability if it has the
451 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
452 * in its manifest.
453 * <p>
454 * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
Tyler Gunn720c6642016-03-22 09:02:47 -0700455 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700456 */
457 public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
458
Pooja Jaind34698d2017-12-28 14:15:31 +0530459 /** Call supports the deflect feature. */
460 public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
461
Tyler Gunn0c62ef02020-02-11 14:39:43 -0800462 /**
463 * Call supports adding participants to the call via
Grace Jia8587ee52020-07-10 15:42:32 -0700464 * {@link #addConferenceParticipants(List)}. Once participants are added, the call becomes
465 * an adhoc conference call ({@link #PROPERTY_IS_ADHOC_CONFERENCE}).
Tyler Gunn0c62ef02020-02-11 14:39:43 -0800466 */
Ravi Paluri404babb2020-01-23 19:02:44 +0530467 public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
Ravi Palurif4b38e72020-02-05 12:35:41 +0530468
469 /**
470 * When set for a call, indicates that this {@code Call} can be transferred to another
471 * number.
472 * Call supports the blind and assured call transfer feature.
473 *
474 * @hide
475 */
476 public static final int CAPABILITY_TRANSFER = 0x04000000;
477
478 /**
479 * When set for a call, indicates that this {@code Call} can be transferred to another
480 * ongoing call.
481 * Call supports the consultative call transfer feature.
482 *
483 * @hide
484 */
485 public static final int CAPABILITY_TRANSFER_CONSULTATIVE = 0x08000000;
486
Tyler Gunnd11a3152015-03-18 13:09:14 -0700487 //******************************************************************************************
Ravi Palurif4b38e72020-02-05 12:35:41 +0530488 // Next CAPABILITY value: 0x10000000
Andrew Lee2378ea72015-04-29 14:38:11 -0700489 //******************************************************************************************
490
491 /**
492 * Whether the call is currently a conference.
493 */
494 public static final int PROPERTY_CONFERENCE = 0x00000001;
495
496 /**
497 * Whether the call is a generic conference, where we do not know the precise state of
498 * participants in the conference (eg. on CDMA).
499 */
500 public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
501
502 /**
503 * Whether the call is made while the device is in emergency callback mode.
504 */
505 public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
506
507 /**
508 * Connection is using WIFI.
509 */
510 public static final int PROPERTY_WIFI = 0x00000008;
511
512 /**
Tyler Gunn6b6ae552018-10-11 10:42:10 -0700513 * When set, the UI should indicate to the user that a call is using high definition
514 * audio.
515 * <p>
516 * The underlying {@link ConnectionService} is responsible for reporting this
517 * property. It is important to note that this property is not intended to report the
518 * actual audio codec being used for a Call, but whether the call should be indicated
519 * to the user as high definition.
520 * <p>
521 * The Android Telephony stack reports this property for calls based on a number
522 * of factors, including which audio codec is used and whether a call is using an HD
523 * codec end-to-end. Some mobile operators choose to suppress display of an HD indication,
524 * and in these cases this property will not be set for a call even if the underlying audio
525 * codec is in fact "high definition".
Andrew Lee2378ea72015-04-29 14:38:11 -0700526 */
527 public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
528
Tony Maka68dcce2015-12-17 09:31:18 +0000529 /**
Tony Mak53b5df42016-05-19 13:40:38 +0100530 * Whether the call is associated with the work profile.
531 */
532 public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;
533
534 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700535 * When set, indicates that this {@code Call} does not actually exist locally for the
536 * {@link ConnectionService}.
537 * <p>
538 * Consider, for example, a scenario where a user has two phones with the same phone number.
539 * When a user places a call on one device, the telephony stack can represent that call on
540 * the other device by adding it to the {@link ConnectionService} with the
Tyler Gunn720c6642016-03-22 09:02:47 -0700541 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700542 * <p>
543 * An {@link InCallService} will only see calls with this property if it has the
544 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
545 * in its manifest.
546 * <p>
Tyler Gunn720c6642016-03-22 09:02:47 -0700547 * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700548 */
549 public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
550
Brad Ebinger15847072016-05-18 11:08:36 -0700551 /**
552 * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
553 */
554 public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
555
Tyler Gunn24e18332017-02-10 09:42:49 -0800556 /**
557 * Indicates that the call is from a self-managed {@link ConnectionService}.
558 * <p>
559 * See also {@link Connection#PROPERTY_SELF_MANAGED}
560 */
561 public static final int PROPERTY_SELF_MANAGED = 0x00000100;
562
Eric Erfanianec881872017-12-06 16:27:53 -0800563 /**
564 * Indicates the call used Assisted Dialing.
Tyler Gunn5567d742019-10-31 13:04:37 -0700565 *
566 * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING
Eric Erfanianec881872017-12-06 16:27:53 -0800567 */
Tyler Gunnc9503d62020-01-27 10:30:51 -0800568 public static final int PROPERTY_ASSISTED_DIALING = 0x00000200;
Eric Erfanianec881872017-12-06 16:27:53 -0800569
Hall Liue9041242018-02-09 16:40:03 -0800570 /**
571 * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
572 * {@link RttCall} object that is used to send and receive text.
573 */
574 public static final int PROPERTY_RTT = 0x00000400;
575
Tyler Gunn5bd90852018-09-21 09:37:07 -0700576 /**
577 * Indicates that the call has been identified as the network as an emergency call. This
578 * property may be set for both incoming and outgoing calls which the network identifies as
579 * emergency calls.
580 */
581 public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 0x00000800;
582
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700583 /**
584 * Indicates that the call is using VoIP audio mode.
585 * <p>
586 * When this property is set, the {@link android.media.AudioManager} audio mode for this
587 * call will be {@link android.media.AudioManager#MODE_IN_COMMUNICATION}. When this
588 * property is not set, the audio mode for this call will be
589 * {@link android.media.AudioManager#MODE_IN_CALL}.
590 * <p>
591 * This property reflects changes made using {@link Connection#setAudioModeIsVoip(boolean)}.
592 * <p>
593 * You can use this property to determine whether an un-answered incoming call or a held
594 * call will use VoIP audio mode (if the call does not currently have focus, the system
595 * audio mode may not reflect the mode the call will use).
596 */
597 public static final int PROPERTY_VOIP_AUDIO_MODE = 0x00001000;
598
Ravi Paluri80aa2142019-12-02 11:57:37 +0530599 /**
600 * Indicates that the call is an adhoc conference call. This property can be set for both
Grace Jia8587ee52020-07-10 15:42:32 -0700601 * incoming and outgoing calls. An adhoc conference call is formed using
602 * {@link #addConferenceParticipants(List)},
603 * {@link TelecomManager#addNewIncomingConference(PhoneAccountHandle, Bundle)}, or
604 * {@link TelecomManager#startConference(List, Bundle)}, rather than by merging existing
605 * call using {@link #conference(Call)}.
Ravi Paluri80aa2142019-12-02 11:57:37 +0530606 */
607 public static final int PROPERTY_IS_ADHOC_CONFERENCE = 0x00002000;
608
Andrew Lee2378ea72015-04-29 14:38:11 -0700609 //******************************************************************************************
Ravi Paluri80aa2142019-12-02 11:57:37 +0530610 // Next PROPERTY value: 0x00004000
Tyler Gunnd11a3152015-03-18 13:09:14 -0700611 //******************************************************************************************
Tyler Gunn068085b2015-02-06 13:56:52 -0800612
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800613 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700614 private final Uri mHandle;
615 private final int mHandlePresentation;
616 private final String mCallerDisplayName;
617 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700618 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700619 private final int mCallCapabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700620 private final int mCallProperties;
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800621 private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700622 private final DisconnectCause mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700623 private final long mConnectTimeMillis;
624 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700625 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700626 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700627 private final Bundle mExtras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700628 private final Bundle mIntentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700629 private final long mCreationTimeMillis;
Hall Liuef98bf82020-01-09 15:22:44 -0800630 private final String mContactDisplayName;
Tyler Gunn94f8f112018-12-17 09:56:11 -0800631 private final @CallDirection int mCallDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700632 private final @Connection.VerificationStatus int mCallerNumberVerificationStatus;
Ihab Awade63fadb2014-07-09 21:52:04 -0700633
634 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800635 * Whether the supplied capabilities supports the specified capability.
636 *
637 * @param capabilities A bit field of capabilities.
638 * @param capability The capability to check capabilities for.
639 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800640 */
641 public static boolean can(int capabilities, int capability) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800642 return (capabilities & capability) == capability;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800643 }
644
645 /**
646 * Whether the capabilities of this {@code Details} supports the specified capability.
647 *
648 * @param capability The capability to check capabilities for.
649 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800650 */
651 public boolean can(int capability) {
652 return can(mCallCapabilities, capability);
653 }
654
655 /**
656 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
657 *
658 * @param capabilities A capability bit field.
659 * @return A human readable string representation.
660 */
661 public static String capabilitiesToString(int capabilities) {
662 StringBuilder builder = new StringBuilder();
663 builder.append("[Capabilities:");
664 if (can(capabilities, CAPABILITY_HOLD)) {
665 builder.append(" CAPABILITY_HOLD");
666 }
667 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
668 builder.append(" CAPABILITY_SUPPORT_HOLD");
669 }
670 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
671 builder.append(" CAPABILITY_MERGE_CONFERENCE");
672 }
673 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
674 builder.append(" CAPABILITY_SWAP_CONFERENCE");
675 }
676 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
677 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
678 }
679 if (can(capabilities, CAPABILITY_MUTE)) {
680 builder.append(" CAPABILITY_MUTE");
681 }
682 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
683 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
684 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700685 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
686 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
687 }
688 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
689 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
690 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700691 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
692 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800693 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700694 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
695 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
696 }
697 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
698 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
699 }
Tyler Gunnf97a0092016-01-19 15:59:34 -0800700 if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
701 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
702 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700703 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
704 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800705 }
Dong Zhou89f41eb2015-03-15 11:59:49 -0500706 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
Tyler Gunnd11a3152015-03-18 13:09:14 -0700707 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
Dong Zhou89f41eb2015-03-15 11:59:49 -0500708 }
Rekha Kumar07366812015-03-24 16:42:31 -0700709 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
710 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
711 }
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700712 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
713 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
714 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700715 if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
716 builder.append(" CAPABILITY_CAN_PULL_CALL");
717 }
Pooja Jaind34698d2017-12-28 14:15:31 +0530718 if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
719 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
720 }
Ravi Paluri404babb2020-01-23 19:02:44 +0530721 if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) {
722 builder.append(" CAPABILITY_ADD_PARTICIPANT");
723 }
Ravi Palurif4b38e72020-02-05 12:35:41 +0530724 if (can(capabilities, CAPABILITY_TRANSFER)) {
725 builder.append(" CAPABILITY_TRANSFER");
726 }
727 if (can(capabilities, CAPABILITY_TRANSFER_CONSULTATIVE)) {
728 builder.append(" CAPABILITY_TRANSFER_CONSULTATIVE");
729 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800730 builder.append("]");
731 return builder.toString();
732 }
733
734 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700735 * Whether the supplied properties includes the specified property.
736 *
737 * @param properties A bit field of properties.
738 * @param property The property to check properties for.
739 * @return Whether the specified property is supported.
740 */
741 public static boolean hasProperty(int properties, int property) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800742 return (properties & property) == property;
Andrew Lee2378ea72015-04-29 14:38:11 -0700743 }
744
745 /**
746 * Whether the properties of this {@code Details} includes the specified property.
747 *
748 * @param property The property to check properties for.
749 * @return Whether the specified property is supported.
750 */
751 public boolean hasProperty(int property) {
752 return hasProperty(mCallProperties, property);
753 }
754
755 /**
756 * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
757 *
758 * @param properties A property bit field.
759 * @return A human readable string representation.
760 */
761 public static String propertiesToString(int properties) {
762 StringBuilder builder = new StringBuilder();
763 builder.append("[Properties:");
764 if (hasProperty(properties, PROPERTY_CONFERENCE)) {
765 builder.append(" PROPERTY_CONFERENCE");
766 }
767 if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
768 builder.append(" PROPERTY_GENERIC_CONFERENCE");
769 }
770 if (hasProperty(properties, PROPERTY_WIFI)) {
771 builder.append(" PROPERTY_WIFI");
772 }
773 if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
774 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
775 }
776 if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
Yorke Leebe2a4a22015-06-12 10:10:55 -0700777 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
Andrew Lee2378ea72015-04-29 14:38:11 -0700778 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700779 if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
780 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
781 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700782 if (hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
Brad Ebinger15847072016-05-18 11:08:36 -0700783 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
784 }
Tyler Gunnc9503d62020-01-27 10:30:51 -0800785 if (hasProperty(properties, PROPERTY_ASSISTED_DIALING)) {
Eric Erfanianec881872017-12-06 16:27:53 -0800786 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
787 }
Tyler Gunn5bd90852018-09-21 09:37:07 -0700788 if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
789 builder.append(" PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL");
790 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700791 if (hasProperty(properties, PROPERTY_RTT)) {
792 builder.append(" PROPERTY_RTT");
793 }
794 if (hasProperty(properties, PROPERTY_VOIP_AUDIO_MODE)) {
795 builder.append(" PROPERTY_VOIP_AUDIO_MODE");
796 }
Ravi Paluri80aa2142019-12-02 11:57:37 +0530797 if (hasProperty(properties, PROPERTY_IS_ADHOC_CONFERENCE)) {
798 builder.append(" PROPERTY_IS_ADHOC_CONFERENCE");
799 }
Andrew Lee2378ea72015-04-29 14:38:11 -0700800 builder.append("]");
801 return builder.toString();
802 }
803
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800804 /** {@hide} */
Hall Liu31de23d2019-10-11 15:38:29 -0700805 @TestApi
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800806 public String getTelecomCallId() {
807 return mTelecomCallId;
808 }
809
Andrew Lee2378ea72015-04-29 14:38:11 -0700810 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700811 * @return The handle (e.g., phone number) to which the {@code Call} is currently
812 * connected.
813 */
814 public Uri getHandle() {
815 return mHandle;
816 }
817
818 /**
819 * @return The presentation requirements for the handle. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700820 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700821 */
822 public int getHandlePresentation() {
823 return mHandlePresentation;
824 }
825
826 /**
Tyler Gunnd081f042018-12-04 12:56:45 -0800827 * The display name for the caller.
828 * <p>
829 * This is the name as reported by the {@link ConnectionService} associated with this call.
Tyler Gunnd081f042018-12-04 12:56:45 -0800830 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700831 * @return The display name for the caller.
832 */
833 public String getCallerDisplayName() {
834 return mCallerDisplayName;
835 }
836
837 /**
838 * @return The presentation requirements for the caller display name. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700839 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700840 */
841 public int getCallerDisplayNamePresentation() {
842 return mCallerDisplayNamePresentation;
843 }
844
845 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700846 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
847 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700848 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700849 public PhoneAccountHandle getAccountHandle() {
850 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -0700851 }
852
853 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800854 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
855 * {@code CAPABILITY_*} constants in this class.
Ihab Awade63fadb2014-07-09 21:52:04 -0700856 */
Ihab Awad5d0410f2014-07-30 10:07:40 -0700857 public int getCallCapabilities() {
858 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700859 }
860
861 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700862 * @return A bitmask of the properties of the {@code Call}, as defined by the various
863 * {@code PROPERTY_*} constants in this class.
Andrew Lee223ad142014-08-27 16:33:08 -0700864 */
865 public int getCallProperties() {
866 return mCallProperties;
867 }
868
869 /**
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800870 * @return a bitmask of the audio routes available for the call.
871 *
872 * @hide
873 */
874 public int getSupportedAudioRoutes() {
875 return mSupportedAudioRoutes;
876 }
877
878 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700879 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
Nancy Chenf4cf77c2014-09-19 10:53:21 -0700880 * by {@link android.telecom.DisconnectCause}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700881 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700882 public DisconnectCause getDisconnectCause() {
883 return mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700884 }
885
886 /**
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700887 * Returns the time the {@link Call} connected (i.e. became active). This information is
888 * updated periodically, but user interfaces should not rely on this to display the "call
889 * time clock". For the time when the call was first added to Telecom, see
890 * {@link #getCreationTimeMillis()}.
891 *
892 * @return The time the {@link Call} connected in milliseconds since the epoch.
Ihab Awade63fadb2014-07-09 21:52:04 -0700893 */
Jay Shrauner164a0ac2015-04-14 18:16:10 -0700894 public final long getConnectTimeMillis() {
Ihab Awade63fadb2014-07-09 21:52:04 -0700895 return mConnectTimeMillis;
896 }
897
898 /**
899 * @return Information about any calling gateway the {@code Call} may be using.
900 */
901 public GatewayInfo getGatewayInfo() {
902 return mGatewayInfo;
903 }
904
Andrew Lee7a341382014-07-15 17:05:08 -0700905 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -0700906 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -0700907 */
908 public int getVideoState() {
909 return mVideoState;
910 }
911
Ihab Awad5d0410f2014-07-30 10:07:40 -0700912 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700913 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
Ihab Awad5d0410f2014-07-30 10:07:40 -0700914 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -0700915 */
916 public StatusHints getStatusHints() {
917 return mStatusHints;
918 }
919
Nancy Chen10798dc2014-08-08 14:00:25 -0700920 /**
Santos Cordon6b7f9552015-05-27 17:21:45 -0700921 * @return The extras associated with this call.
Nancy Chen10798dc2014-08-08 14:00:25 -0700922 */
923 public Bundle getExtras() {
924 return mExtras;
925 }
926
Santos Cordon6b7f9552015-05-27 17:21:45 -0700927 /**
928 * @return The extras used with the original intent to place this call.
929 */
930 public Bundle getIntentExtras() {
931 return mIntentExtras;
932 }
933
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700934 /**
935 * Returns the time when the call was first created and added to Telecom. This is the same
936 * time that is logged as the start time in the Call Log (see
937 * {@link android.provider.CallLog.Calls#DATE}). To determine when the call was connected
938 * (became active), see {@link #getConnectTimeMillis()}.
939 *
940 * @return The creation time of the call, in millis since the epoch.
941 */
942 public long getCreationTimeMillis() {
943 return mCreationTimeMillis;
944 }
945
Tyler Gunnd081f042018-12-04 12:56:45 -0800946 /**
Hall Liuef98bf82020-01-09 15:22:44 -0800947 * Returns the name of the caller on the remote end, as derived from a
948 * {@link android.provider.ContactsContract} lookup of the call's handle.
949 * @return The name of the caller, or {@code null} if the lookup is not yet complete, if
950 * there's no contacts entry for the caller, or if the {@link InCallService} does
951 * not hold the {@link android.Manifest.permission#READ_CONTACTS} permission.
952 */
953 public @Nullable String getContactDisplayName() {
954 return mContactDisplayName;
955 }
956
957 /**
Tyler Gunn94f8f112018-12-17 09:56:11 -0800958 * Indicates whether the call is an incoming or outgoing call.
959 * @return The call's direction.
960 */
961 public @CallDirection int getCallDirection() {
962 return mCallDirection;
963 }
964
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700965 /**
966 * Gets the verification status for the phone number of an incoming call as identified in
967 * ATIS-1000082.
968 * @return the verification status.
969 */
970 public @Connection.VerificationStatus int getCallerNumberVerificationStatus() {
971 return mCallerNumberVerificationStatus;
972 }
973
Ihab Awade63fadb2014-07-09 21:52:04 -0700974 @Override
975 public boolean equals(Object o) {
976 if (o instanceof Details) {
977 Details d = (Details) o;
978 return
979 Objects.equals(mHandle, d.mHandle) &&
980 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
981 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
982 Objects.equals(mCallerDisplayNamePresentation,
983 d.mCallerDisplayNamePresentation) &&
Evan Charlton8c8a0622014-07-20 12:31:00 -0700984 Objects.equals(mAccountHandle, d.mAccountHandle) &&
Ihab Awad5d0410f2014-07-30 10:07:40 -0700985 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Andrew Lee223ad142014-08-27 16:33:08 -0700986 Objects.equals(mCallProperties, d.mCallProperties) &&
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700987 Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
Ihab Awade63fadb2014-07-09 21:52:04 -0700988 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Andrew Lee85f5d422014-07-11 17:22:03 -0700989 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Evan Charlton5b49ade2014-07-15 17:03:20 -0700990 Objects.equals(mVideoState, d.mVideoState) &&
Nancy Chen10798dc2014-08-08 14:00:25 -0700991 Objects.equals(mStatusHints, d.mStatusHints) &&
Tyler Gunn1e9bfc62015-08-19 11:18:58 -0700992 areBundlesEqual(mExtras, d.mExtras) &&
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700993 areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
Tyler Gunnd081f042018-12-04 12:56:45 -0800994 Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis) &&
Hall Liuef98bf82020-01-09 15:22:44 -0800995 Objects.equals(mContactDisplayName, d.mContactDisplayName) &&
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700996 Objects.equals(mCallDirection, d.mCallDirection) &&
997 Objects.equals(mCallerNumberVerificationStatus,
998 d.mCallerNumberVerificationStatus);
Ihab Awade63fadb2014-07-09 21:52:04 -0700999 }
1000 return false;
1001 }
1002
1003 @Override
1004 public int hashCode() {
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001005 return Objects.hash(mHandle,
1006 mHandlePresentation,
1007 mCallerDisplayName,
1008 mCallerDisplayNamePresentation,
1009 mAccountHandle,
1010 mCallCapabilities,
1011 mCallProperties,
1012 mDisconnectCause,
1013 mConnectTimeMillis,
1014 mGatewayInfo,
1015 mVideoState,
1016 mStatusHints,
1017 mExtras,
1018 mIntentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -08001019 mCreationTimeMillis,
Hall Liuef98bf82020-01-09 15:22:44 -08001020 mContactDisplayName,
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001021 mCallDirection,
1022 mCallerNumberVerificationStatus);
Ihab Awade63fadb2014-07-09 21:52:04 -07001023 }
1024
1025 /** {@hide} */
1026 public Details(
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001027 String telecomCallId,
Ihab Awade63fadb2014-07-09 21:52:04 -07001028 Uri handle,
1029 int handlePresentation,
1030 String callerDisplayName,
1031 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -07001032 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -07001033 int capabilities,
Andrew Lee223ad142014-08-27 16:33:08 -07001034 int properties,
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001035 DisconnectCause disconnectCause,
Ihab Awade63fadb2014-07-09 21:52:04 -07001036 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -07001037 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -07001038 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -07001039 StatusHints statusHints,
Santos Cordon6b7f9552015-05-27 17:21:45 -07001040 Bundle extras,
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001041 Bundle intentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -08001042 long creationTimeMillis,
Hall Liuef98bf82020-01-09 15:22:44 -08001043 String contactDisplayName,
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001044 int callDirection,
1045 int callerNumberVerificationStatus) {
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001046 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001047 mHandle = handle;
1048 mHandlePresentation = handlePresentation;
1049 mCallerDisplayName = callerDisplayName;
1050 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -07001051 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -07001052 mCallCapabilities = capabilities;
Andrew Lee223ad142014-08-27 16:33:08 -07001053 mCallProperties = properties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001054 mDisconnectCause = disconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -07001055 mConnectTimeMillis = connectTimeMillis;
1056 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -07001057 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -07001058 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -07001059 mExtras = extras;
Santos Cordon6b7f9552015-05-27 17:21:45 -07001060 mIntentExtras = intentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001061 mCreationTimeMillis = creationTimeMillis;
Hall Liuef98bf82020-01-09 15:22:44 -08001062 mContactDisplayName = contactDisplayName;
Tyler Gunn94f8f112018-12-17 09:56:11 -08001063 mCallDirection = callDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001064 mCallerNumberVerificationStatus = callerNumberVerificationStatus;
Ihab Awade63fadb2014-07-09 21:52:04 -07001065 }
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001066
1067 /** {@hide} */
1068 public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
1069 return new Details(
1070 parcelableCall.getId(),
1071 parcelableCall.getHandle(),
1072 parcelableCall.getHandlePresentation(),
1073 parcelableCall.getCallerDisplayName(),
1074 parcelableCall.getCallerDisplayNamePresentation(),
1075 parcelableCall.getAccountHandle(),
1076 parcelableCall.getCapabilities(),
1077 parcelableCall.getProperties(),
1078 parcelableCall.getDisconnectCause(),
1079 parcelableCall.getConnectTimeMillis(),
1080 parcelableCall.getGatewayInfo(),
1081 parcelableCall.getVideoState(),
1082 parcelableCall.getStatusHints(),
1083 parcelableCall.getExtras(),
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001084 parcelableCall.getIntentExtras(),
Tyler Gunnd081f042018-12-04 12:56:45 -08001085 parcelableCall.getCreationTimeMillis(),
Hall Liuef98bf82020-01-09 15:22:44 -08001086 parcelableCall.getContactDisplayName(),
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001087 parcelableCall.getCallDirection(),
1088 parcelableCall.getCallerNumberVerificationStatus());
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001089 }
Santos Cordon3c20d632016-02-25 16:12:35 -08001090
1091 @Override
1092 public String toString() {
1093 StringBuilder sb = new StringBuilder();
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001094 sb.append("[id: ");
1095 sb.append(mTelecomCallId);
1096 sb.append(", pa: ");
Santos Cordon3c20d632016-02-25 16:12:35 -08001097 sb.append(mAccountHandle);
1098 sb.append(", hdl: ");
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001099 sb.append(Log.piiHandle(mHandle));
1100 sb.append(", hdlPres: ");
1101 sb.append(mHandlePresentation);
1102 sb.append(", videoState: ");
1103 sb.append(VideoProfile.videoStateToString(mVideoState));
Santos Cordon3c20d632016-02-25 16:12:35 -08001104 sb.append(", caps: ");
1105 sb.append(capabilitiesToString(mCallCapabilities));
1106 sb.append(", props: ");
Tyler Gunn720c6642016-03-22 09:02:47 -07001107 sb.append(propertiesToString(mCallProperties));
Santos Cordon3c20d632016-02-25 16:12:35 -08001108 sb.append("]");
1109 return sb.toString();
1110 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001111 }
1112
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001113 /**
1114 * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
1115 * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
1116 * implementation.
1117 * <p>
1118 * You can handle these callbacks by extending the {@link Callback} class and overriding the
1119 * callbacks that your {@link InCallService} is interested in. The callback methods include the
1120 * {@link Call} for which the callback applies, allowing reuse of a single instance of your
1121 * {@link Callback} implementation, if desired.
1122 * <p>
1123 * Use {@link Call#registerCallback(Callback)} to register your callback(s). Ensure
1124 * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
1125 * (typically in {@link InCallService#onCallRemoved(Call)}).
1126 * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
1127 * reach your implementation of {@link Callback}, so it is important to register your callback
1128 * as soon as your {@link InCallService} is notified of a new call via
1129 * {@link InCallService#onCallAdded(Call)}.
1130 */
Andrew Leeda80c872015-04-15 14:09:50 -07001131 public static abstract class Callback {
Ihab Awade63fadb2014-07-09 21:52:04 -07001132 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001133 * @hide
1134 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001135 @IntDef(prefix = { "HANDOVER_" },
1136 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
Tyler Gunn5c60d712018-03-16 09:53:44 -07001137 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
Tyler Gunn9d127732018-03-02 15:45:51 -08001138 HANDOVER_FAILURE_UNKNOWN})
Sanket Padawea8eddd42017-11-03 11:07:35 -07001139 @Retention(RetentionPolicy.SOURCE)
1140 public @interface HandoverFailureErrors {}
1141
1142 /**
1143 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
Tyler Gunn9d127732018-03-02 15:45:51 -08001144 * to handover the call to rejects the handover request.
1145 * <p>
1146 * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
1147 * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
1148 * {@code null} {@link Connection} from
1149 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1150 * ConnectionRequest)}.
1151 * <p>
1152 * For more information on call handovers, see
1153 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001154 */
1155 public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
1156
1157 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001158 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1159 * is initiated but the source or destination app does not support handover.
1160 * <p>
1161 * Will be returned when a handover is requested via
1162 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
1163 * {@link PhoneAccountHandle} does not declare
1164 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}. May also be returned when a handover is
1165 * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
1166 * {@link Details#getAccountHandle()}) does not declare
1167 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
1168 * <p>
1169 * For more information on call handovers, see
1170 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001171 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001172 public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001173
1174 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001175 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
1176 * user rejects the handover request.
1177 * <p>
1178 * For more information on call handovers, see
1179 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001180 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001181 public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001182
Sanket Padawe85291f62017-12-01 13:59:27 -08001183 /**
1184 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
1185 * is ongoing emergency call.
Tyler Gunn9d127732018-03-02 15:45:51 -08001186 * <p>
1187 * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
1188 * called on an emergency call, or if any other call is an emergency call.
1189 * <p>
1190 * Handovers are not permitted while there are ongoing emergency calls.
1191 * <p>
1192 * For more information on call handovers, see
1193 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawe85291f62017-12-01 13:59:27 -08001194 */
Tyler Gunn5c60d712018-03-16 09:53:44 -07001195 public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
Sanket Padawe85291f62017-12-01 13:59:27 -08001196
Tyler Gunn9d127732018-03-02 15:45:51 -08001197 /**
1198 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1199 * fails for an unknown reason.
1200 * <p>
1201 * For more information on call handovers, see
1202 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
1203 */
1204 public static final int HANDOVER_FAILURE_UNKNOWN = 5;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001205
1206 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001207 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
1208 *
Ihab Awade63fadb2014-07-09 21:52:04 -07001209 * @param call The {@code Call} invoking this method.
1210 * @param state The new state of the {@code Call}.
1211 */
1212 public void onStateChanged(Call call, int state) {}
1213
1214 /**
1215 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
1216 *
1217 * @param call The {@code Call} invoking this method.
1218 * @param parent The new parent of the {@code Call}.
1219 */
1220 public void onParentChanged(Call call, Call parent) {}
1221
1222 /**
1223 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
1224 *
1225 * @param call The {@code Call} invoking this method.
1226 * @param children The new children of the {@code Call}.
1227 */
1228 public void onChildrenChanged(Call call, List<Call> children) {}
1229
1230 /**
1231 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
1232 *
1233 * @param call The {@code Call} invoking this method.
1234 * @param details A {@code Details} object describing the {@code Call}.
1235 */
1236 public void onDetailsChanged(Call call, Details details) {}
1237
1238 /**
1239 * Invoked when the text messages that can be used as responses to the incoming
1240 * {@code Call} are loaded from the relevant database.
1241 * See {@link #getCannedTextResponses()}.
1242 *
1243 * @param call The {@code Call} invoking this method.
1244 * @param cannedTextResponses The text messages useable as responses.
1245 */
1246 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
1247
1248 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001249 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
1250 * character. This causes the post-dial signals to stop pending user confirmation. An
1251 * implementation should present this choice to the user and invoke
1252 * {@link #postDialContinue(boolean)} when the user makes the choice.
1253 *
1254 * @param call The {@code Call} invoking this method.
1255 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
1256 */
1257 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
1258
1259 /**
Andrew Lee50aca232014-07-22 16:41:54 -07001260 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -07001261 *
1262 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -07001263 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001264 */
Andrew Lee50aca232014-07-22 16:41:54 -07001265 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -07001266
1267 /**
1268 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
1269 * up their UI for the {@code Call} in response to state transitions. Specifically,
1270 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
1271 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
1272 * clients should wait for this method to be invoked.
1273 *
1274 * @param call The {@code Call} being destroyed.
1275 */
1276 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001277
1278 /**
1279 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
1280 * conferenced.
1281 *
1282 * @param call The {@code Call} being updated.
1283 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
1284 * conferenced.
1285 */
1286 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001287
1288 /**
Tyler Gunn5567d742019-10-31 13:04:37 -07001289 * Invoked when a {@link Call} receives an event from its associated {@link Connection} or
1290 * {@link Conference}.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001291 * <p>
1292 * Where possible, the Call should make an attempt to handle {@link Connection} events which
1293 * are part of the {@code android.telecom.*} namespace. The Call should ignore any events
1294 * it does not wish to handle. Unexpected events should be handled gracefully, as it is
1295 * possible that a {@link ConnectionService} has defined its own Connection events which a
1296 * Call is not aware of.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001297 * <p>
Tyler Gunn5567d742019-10-31 13:04:37 -07001298 * See {@link Connection#sendConnectionEvent(String, Bundle)},
1299 * {@link Conference#sendConferenceEvent(String, Bundle)}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001300 *
1301 * @param call The {@code Call} receiving the event.
1302 * @param event The event.
1303 * @param extras Extras associated with the connection event.
1304 */
1305 public void onConnectionEvent(Call call, String event, Bundle extras) {}
Hall Liu95d55872017-01-25 17:12:49 -08001306
1307 /**
1308 * Invoked when the RTT mode changes for this call.
1309 * @param call The call whose RTT mode has changed.
1310 * @param mode the new RTT mode, one of
1311 * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
1312 * or {@link RttCall#RTT_MODE_VCO}
1313 */
1314 public void onRttModeChanged(Call call, int mode) {}
1315
1316 /**
1317 * Invoked when the call's RTT status changes, either from off to on or from on to off.
1318 * @param call The call whose RTT status has changed.
1319 * @param enabled whether RTT is now enabled or disabled
1320 * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
1321 * on, null otherwise.
1322 */
1323 public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
1324
1325 /**
1326 * Invoked when the remote end of the connection has requested that an RTT communication
1327 * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
1328 * with the same ID that this method is invoked with.
1329 * @param call The call which the RTT request was placed on
1330 * @param id The ID of the request.
1331 */
1332 public void onRttRequest(Call call, int id) {}
Hall Liu57006aa2017-02-06 10:49:48 -08001333
1334 /**
1335 * Invoked when the RTT session failed to initiate for some reason, including rejection
1336 * by the remote party.
1337 * @param call The call which the RTT initiation failure occurred on.
1338 * @param reason One of the status codes defined in
1339 * {@link android.telecom.Connection.RttModifyStatus}, with the exception of
1340 * {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
1341 */
1342 public void onRttInitiationFailure(Call call, int reason) {}
Sanket Padawea8eddd42017-11-03 11:07:35 -07001343
1344 /**
1345 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1346 * has completed successfully.
Tyler Gunn9d127732018-03-02 15:45:51 -08001347 * <p>
1348 * For a full discussion of the handover process and the APIs involved, see
1349 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1350 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001351 * @param call The call which had initiated handover.
1352 */
1353 public void onHandoverComplete(Call call) {}
1354
1355 /**
1356 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1357 * has failed.
Tyler Gunn9d127732018-03-02 15:45:51 -08001358 * <p>
1359 * For a full discussion of the handover process and the APIs involved, see
1360 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1361 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001362 * @param call The call which had initiated handover.
Tyler Gunn9d127732018-03-02 15:45:51 -08001363 * @param failureReason Error reason for failure.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001364 */
1365 public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
Hall Liu95d55872017-01-25 17:12:49 -08001366 }
1367
1368 /**
1369 * A class that holds the state that describes the state of the RTT channel to the remote
1370 * party, if it is active.
1371 */
1372 public static final class RttCall {
Hall Liu07094df2017-02-28 15:17:44 -08001373 /** @hide */
Hall Liu95d55872017-01-25 17:12:49 -08001374 @Retention(RetentionPolicy.SOURCE)
1375 @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
1376 public @interface RttAudioMode {}
1377
1378 /**
1379 * For metrics use. Default value in the proto.
1380 * @hide
1381 */
1382 public static final int RTT_MODE_INVALID = 0;
1383
1384 /**
1385 * Indicates that there should be a bidirectional audio stream between the two parties
1386 * on the call.
1387 */
1388 public static final int RTT_MODE_FULL = 1;
1389
1390 /**
1391 * Indicates that the local user should be able to hear the audio stream from the remote
1392 * user, but not vice versa. Equivalent to muting the microphone.
1393 */
1394 public static final int RTT_MODE_HCO = 2;
1395
1396 /**
1397 * Indicates that the remote user should be able to hear the audio stream from the local
1398 * user, but not vice versa. Equivalent to setting the volume to zero.
1399 */
1400 public static final int RTT_MODE_VCO = 3;
1401
1402 private static final int READ_BUFFER_SIZE = 1000;
1403
1404 private InputStreamReader mReceiveStream;
1405 private OutputStreamWriter mTransmitStream;
1406 private int mRttMode;
1407 private final InCallAdapter mInCallAdapter;
Hall Liu57006aa2017-02-06 10:49:48 -08001408 private final String mTelecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001409 private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
1410
1411 /**
1412 * @hide
1413 */
Hall Liu57006aa2017-02-06 10:49:48 -08001414 public RttCall(String telecomCallId, InputStreamReader receiveStream,
1415 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
1416 mTelecomCallId = telecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001417 mReceiveStream = receiveStream;
1418 mTransmitStream = transmitStream;
1419 mRttMode = mode;
1420 mInCallAdapter = inCallAdapter;
1421 }
1422
1423 /**
1424 * Returns the current RTT audio mode.
1425 * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
1426 * {@link #RTT_MODE_HCO}.
1427 */
1428 public int getRttAudioMode() {
1429 return mRttMode;
1430 }
1431
1432 /**
1433 * Sets the RTT audio mode. The requested mode change will be communicated through
1434 * {@link Callback#onRttModeChanged(Call, int)}.
1435 * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
1436 * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
1437 */
1438 public void setRttMode(@RttAudioMode int mode) {
Hall Liu57006aa2017-02-06 10:49:48 -08001439 mInCallAdapter.setRttMode(mTelecomCallId, mode);
Hall Liu95d55872017-01-25 17:12:49 -08001440 }
1441
1442 /**
1443 * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
1444 * RTT transmits text in real-time, this method should be called once for each character
1445 * the user enters into the device.
1446 *
1447 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1448 * lead to interleaved text.
1449 * @param input The message to send to the remote user.
1450 */
1451 public void write(String input) throws IOException {
1452 mTransmitStream.write(input);
1453 mTransmitStream.flush();
1454 }
1455
1456 /**
1457 * Reads a string from the remote user, blocking if there is no data available. Returns
1458 * {@code null} if the RTT conversation has been terminated and there is no further data
1459 * to read.
1460 *
1461 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1462 * lead to interleaved text.
1463 * @return A string containing text sent by the remote user, or {@code null} if the
1464 * conversation has been terminated or if there was an error while reading.
1465 */
Hall Liub1c8a772017-07-17 17:04:41 -07001466 public String read() {
1467 try {
1468 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1469 if (numRead < 0) {
1470 return null;
1471 }
1472 return new String(mReadBuffer, 0, numRead);
1473 } catch (IOException e) {
1474 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
Jeff Sharkey90396362017-06-12 16:26:53 -06001475 return null;
Hall Liuffa4a812017-03-02 16:11:00 -08001476 }
Hall Liuffa4a812017-03-02 16:11:00 -08001477 }
1478
1479 /**
1480 * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
1481 * be read.
1482 * @return A string containing text entered by the user, or {@code null} if the user has
1483 * not entered any new text yet.
1484 */
1485 public String readImmediately() throws IOException {
1486 if (mReceiveStream.ready()) {
Hall Liub1c8a772017-07-17 17:04:41 -07001487 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1488 if (numRead < 0) {
1489 return null;
1490 }
1491 return new String(mReadBuffer, 0, numRead);
Hall Liuffa4a812017-03-02 16:11:00 -08001492 } else {
Hall Liu95d55872017-01-25 17:12:49 -08001493 return null;
1494 }
1495 }
Hall Liue9041242018-02-09 16:40:03 -08001496
1497 /**
1498 * Closes the underlying file descriptors
1499 * @hide
1500 */
1501 public void close() {
1502 try {
1503 mReceiveStream.close();
1504 } catch (IOException e) {
1505 // ignore
1506 }
1507 try {
1508 mTransmitStream.close();
1509 } catch (IOException e) {
1510 // ignore
1511 }
1512 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001513 }
1514
Andrew Leeda80c872015-04-15 14:09:50 -07001515 /**
1516 * @deprecated Use {@code Call.Callback} instead.
1517 * @hide
1518 */
1519 @Deprecated
1520 @SystemApi
1521 public static abstract class Listener extends Callback { }
1522
Ihab Awade63fadb2014-07-09 21:52:04 -07001523 private final Phone mPhone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001524 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001525 private final InCallAdapter mInCallAdapter;
Santos Cordon823fd3c2014-08-07 18:35:18 -07001526 private final List<String> mChildrenIds = new ArrayList<>();
Ihab Awade63fadb2014-07-09 21:52:04 -07001527 private final List<Call> mChildren = new ArrayList<>();
1528 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Andrew Lee011728f2015-04-23 15:47:06 -07001529 private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001530 private final List<Call> mConferenceableCalls = new ArrayList<>();
1531 private final List<Call> mUnmodifiableConferenceableCalls =
1532 Collections.unmodifiableList(mConferenceableCalls);
1533
Santos Cordon823fd3c2014-08-07 18:35:18 -07001534 private boolean mChildrenCached;
1535 private String mParentId = null;
Hall Liuef98bf82020-01-09 15:22:44 -08001536 private String mActiveGenericConferenceChild = null;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001537 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -07001538 private List<String> mCannedTextResponses = null;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001539 private String mCallingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001540 private int mTargetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07001541 private String mRemainingPostDialSequence;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001542 private VideoCallImpl mVideoCallImpl;
Hall Liu95d55872017-01-25 17:12:49 -08001543 private RttCall mRttCall;
Ihab Awade63fadb2014-07-09 21:52:04 -07001544 private Details mDetails;
Tyler Gunndee56a82016-03-23 16:06:34 -07001545 private Bundle mExtras;
Ihab Awade63fadb2014-07-09 21:52:04 -07001546
1547 /**
1548 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
1549 *
1550 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
1551 * remaining or this {@code Call} is not in a post-dial state.
1552 */
1553 public String getRemainingPostDialSequence() {
1554 return mRemainingPostDialSequence;
1555 }
1556
1557 /**
1558 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001559 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -07001560 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001561 public void answer(@VideoProfile.VideoState int videoState) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001562 mInCallAdapter.answerCall(mTelecomCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -07001563 }
1564
1565 /**
Pooja Jaind34698d2017-12-28 14:15:31 +05301566 * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
1567 *
1568 * @param address The address to which the call will be deflected.
1569 */
1570 public void deflect(Uri address) {
1571 mInCallAdapter.deflectCall(mTelecomCallId, address);
1572 }
1573
1574 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001575 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
1576 *
1577 * @param rejectWithMessage Whether to reject with a text message.
1578 * @param textMessage An optional text message with which to respond.
1579 */
1580 public void reject(boolean rejectWithMessage, String textMessage) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001581 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
Ihab Awade63fadb2014-07-09 21:52:04 -07001582 }
1583
1584 /**
Tyler Gunnfacfdee2020-01-23 13:10:37 -08001585 * Instructs the {@link ConnectionService} providing this {@link #STATE_RINGING} call that the
1586 * user has chosen to reject the call and has indicated a reason why the call is being rejected.
1587 *
1588 * @param rejectReason the reason the call is being rejected.
1589 */
1590 public void reject(@RejectReason int rejectReason) {
1591 mInCallAdapter.rejectCall(mTelecomCallId, rejectReason);
1592 }
1593
1594 /**
Ravi Palurif4b38e72020-02-05 12:35:41 +05301595 * Instructs this {@code Call} to be transferred to another number.
1596 *
1597 * @param targetNumber The address to which the call will be transferred.
1598 * @param isConfirmationRequired if {@code true} it will initiate ASSURED transfer,
1599 * if {@code false}, it will initiate BLIND transfer.
1600 *
1601 * @hide
1602 */
1603 public void transfer(@NonNull Uri targetNumber, boolean isConfirmationRequired) {
1604 mInCallAdapter.transferCall(mTelecomCallId, targetNumber, isConfirmationRequired);
1605 }
1606
1607 /**
1608 * Instructs this {@code Call} to be transferred to another ongoing call.
1609 * This will initiate CONSULTATIVE transfer.
1610 * @param toCall The other ongoing {@code Call} to which this call will be transferred.
1611 *
1612 * @hide
1613 */
1614 public void transfer(@NonNull android.telecom.Call toCall) {
1615 mInCallAdapter.transferCall(mTelecomCallId, toCall.mTelecomCallId);
1616 }
1617
1618 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001619 * Instructs this {@code Call} to disconnect.
1620 */
1621 public void disconnect() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001622 mInCallAdapter.disconnectCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001623 }
1624
1625 /**
1626 * Instructs this {@code Call} to go on hold.
1627 */
1628 public void hold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001629 mInCallAdapter.holdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001630 }
1631
1632 /**
1633 * Instructs this {@link #STATE_HOLDING} call to release from hold.
1634 */
1635 public void unhold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001636 mInCallAdapter.unholdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001637 }
1638
1639 /**
Hall Liu6dfa2492019-10-01 17:20:39 -07001640 * Instructs Telecom to put the call into the background audio processing state.
1641 *
1642 * This method can be called either when the call is in {@link #STATE_RINGING} or
1643 * {@link #STATE_ACTIVE}. After Telecom acknowledges the request by setting the call's state to
1644 * {@link #STATE_AUDIO_PROCESSING}, your app may setup the audio paths with the audio stack in
1645 * order to capture and play audio on the call stream.
1646 *
1647 * This method can only be called by the default dialer app.
1648 * @hide
1649 */
1650 @SystemApi
1651 @TestApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001652 public void enterBackgroundAudioProcessing() {
1653 if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
1654 throw new IllegalStateException("Call must be active or ringing");
1655 }
1656 mInCallAdapter.enterBackgroundAudioProcessing(mTelecomCallId);
1657 }
1658
1659 /**
1660 * Instructs Telecom to come out of the background audio processing state requested by
1661 * {@link #enterBackgroundAudioProcessing()} or from the call screening service.
1662 *
1663 * This method can only be called when the call is in {@link #STATE_AUDIO_PROCESSING}.
1664 *
1665 * @param shouldRing If true, Telecom will put the call into the
1666 * {@link #STATE_SIMULATED_RINGING} state and notify other apps that there is
1667 * a ringing call. Otherwise, the call will go into {@link #STATE_ACTIVE}
1668 * immediately.
1669 * @hide
1670 */
1671 @SystemApi
1672 @TestApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001673 public void exitBackgroundAudioProcessing(boolean shouldRing) {
1674 if (mState != STATE_AUDIO_PROCESSING) {
1675 throw new IllegalStateException("Call must in the audio processing state");
1676 }
1677 mInCallAdapter.exitBackgroundAudioProcessing(mTelecomCallId, shouldRing);
1678 }
1679
1680 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001681 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
1682 *
1683 * Any other currently playing DTMF tone in the specified call is immediately stopped.
1684 *
1685 * @param digit A character representing the DTMF digit for which to play the tone. This
1686 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
1687 */
1688 public void playDtmfTone(char digit) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001689 mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
Ihab Awade63fadb2014-07-09 21:52:04 -07001690 }
1691
1692 /**
1693 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
1694 * currently playing.
1695 *
1696 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
1697 * currently playing, this method will do nothing.
1698 */
1699 public void stopDtmfTone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001700 mInCallAdapter.stopDtmfTone(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001701 }
1702
1703 /**
1704 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
1705 *
1706 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
1707 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -07001708 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001709 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -07001710 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
1711 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001712 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
Andrew Leeda80c872015-04-15 14:09:50 -07001713 * {@code Call} will pause playing the tones and notify callbacks via
1714 * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
Ihab Awade63fadb2014-07-09 21:52:04 -07001715 * should display to the user an indication of this state and an affordance to continue
1716 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
1717 * app should invoke the {@link #postDialContinue(boolean)} method.
1718 *
1719 * @param proceed Whether or not to continue with the post-dial sequence.
1720 */
1721 public void postDialContinue(boolean proceed) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001722 mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
Ihab Awade63fadb2014-07-09 21:52:04 -07001723 }
1724
1725 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -07001726 * Notifies this {@code Call} that an account has been selected and to proceed with placing
Nancy Chen36c62f32014-10-21 18:36:39 -07001727 * an outgoing call. Optionally sets this account as the default account.
Nancy Chen5da0fd52014-07-08 14:16:17 -07001728 */
Nancy Chen36c62f32014-10-21 18:36:39 -07001729 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
1730 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
Nancy Chen5da0fd52014-07-08 14:16:17 -07001731
1732 }
1733
1734 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001735 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001736 *
1737 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -07001738 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001739 public void conference(Call callToConferenceWith) {
1740 if (callToConferenceWith != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001741 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001742 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001743 }
1744
1745 /**
1746 * Instructs this {@code Call} to split from any conference call with which it may be
1747 * connected.
1748 */
1749 public void splitFromConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001750 mInCallAdapter.splitFromConference(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001751 }
1752
1753 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001754 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001755 */
1756 public void mergeConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001757 mInCallAdapter.mergeConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001758 }
1759
1760 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001761 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001762 */
1763 public void swapConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001764 mInCallAdapter.swapConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001765 }
1766
1767 /**
Ravi Paluri404babb2020-01-23 19:02:44 +05301768 * Pulls participants to existing call by forming a conference call.
1769 * See {@link Details#CAPABILITY_ADD_PARTICIPANT}.
1770 *
1771 * @param participants participants to be pulled to existing call.
1772 */
1773 public void addConferenceParticipants(@NonNull List<Uri> participants) {
1774 mInCallAdapter.addConferenceParticipants(mTelecomCallId, participants);
1775 }
1776
1777 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001778 * Initiates a request to the {@link ConnectionService} to pull an external call to the local
1779 * device.
1780 * <p>
1781 * Calls to this method are ignored if the call does not have the
1782 * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
1783 * <p>
1784 * An {@link InCallService} will only see calls which support this method if it has the
1785 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
1786 * in its manifest.
1787 */
1788 public void pullExternalCall() {
1789 // If this isn't an external call, ignore the request.
1790 if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
1791 return;
1792 }
1793
1794 mInCallAdapter.pullExternalCall(mTelecomCallId);
1795 }
1796
1797 /**
1798 * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
1799 * the {@link ConnectionService}.
1800 * <p>
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001801 * Call events are used to communicate point in time information from an {@link InCallService}
1802 * to a {@link ConnectionService}. A {@link ConnectionService} implementation could define
1803 * events which enable the {@link InCallService}, for example, toggle a unique feature of the
1804 * {@link ConnectionService}.
1805 * <p>
1806 * A {@link ConnectionService} can communicate to the {@link InCallService} using
1807 * {@link Connection#sendConnectionEvent(String, Bundle)}.
1808 * <p>
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001809 * Events are exposed to {@link ConnectionService} implementations via
1810 * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
1811 * <p>
1812 * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001813 * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
1814 * ignore some events altogether.
1815 * <p>
1816 * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
1817 * conflicts between {@link InCallService} implementations. Further, {@link InCallService}
1818 * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
1819 * they define their own event types in this namespace. When defining a custom event type,
1820 * ensure the contents of the extras {@link Bundle} is clearly defined. Extra keys for this
1821 * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
1822 * <p>
1823 * When defining events and the associated extras, it is important to keep their behavior
1824 * consistent when the associated {@link InCallService} is updated. Support for deprecated
1825 * events/extras should me maintained to ensure backwards compatibility with older
1826 * {@link ConnectionService} implementations which were built to support the older behavior.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001827 *
1828 * @param event The connection event.
1829 * @param extras Bundle containing extra information associated with the event.
1830 */
1831 public void sendCallEvent(String event, Bundle extras) {
Sanket Padawef6a9e5b2018-01-05 14:26:16 -08001832 mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001833 }
1834
1835 /**
Hall Liu95d55872017-01-25 17:12:49 -08001836 * Sends an RTT upgrade request to the remote end of the connection. Success is not
1837 * guaranteed, and notification of success will be via the
1838 * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1839 */
1840 public void sendRttRequest() {
Hall Liu57006aa2017-02-06 10:49:48 -08001841 mInCallAdapter.sendRttRequest(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001842 }
1843
1844 /**
1845 * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
1846 * callback.
1847 * The ID used here should be the same as the ID that was received via the callback.
1848 * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
1849 * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
1850 */
1851 public void respondToRttRequest(int id, boolean accept) {
Hall Liu57006aa2017-02-06 10:49:48 -08001852 mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
Hall Liu95d55872017-01-25 17:12:49 -08001853 }
1854
1855 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001856 * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
1857 * by {@code toHandle}. The videoState specified indicates the desired video state after the
1858 * handover.
1859 * <p>
Tyler Gunn9d127732018-03-02 15:45:51 -08001860 * A call handover is the process where an ongoing call is transferred from one app (i.e.
1861 * {@link ConnectionService} to another app. The user could, for example, choose to continue a
1862 * mobile network call in a video calling app. The mobile network call via the Telephony stack
1863 * is referred to as the source of the handover, and the video calling app is referred to as the
1864 * destination.
1865 * <p>
1866 * When considering a handover scenario the device this method is called on is considered the
1867 * <em>initiating</em> device (since the user initiates the handover from this device), and the
1868 * other device is considered the <em>receiving</em> device.
1869 * <p>
1870 * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
1871 * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
1872 * and invoke
1873 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1874 * ConnectionRequest)} to inform the destination app that a request has been made to handover a
1875 * call to it. The app returns an instance of {@link Connection} to represent the handover call
1876 * At this point the app should display UI to indicate to the user that a call
1877 * handover is in process.
1878 * <p>
1879 * The destination app is responsible for communicating the handover request from the
1880 * <em>initiating</em> device to the <em>receiving</em> device.
1881 * <p>
1882 * When the app on the <em>receiving</em> device receives the handover request, it calls
1883 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
1884 * process from the <em>initiating</em> device to the <em>receiving</em> device. At this point
1885 * the destination app on the <em>receiving</em> device should show UI to allow the user to
1886 * choose whether they want to continue their call in the destination app.
1887 * <p>
1888 * When the destination app on the <em>receiving</em> device calls
1889 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
1890 * {@link ConnectionService} and call
1891 * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
1892 * ConnectionRequest)} to inform it of the handover request. The app returns an instance of
1893 * {@link Connection} to represent the handover call.
1894 * <p>
1895 * If the user of the <em>receiving</em> device accepts the handover, the app calls
1896 * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
1897 * original call. If the user rejects the handover, the app calls
1898 * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
1899 * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
1900 * <p>
1901 * Telecom will only allow handovers from {@link PhoneAccount}s which declare
1902 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}. Similarly, the {@link PhoneAccount}
1903 * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
1904 * <p>
1905 * Errors in the handover process are reported to the {@link InCallService} via
1906 * {@link Callback#onHandoverFailed(Call, int)}. Errors in the handover process are reported to
1907 * the involved {@link ConnectionService}s via
1908 * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001909 *
1910 * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
1911 * this call to.
Tyler Gunn9d127732018-03-02 15:45:51 -08001912 * @param videoState Indicates the video state desired after the handover (see the
1913 * {@code STATE_*} constants defined in {@link VideoProfile}).
Sanket Padawea8eddd42017-11-03 11:07:35 -07001914 * @param extras Bundle containing extra information to be passed to the
1915 * {@link ConnectionService}
1916 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001917 public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
1918 Bundle extras) {
Sanket Padawea8eddd42017-11-03 11:07:35 -07001919 mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
1920 }
1921
1922 /**
Hall Liu95d55872017-01-25 17:12:49 -08001923 * Terminate the RTT session on this call. The resulting state change will be notified via
1924 * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1925 */
1926 public void stopRtt() {
Hall Liu57006aa2017-02-06 10:49:48 -08001927 mInCallAdapter.stopRtt(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001928 }
1929
1930 /**
Tyler Gunndee56a82016-03-23 16:06:34 -07001931 * Adds some extras to this {@link Call}. Existing keys are replaced and new ones are
1932 * added.
1933 * <p>
1934 * No assumptions should be made as to how an In-Call UI or service will handle these
1935 * extras. Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
1936 *
1937 * @param extras The extras to add.
1938 */
1939 public final void putExtras(Bundle extras) {
1940 if (extras == null) {
1941 return;
1942 }
1943
1944 if (mExtras == null) {
1945 mExtras = new Bundle();
1946 }
1947 mExtras.putAll(extras);
1948 mInCallAdapter.putExtras(mTelecomCallId, extras);
1949 }
1950
1951 /**
1952 * Adds a boolean extra to this {@link Call}.
1953 *
1954 * @param key The extra key.
1955 * @param value The value.
1956 * @hide
1957 */
1958 public final void putExtra(String key, boolean value) {
1959 if (mExtras == null) {
1960 mExtras = new Bundle();
1961 }
1962 mExtras.putBoolean(key, value);
1963 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1964 }
1965
1966 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001967 * Adds an integer extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001968 *
1969 * @param key The extra key.
1970 * @param value The value.
1971 * @hide
1972 */
1973 public final void putExtra(String key, int value) {
1974 if (mExtras == null) {
1975 mExtras = new Bundle();
1976 }
1977 mExtras.putInt(key, value);
1978 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1979 }
1980
1981 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001982 * Adds a string extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001983 *
1984 * @param key The extra key.
1985 * @param value The value.
1986 * @hide
1987 */
1988 public final void putExtra(String key, String value) {
1989 if (mExtras == null) {
1990 mExtras = new Bundle();
1991 }
1992 mExtras.putString(key, value);
1993 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1994 }
1995
1996 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001997 * Removes extras from this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001998 *
1999 * @param keys The keys of the extras to remove.
2000 */
2001 public final void removeExtras(List<String> keys) {
2002 if (mExtras != null) {
2003 for (String key : keys) {
2004 mExtras.remove(key);
2005 }
2006 if (mExtras.size() == 0) {
2007 mExtras = null;
2008 }
2009 }
2010 mInCallAdapter.removeExtras(mTelecomCallId, keys);
2011 }
2012
2013 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002014 * Removes extras from this {@link Call}.
2015 *
2016 * @param keys The keys of the extras to remove.
2017 */
2018 public final void removeExtras(String ... keys) {
2019 removeExtras(Arrays.asList(keys));
2020 }
2021
2022 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002023 * Obtains the parent of this {@code Call} in a conference, if any.
2024 *
2025 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
2026 * child of any conference {@code Call}s.
2027 */
2028 public Call getParent() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002029 if (mParentId != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002030 return mPhone.internalGetCallByTelecomId(mParentId);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002031 }
2032 return null;
Ihab Awade63fadb2014-07-09 21:52:04 -07002033 }
2034
2035 /**
2036 * Obtains the children of this conference {@code Call}, if any.
2037 *
2038 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
2039 * {@code List} otherwise.
2040 */
2041 public List<Call> getChildren() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002042 if (!mChildrenCached) {
2043 mChildrenCached = true;
2044 mChildren.clear();
2045
2046 for(String id : mChildrenIds) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002047 Call call = mPhone.internalGetCallByTelecomId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002048 if (call == null) {
2049 // At least one child was still not found, so do not save true for "cached"
2050 mChildrenCached = false;
2051 } else {
2052 mChildren.add(call);
2053 }
2054 }
2055 }
2056
Ihab Awade63fadb2014-07-09 21:52:04 -07002057 return mUnmodifiableChildren;
2058 }
2059
2060 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002061 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
2062 *
2063 * @return The list of conferenceable {@code Call}s.
2064 */
2065 public List<Call> getConferenceableCalls() {
2066 return mUnmodifiableConferenceableCalls;
2067 }
2068
2069 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002070 * Obtains the state of this {@code Call}.
2071 *
2072 * @return A state value, chosen from the {@code STATE_*} constants.
2073 */
2074 public int getState() {
2075 return mState;
2076 }
2077
2078 /**
Hall Liuef98bf82020-01-09 15:22:44 -08002079 * Returns the child {@link Call} in a generic conference that is currently active.
Hall Liu135e53aa2020-02-27 18:34:11 -08002080 *
2081 * A "generic conference" is the mechanism used to support two simultaneous calls on a device
2082 * in CDMA networks. It is effectively equivalent to having one call active and one call on hold
2083 * in GSM or IMS calls. This method returns the currently active call.
2084 *
2085 * In a generic conference, the network exposes the conference to us as a single call, and we
2086 * switch between talking to the two participants using a CDMA flash command. Since the network
2087 * exposes no additional information about the call, the only way we know which caller we're
2088 * currently talking to is by keeping track of the flash commands that we've sent to the
2089 * network.
2090 *
Hall Liuef98bf82020-01-09 15:22:44 -08002091 * For calls that are not generic conferences, or when the generic conference has more than
2092 * 2 children, returns {@code null}.
2093 * @see Details#PROPERTY_GENERIC_CONFERENCE
2094 * @return The active child call.
2095 */
2096 public @Nullable Call getGenericConferenceActiveChildCall() {
2097 if (mActiveGenericConferenceChild != null) {
2098 return mPhone.internalGetCallByTelecomId(mActiveGenericConferenceChild);
2099 }
2100 return null;
2101 }
2102
2103 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002104 * Obtains a list of canned, pre-configured message responses to present to the user as
2105 * ways of rejecting this {@code Call} using via a text message.
2106 *
2107 * @see #reject(boolean, String)
2108 *
2109 * @return A list of canned text message responses.
2110 */
2111 public List<String> getCannedTextResponses() {
2112 return mCannedTextResponses;
2113 }
2114
2115 /**
2116 * Obtains an object that can be used to display video from this {@code Call}.
2117 *
Andrew Lee50aca232014-07-22 16:41:54 -07002118 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -07002119 */
Andrew Lee50aca232014-07-22 16:41:54 -07002120 public InCallService.VideoCall getVideoCall() {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002121 return mVideoCallImpl;
Ihab Awade63fadb2014-07-09 21:52:04 -07002122 }
2123
2124 /**
2125 * Obtains an object containing call details.
2126 *
2127 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
2128 * result may be {@code null}.
2129 */
2130 public Details getDetails() {
2131 return mDetails;
2132 }
2133
2134 /**
Hall Liu95d55872017-01-25 17:12:49 -08002135 * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
2136 * receive RTT text data, as well as to change the RTT mode.
2137 * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
2138 */
2139 public @Nullable RttCall getRttCall() {
2140 return mRttCall;
2141 }
2142
2143 /**
2144 * Returns whether this call has an active RTT connection.
2145 * @return true if there is a connection, false otherwise.
2146 */
2147 public boolean isRttActive() {
Hall Liue9041242018-02-09 16:40:03 -08002148 return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
Hall Liu95d55872017-01-25 17:12:49 -08002149 }
2150
2151 /**
Andrew Leeda80c872015-04-15 14:09:50 -07002152 * Registers a callback to this {@code Call}.
2153 *
2154 * @param callback A {@code Callback}.
2155 */
2156 public void registerCallback(Callback callback) {
Andrew Lee011728f2015-04-23 15:47:06 -07002157 registerCallback(callback, new Handler());
2158 }
2159
2160 /**
2161 * Registers a callback to this {@code Call}.
2162 *
2163 * @param callback A {@code Callback}.
2164 * @param handler A handler which command and status changes will be delivered to.
2165 */
2166 public void registerCallback(Callback callback, Handler handler) {
2167 unregisterCallback(callback);
Roshan Pius1ca62072015-07-07 17:34:51 -07002168 // Don't allow new callback registration if the call is already being destroyed.
2169 if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002170 mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
2171 }
Andrew Leeda80c872015-04-15 14:09:50 -07002172 }
2173
2174 /**
2175 * Unregisters a callback from this {@code Call}.
2176 *
2177 * @param callback A {@code Callback}.
2178 */
2179 public void unregisterCallback(Callback callback) {
Roshan Pius1ca62072015-07-07 17:34:51 -07002180 // Don't allow callback deregistration if the call is already being destroyed.
2181 if (callback != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002182 for (CallbackRecord<Callback> record : mCallbackRecords) {
2183 if (record.getCallback() == callback) {
2184 mCallbackRecords.remove(record);
2185 break;
2186 }
2187 }
Andrew Leeda80c872015-04-15 14:09:50 -07002188 }
2189 }
2190
Santos Cordon3c20d632016-02-25 16:12:35 -08002191 @Override
2192 public String toString() {
2193 return new StringBuilder().
2194 append("Call [id: ").
2195 append(mTelecomCallId).
2196 append(", state: ").
2197 append(stateToString(mState)).
2198 append(", details: ").
2199 append(mDetails).
2200 append("]").toString();
2201 }
2202
2203 /**
2204 * @param state An integer value of a {@code STATE_*} constant.
2205 * @return A string representation of the value.
2206 */
2207 private static String stateToString(int state) {
2208 switch (state) {
2209 case STATE_NEW:
2210 return "NEW";
2211 case STATE_RINGING:
2212 return "RINGING";
2213 case STATE_DIALING:
2214 return "DIALING";
2215 case STATE_ACTIVE:
2216 return "ACTIVE";
2217 case STATE_HOLDING:
2218 return "HOLDING";
2219 case STATE_DISCONNECTED:
2220 return "DISCONNECTED";
2221 case STATE_CONNECTING:
2222 return "CONNECTING";
2223 case STATE_DISCONNECTING:
2224 return "DISCONNECTING";
2225 case STATE_SELECT_PHONE_ACCOUNT:
2226 return "SELECT_PHONE_ACCOUNT";
Hall Liu4e35b642019-10-14 17:50:45 -07002227 case STATE_SIMULATED_RINGING:
2228 return "SIMULATED_RINGING";
2229 case STATE_AUDIO_PROCESSING:
2230 return "AUDIO_PROCESSING";
Santos Cordon3c20d632016-02-25 16:12:35 -08002231 default:
2232 Log.w(Call.class, "Unknown state %d", state);
2233 return "UNKNOWN";
2234 }
2235 }
2236
Andrew Leeda80c872015-04-15 14:09:50 -07002237 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002238 * Adds a listener to this {@code Call}.
2239 *
2240 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002241 * @deprecated Use {@link #registerCallback} instead.
2242 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002243 */
Andrew Leeda80c872015-04-15 14:09:50 -07002244 @Deprecated
2245 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002246 public void addListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002247 registerCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002248 }
2249
2250 /**
2251 * Removes a listener from this {@code Call}.
2252 *
2253 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002254 * @deprecated Use {@link #unregisterCallback} instead.
2255 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002256 */
Andrew Leeda80c872015-04-15 14:09:50 -07002257 @Deprecated
2258 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002259 public void removeListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002260 unregisterCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002261 }
2262
2263 /** {@hide} */
Tyler Gunn159f35c2017-03-02 09:28:37 -08002264 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
2265 int targetSdkVersion) {
Ihab Awade63fadb2014-07-09 21:52:04 -07002266 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002267 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002268 mInCallAdapter = inCallAdapter;
2269 mState = STATE_NEW;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002270 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002271 mTargetSdkVersion = targetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07002272 }
2273
2274 /** {@hide} */
Tyler Gunnb88b3112016-11-09 10:19:23 -08002275 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
Tyler Gunn159f35c2017-03-02 09:28:37 -08002276 String callingPackage, int targetSdkVersion) {
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002277 mPhone = phone;
2278 mTelecomCallId = telecomCallId;
2279 mInCallAdapter = inCallAdapter;
2280 mState = state;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002281 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002282 mTargetSdkVersion = targetSdkVersion;
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002283 }
2284
2285 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002286 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002287 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002288 }
2289
2290 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002291 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Tyler Gunnb88b3112016-11-09 10:19:23 -08002292
Ihab Awade63fadb2014-07-09 21:52:04 -07002293 // First, we update the internal state as far as possible before firing any updates.
Sailesh Nepal1bef3392016-01-24 18:21:53 -08002294 Details details = Details.createFromParcelableCall(parcelableCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07002295 boolean detailsChanged = !Objects.equals(mDetails, details);
2296 if (detailsChanged) {
2297 mDetails = details;
2298 }
2299
2300 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -07002301 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
2302 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
2303 mCannedTextResponses =
2304 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Yorke Leee886f632015-08-04 13:43:31 -07002305 cannedTextResponsesChanged = true;
Ihab Awade63fadb2014-07-09 21:52:04 -07002306 }
2307
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002308 IVideoProvider previousVideoProvider = mVideoCallImpl == null ? null :
2309 mVideoCallImpl.getVideoProvider();
2310 IVideoProvider newVideoProvider = parcelableCall.getVideoProvider();
2311
2312 // parcelableCall.isVideoCallProviderChanged is only true when we have a video provider
2313 // specified; so we should check if the actual IVideoProvider changes as well.
2314 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged()
2315 && !Objects.equals(previousVideoProvider, newVideoProvider);
Andrew Lee50aca232014-07-22 16:41:54 -07002316 if (videoCallChanged) {
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002317 if (mVideoCallImpl != null) {
2318 mVideoCallImpl.destroy();
2319 }
2320 mVideoCallImpl = parcelableCall.isVideoCallProviderChanged() ?
2321 parcelableCall.getVideoCallImpl(mCallingPackage, mTargetSdkVersion) : null;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002322 }
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002323
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002324 if (mVideoCallImpl != null) {
2325 mVideoCallImpl.setVideoState(getDetails().getVideoState());
Ihab Awade63fadb2014-07-09 21:52:04 -07002326 }
2327
Santos Cordone3c507b2015-04-23 14:44:19 -07002328 int state = parcelableCall.getState();
Hall Liu31de23d2019-10-11 15:38:29 -07002329 if (mTargetSdkVersion < Phone.SDK_VERSION_R && state == Call.STATE_SIMULATED_RINGING) {
2330 state = Call.STATE_RINGING;
2331 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002332 boolean stateChanged = mState != state;
2333 if (stateChanged) {
2334 mState = state;
2335 }
2336
Santos Cordon823fd3c2014-08-07 18:35:18 -07002337 String parentId = parcelableCall.getParentCallId();
2338 boolean parentChanged = !Objects.equals(mParentId, parentId);
2339 if (parentChanged) {
2340 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002341 }
2342
Santos Cordon823fd3c2014-08-07 18:35:18 -07002343 List<String> childCallIds = parcelableCall.getChildCallIds();
2344 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
2345 if (childrenChanged) {
2346 mChildrenIds.clear();
2347 mChildrenIds.addAll(parcelableCall.getChildCallIds());
2348 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -07002349 }
2350
Hall Liuef98bf82020-01-09 15:22:44 -08002351 String activeChildCallId = parcelableCall.getActiveChildCallId();
2352 boolean activeChildChanged = !Objects.equals(activeChildCallId,
2353 mActiveGenericConferenceChild);
2354 if (activeChildChanged) {
2355 mActiveGenericConferenceChild = activeChildCallId;
2356 }
2357
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002358 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
2359 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
2360 for (String otherId : conferenceableCallIds) {
2361 if (callIdMap.containsKey(otherId)) {
2362 conferenceableCalls.add(callIdMap.get(otherId));
2363 }
2364 }
2365
2366 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
2367 mConferenceableCalls.clear();
2368 mConferenceableCalls.addAll(conferenceableCalls);
2369 fireConferenceableCallsChanged();
2370 }
2371
Hall Liu95d55872017-01-25 17:12:49 -08002372 boolean isRttChanged = false;
2373 boolean rttModeChanged = false;
Hall Liue9041242018-02-09 16:40:03 -08002374 if (parcelableCall.getIsRttCallChanged()
2375 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
Hall Liu95d55872017-01-25 17:12:49 -08002376 ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
2377 InputStreamReader receiveStream = new InputStreamReader(
2378 new ParcelFileDescriptor.AutoCloseInputStream(
2379 parcelableRttCall.getReceiveStream()),
2380 StandardCharsets.UTF_8);
2381 OutputStreamWriter transmitStream = new OutputStreamWriter(
2382 new ParcelFileDescriptor.AutoCloseOutputStream(
2383 parcelableRttCall.getTransmitStream()),
2384 StandardCharsets.UTF_8);
Hall Liu57006aa2017-02-06 10:49:48 -08002385 RttCall newRttCall = new Call.RttCall(mTelecomCallId,
Hall Liu95d55872017-01-25 17:12:49 -08002386 receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
2387 if (mRttCall == null) {
2388 isRttChanged = true;
2389 } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
2390 rttModeChanged = true;
2391 }
2392 mRttCall = newRttCall;
2393 } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
2394 && parcelableCall.getIsRttCallChanged()) {
2395 isRttChanged = true;
2396 mRttCall = null;
2397 }
2398
Ihab Awade63fadb2014-07-09 21:52:04 -07002399 // Now we fire updates, ensuring that any client who listens to any of these notifications
2400 // gets the most up-to-date state.
2401
2402 if (stateChanged) {
2403 fireStateChanged(mState);
2404 }
2405 if (detailsChanged) {
2406 fireDetailsChanged(mDetails);
2407 }
2408 if (cannedTextResponsesChanged) {
2409 fireCannedTextResponsesLoaded(mCannedTextResponses);
2410 }
Andrew Lee50aca232014-07-22 16:41:54 -07002411 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002412 fireVideoCallChanged(mVideoCallImpl);
Ihab Awade63fadb2014-07-09 21:52:04 -07002413 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002414 if (parentChanged) {
2415 fireParentChanged(getParent());
2416 }
Hall Liuef98bf82020-01-09 15:22:44 -08002417 if (childrenChanged || activeChildChanged) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002418 fireChildrenChanged(getChildren());
2419 }
Hall Liu95d55872017-01-25 17:12:49 -08002420 if (isRttChanged) {
2421 fireOnIsRttChanged(mRttCall != null, mRttCall);
2422 }
2423 if (rttModeChanged) {
2424 fireOnRttModeChanged(mRttCall.getRttAudioMode());
2425 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002426
2427 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
2428 // remove ourselves from the Phone. Note that we do this after completing all state updates
2429 // so a client can cleanly transition all their UI to the state appropriate for a
2430 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
2431 if (mState == STATE_DISCONNECTED) {
2432 fireCallDestroyed();
Ihab Awade63fadb2014-07-09 21:52:04 -07002433 }
2434 }
2435
2436 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002437 final void internalSetPostDialWait(String remaining) {
2438 mRemainingPostDialSequence = remaining;
2439 firePostDialWait(mRemainingPostDialSequence);
2440 }
2441
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07002442 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -07002443 final void internalSetDisconnected() {
2444 if (mState != Call.STATE_DISCONNECTED) {
2445 mState = Call.STATE_DISCONNECTED;
2446 fireStateChanged(mState);
2447 fireCallDestroyed();
Santos Cordonf30d7e92014-08-26 09:54:33 -07002448 }
2449 }
2450
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002451 /** {@hide} */
2452 final void internalOnConnectionEvent(String event, Bundle extras) {
2453 fireOnConnectionEvent(event, extras);
2454 }
2455
Hall Liu95d55872017-01-25 17:12:49 -08002456 /** {@hide} */
2457 final void internalOnRttUpgradeRequest(final int requestId) {
2458 for (CallbackRecord<Callback> record : mCallbackRecords) {
2459 final Call call = this;
2460 final Callback callback = record.getCallback();
2461 record.getHandler().post(() -> callback.onRttRequest(call, requestId));
2462 }
2463 }
2464
Hall Liu57006aa2017-02-06 10:49:48 -08002465 /** @hide */
2466 final void internalOnRttInitiationFailure(int reason) {
2467 for (CallbackRecord<Callback> record : mCallbackRecords) {
2468 final Call call = this;
2469 final Callback callback = record.getCallback();
2470 record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
2471 }
2472 }
2473
Sanket Padawe85291f62017-12-01 13:59:27 -08002474 /** {@hide} */
2475 final void internalOnHandoverFailed(int error) {
2476 for (CallbackRecord<Callback> record : mCallbackRecords) {
2477 final Call call = this;
2478 final Callback callback = record.getCallback();
2479 record.getHandler().post(() -> callback.onHandoverFailed(call, error));
2480 }
2481 }
2482
Tyler Gunn858bfaf2018-01-22 15:17:54 -08002483 /** {@hide} */
2484 final void internalOnHandoverComplete() {
2485 for (CallbackRecord<Callback> record : mCallbackRecords) {
2486 final Call call = this;
2487 final Callback callback = record.getCallback();
2488 record.getHandler().post(() -> callback.onHandoverComplete(call));
2489 }
2490 }
2491
Andrew Lee011728f2015-04-23 15:47:06 -07002492 private void fireStateChanged(final int newState) {
2493 for (CallbackRecord<Callback> record : mCallbackRecords) {
2494 final Call call = this;
2495 final Callback callback = record.getCallback();
2496 record.getHandler().post(new Runnable() {
2497 @Override
2498 public void run() {
2499 callback.onStateChanged(call, newState);
2500 }
2501 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002502 }
2503 }
2504
Andrew Lee011728f2015-04-23 15:47:06 -07002505 private void fireParentChanged(final Call newParent) {
2506 for (CallbackRecord<Callback> record : mCallbackRecords) {
2507 final Call call = this;
2508 final Callback callback = record.getCallback();
2509 record.getHandler().post(new Runnable() {
2510 @Override
2511 public void run() {
2512 callback.onParentChanged(call, newParent);
2513 }
2514 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002515 }
2516 }
2517
Andrew Lee011728f2015-04-23 15:47:06 -07002518 private void fireChildrenChanged(final List<Call> children) {
2519 for (CallbackRecord<Callback> record : mCallbackRecords) {
2520 final Call call = this;
2521 final Callback callback = record.getCallback();
2522 record.getHandler().post(new Runnable() {
2523 @Override
2524 public void run() {
2525 callback.onChildrenChanged(call, children);
2526 }
2527 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002528 }
2529 }
2530
Andrew Lee011728f2015-04-23 15:47:06 -07002531 private void fireDetailsChanged(final Details details) {
2532 for (CallbackRecord<Callback> record : mCallbackRecords) {
2533 final Call call = this;
2534 final Callback callback = record.getCallback();
2535 record.getHandler().post(new Runnable() {
2536 @Override
2537 public void run() {
2538 callback.onDetailsChanged(call, details);
2539 }
2540 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002541 }
2542 }
2543
Andrew Lee011728f2015-04-23 15:47:06 -07002544 private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
2545 for (CallbackRecord<Callback> record : mCallbackRecords) {
2546 final Call call = this;
2547 final Callback callback = record.getCallback();
2548 record.getHandler().post(new Runnable() {
2549 @Override
2550 public void run() {
2551 callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
2552 }
2553 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002554 }
2555 }
2556
Andrew Lee011728f2015-04-23 15:47:06 -07002557 private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
2558 for (CallbackRecord<Callback> record : mCallbackRecords) {
2559 final Call call = this;
2560 final Callback callback = record.getCallback();
2561 record.getHandler().post(new Runnable() {
2562 @Override
2563 public void run() {
2564 callback.onVideoCallChanged(call, videoCall);
2565 }
2566 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002567 }
2568 }
2569
Andrew Lee011728f2015-04-23 15:47:06 -07002570 private void firePostDialWait(final String remainingPostDialSequence) {
2571 for (CallbackRecord<Callback> record : mCallbackRecords) {
2572 final Call call = this;
2573 final Callback callback = record.getCallback();
2574 record.getHandler().post(new Runnable() {
2575 @Override
2576 public void run() {
2577 callback.onPostDialWait(call, remainingPostDialSequence);
2578 }
2579 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002580 }
2581 }
2582
2583 private void fireCallDestroyed() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002584 /**
2585 * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
2586 * onCallRemoved callback, we remove this call from the Phone's record
2587 * only once all of the registered onCallDestroyed callbacks are executed.
2588 * All the callbacks get removed from our records as a part of this operation
2589 * since onCallDestroyed is the final callback.
2590 */
2591 final Call call = this;
2592 if (mCallbackRecords.isEmpty()) {
2593 // No callbacks registered, remove the call from Phone's record.
2594 mPhone.internalRemoveCall(call);
2595 }
2596 for (final CallbackRecord<Callback> record : mCallbackRecords) {
Andrew Lee011728f2015-04-23 15:47:06 -07002597 final Callback callback = record.getCallback();
2598 record.getHandler().post(new Runnable() {
2599 @Override
2600 public void run() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002601 boolean isFinalRemoval = false;
2602 RuntimeException toThrow = null;
2603 try {
2604 callback.onCallDestroyed(call);
2605 } catch (RuntimeException e) {
2606 toThrow = e;
2607 }
2608 synchronized(Call.this) {
2609 mCallbackRecords.remove(record);
2610 if (mCallbackRecords.isEmpty()) {
2611 isFinalRemoval = true;
2612 }
2613 }
2614 if (isFinalRemoval) {
2615 mPhone.internalRemoveCall(call);
2616 }
2617 if (toThrow != null) {
2618 throw toThrow;
2619 }
Andrew Lee011728f2015-04-23 15:47:06 -07002620 }
2621 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002622 }
2623 }
2624
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002625 private void fireConferenceableCallsChanged() {
Andrew Lee011728f2015-04-23 15:47:06 -07002626 for (CallbackRecord<Callback> record : mCallbackRecords) {
2627 final Call call = this;
2628 final Callback callback = record.getCallback();
2629 record.getHandler().post(new Runnable() {
2630 @Override
2631 public void run() {
2632 callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
2633 }
2634 });
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002635 }
2636 }
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002637
2638 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002639 * Notifies listeners of an incoming connection event.
2640 * <p>
2641 * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
2642 *
2643 * @param event
2644 * @param extras
2645 */
2646 private void fireOnConnectionEvent(final String event, final Bundle extras) {
2647 for (CallbackRecord<Callback> record : mCallbackRecords) {
2648 final Call call = this;
2649 final Callback callback = record.getCallback();
2650 record.getHandler().post(new Runnable() {
2651 @Override
2652 public void run() {
2653 callback.onConnectionEvent(call, event, extras);
2654 }
2655 });
2656 }
2657 }
2658
2659 /**
Hall Liu95d55872017-01-25 17:12:49 -08002660 * Notifies listeners of an RTT on/off change
2661 *
2662 * @param enabled True if RTT is now enabled, false otherwise
2663 */
2664 private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
2665 for (CallbackRecord<Callback> record : mCallbackRecords) {
2666 final Call call = this;
2667 final Callback callback = record.getCallback();
2668 record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
2669 }
2670 }
2671
2672 /**
2673 * Notifies listeners of a RTT mode change
2674 *
2675 * @param mode The new RTT mode
2676 */
2677 private void fireOnRttModeChanged(final int mode) {
2678 for (CallbackRecord<Callback> record : mCallbackRecords) {
2679 final Call call = this;
2680 final Callback callback = record.getCallback();
2681 record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
2682 }
2683 }
2684
2685 /**
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002686 * Determines if two bundles are equal.
2687 *
2688 * @param bundle The original bundle.
2689 * @param newBundle The bundle to compare with.
2690 * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
2691 */
2692 private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
2693 if (bundle == null || newBundle == null) {
2694 return bundle == newBundle;
2695 }
2696
2697 if (bundle.size() != newBundle.size()) {
2698 return false;
2699 }
2700
2701 for(String key : bundle.keySet()) {
2702 if (key != null) {
2703 final Object value = bundle.get(key);
2704 final Object newValue = newBundle.get(key);
2705 if (!Objects.equals(value, newValue)) {
2706 return false;
2707 }
2708 }
2709 }
2710 return true;
2711 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002712}