blob: ead90bb4561f0abca82eae3077a5d62718ea0db9 [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
464 * {@link #addConferenceParticipants(List)}.
465 * @hide
466 */
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
601 * incoming and outgoing calls.
Tyler Gunna967af52020-02-10 15:19:07 -0800602 * @hide
Ravi Paluri80aa2142019-12-02 11:57:37 +0530603 */
604 public static final int PROPERTY_IS_ADHOC_CONFERENCE = 0x00002000;
605
Andrew Lee2378ea72015-04-29 14:38:11 -0700606 //******************************************************************************************
Ravi Paluri80aa2142019-12-02 11:57:37 +0530607 // Next PROPERTY value: 0x00004000
Tyler Gunnd11a3152015-03-18 13:09:14 -0700608 //******************************************************************************************
Tyler Gunn068085b2015-02-06 13:56:52 -0800609
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800610 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700611 private final Uri mHandle;
612 private final int mHandlePresentation;
613 private final String mCallerDisplayName;
614 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700615 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700616 private final int mCallCapabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700617 private final int mCallProperties;
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800618 private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700619 private final DisconnectCause mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700620 private final long mConnectTimeMillis;
621 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700622 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700623 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700624 private final Bundle mExtras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700625 private final Bundle mIntentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700626 private final long mCreationTimeMillis;
Hall Liuef98bf82020-01-09 15:22:44 -0800627 private final String mContactDisplayName;
Tyler Gunn94f8f112018-12-17 09:56:11 -0800628 private final @CallDirection int mCallDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700629 private final @Connection.VerificationStatus int mCallerNumberVerificationStatus;
Ihab Awade63fadb2014-07-09 21:52:04 -0700630
631 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800632 * Whether the supplied capabilities supports the specified capability.
633 *
634 * @param capabilities A bit field of capabilities.
635 * @param capability The capability to check capabilities for.
636 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800637 */
638 public static boolean can(int capabilities, int capability) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800639 return (capabilities & capability) == capability;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800640 }
641
642 /**
643 * Whether the capabilities of this {@code Details} supports the specified capability.
644 *
645 * @param capability The capability to check capabilities for.
646 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800647 */
648 public boolean can(int capability) {
649 return can(mCallCapabilities, capability);
650 }
651
652 /**
653 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
654 *
655 * @param capabilities A capability bit field.
656 * @return A human readable string representation.
657 */
658 public static String capabilitiesToString(int capabilities) {
659 StringBuilder builder = new StringBuilder();
660 builder.append("[Capabilities:");
661 if (can(capabilities, CAPABILITY_HOLD)) {
662 builder.append(" CAPABILITY_HOLD");
663 }
664 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
665 builder.append(" CAPABILITY_SUPPORT_HOLD");
666 }
667 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
668 builder.append(" CAPABILITY_MERGE_CONFERENCE");
669 }
670 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
671 builder.append(" CAPABILITY_SWAP_CONFERENCE");
672 }
673 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
674 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
675 }
676 if (can(capabilities, CAPABILITY_MUTE)) {
677 builder.append(" CAPABILITY_MUTE");
678 }
679 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
680 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
681 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700682 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
683 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
684 }
685 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
686 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
687 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700688 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
689 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800690 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700691 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
692 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
693 }
694 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
695 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
696 }
Tyler Gunnf97a0092016-01-19 15:59:34 -0800697 if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
698 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
699 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700700 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
701 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800702 }
Dong Zhou89f41eb2015-03-15 11:59:49 -0500703 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
Tyler Gunnd11a3152015-03-18 13:09:14 -0700704 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
Dong Zhou89f41eb2015-03-15 11:59:49 -0500705 }
Rekha Kumar07366812015-03-24 16:42:31 -0700706 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
707 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
708 }
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700709 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
710 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
711 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700712 if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
713 builder.append(" CAPABILITY_CAN_PULL_CALL");
714 }
Pooja Jaind34698d2017-12-28 14:15:31 +0530715 if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
716 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
717 }
Ravi Paluri404babb2020-01-23 19:02:44 +0530718 if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) {
719 builder.append(" CAPABILITY_ADD_PARTICIPANT");
720 }
Ravi Palurif4b38e72020-02-05 12:35:41 +0530721 if (can(capabilities, CAPABILITY_TRANSFER)) {
722 builder.append(" CAPABILITY_TRANSFER");
723 }
724 if (can(capabilities, CAPABILITY_TRANSFER_CONSULTATIVE)) {
725 builder.append(" CAPABILITY_TRANSFER_CONSULTATIVE");
726 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800727 builder.append("]");
728 return builder.toString();
729 }
730
731 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700732 * Whether the supplied properties includes the specified property.
733 *
734 * @param properties A bit field of properties.
735 * @param property The property to check properties for.
736 * @return Whether the specified property is supported.
737 */
738 public static boolean hasProperty(int properties, int property) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800739 return (properties & property) == property;
Andrew Lee2378ea72015-04-29 14:38:11 -0700740 }
741
742 /**
743 * Whether the properties of this {@code Details} includes the specified property.
744 *
745 * @param property The property to check properties for.
746 * @return Whether the specified property is supported.
747 */
748 public boolean hasProperty(int property) {
749 return hasProperty(mCallProperties, property);
750 }
751
752 /**
753 * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
754 *
755 * @param properties A property bit field.
756 * @return A human readable string representation.
757 */
758 public static String propertiesToString(int properties) {
759 StringBuilder builder = new StringBuilder();
760 builder.append("[Properties:");
761 if (hasProperty(properties, PROPERTY_CONFERENCE)) {
762 builder.append(" PROPERTY_CONFERENCE");
763 }
764 if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
765 builder.append(" PROPERTY_GENERIC_CONFERENCE");
766 }
767 if (hasProperty(properties, PROPERTY_WIFI)) {
768 builder.append(" PROPERTY_WIFI");
769 }
770 if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
771 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
772 }
773 if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
Yorke Leebe2a4a22015-06-12 10:10:55 -0700774 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
Andrew Lee2378ea72015-04-29 14:38:11 -0700775 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700776 if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
777 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
778 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700779 if (hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
Brad Ebinger15847072016-05-18 11:08:36 -0700780 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
781 }
Tyler Gunnc9503d62020-01-27 10:30:51 -0800782 if (hasProperty(properties, PROPERTY_ASSISTED_DIALING)) {
Eric Erfanianec881872017-12-06 16:27:53 -0800783 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
784 }
Tyler Gunn5bd90852018-09-21 09:37:07 -0700785 if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
786 builder.append(" PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL");
787 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700788 if (hasProperty(properties, PROPERTY_RTT)) {
789 builder.append(" PROPERTY_RTT");
790 }
791 if (hasProperty(properties, PROPERTY_VOIP_AUDIO_MODE)) {
792 builder.append(" PROPERTY_VOIP_AUDIO_MODE");
793 }
Ravi Paluri80aa2142019-12-02 11:57:37 +0530794 if (hasProperty(properties, PROPERTY_IS_ADHOC_CONFERENCE)) {
795 builder.append(" PROPERTY_IS_ADHOC_CONFERENCE");
796 }
Andrew Lee2378ea72015-04-29 14:38:11 -0700797 builder.append("]");
798 return builder.toString();
799 }
800
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800801 /** {@hide} */
Hall Liu31de23d2019-10-11 15:38:29 -0700802 @TestApi
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800803 public String getTelecomCallId() {
804 return mTelecomCallId;
805 }
806
Andrew Lee2378ea72015-04-29 14:38:11 -0700807 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700808 * @return The handle (e.g., phone number) to which the {@code Call} is currently
809 * connected.
810 */
811 public Uri getHandle() {
812 return mHandle;
813 }
814
815 /**
816 * @return The presentation requirements for the handle. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700817 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700818 */
819 public int getHandlePresentation() {
820 return mHandlePresentation;
821 }
822
823 /**
Tyler Gunnd081f042018-12-04 12:56:45 -0800824 * The display name for the caller.
825 * <p>
826 * This is the name as reported by the {@link ConnectionService} associated with this call.
Tyler Gunnd081f042018-12-04 12:56:45 -0800827 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700828 * @return The display name for the caller.
829 */
830 public String getCallerDisplayName() {
831 return mCallerDisplayName;
832 }
833
834 /**
835 * @return The presentation requirements for the caller display name. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700836 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700837 */
838 public int getCallerDisplayNamePresentation() {
839 return mCallerDisplayNamePresentation;
840 }
841
842 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700843 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
844 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700845 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700846 public PhoneAccountHandle getAccountHandle() {
847 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -0700848 }
849
850 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800851 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
852 * {@code CAPABILITY_*} constants in this class.
Ihab Awade63fadb2014-07-09 21:52:04 -0700853 */
Ihab Awad5d0410f2014-07-30 10:07:40 -0700854 public int getCallCapabilities() {
855 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700856 }
857
858 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700859 * @return A bitmask of the properties of the {@code Call}, as defined by the various
860 * {@code PROPERTY_*} constants in this class.
Andrew Lee223ad142014-08-27 16:33:08 -0700861 */
862 public int getCallProperties() {
863 return mCallProperties;
864 }
865
866 /**
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800867 * @return a bitmask of the audio routes available for the call.
868 *
869 * @hide
870 */
871 public int getSupportedAudioRoutes() {
872 return mSupportedAudioRoutes;
873 }
874
875 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700876 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
Nancy Chenf4cf77c2014-09-19 10:53:21 -0700877 * by {@link android.telecom.DisconnectCause}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700878 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700879 public DisconnectCause getDisconnectCause() {
880 return mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700881 }
882
883 /**
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700884 * Returns the time the {@link Call} connected (i.e. became active). This information is
885 * updated periodically, but user interfaces should not rely on this to display the "call
886 * time clock". For the time when the call was first added to Telecom, see
887 * {@link #getCreationTimeMillis()}.
888 *
889 * @return The time the {@link Call} connected in milliseconds since the epoch.
Ihab Awade63fadb2014-07-09 21:52:04 -0700890 */
Jay Shrauner164a0ac2015-04-14 18:16:10 -0700891 public final long getConnectTimeMillis() {
Ihab Awade63fadb2014-07-09 21:52:04 -0700892 return mConnectTimeMillis;
893 }
894
895 /**
896 * @return Information about any calling gateway the {@code Call} may be using.
897 */
898 public GatewayInfo getGatewayInfo() {
899 return mGatewayInfo;
900 }
901
Andrew Lee7a341382014-07-15 17:05:08 -0700902 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -0700903 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -0700904 */
905 public int getVideoState() {
906 return mVideoState;
907 }
908
Ihab Awad5d0410f2014-07-30 10:07:40 -0700909 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700910 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
Ihab Awad5d0410f2014-07-30 10:07:40 -0700911 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -0700912 */
913 public StatusHints getStatusHints() {
914 return mStatusHints;
915 }
916
Nancy Chen10798dc2014-08-08 14:00:25 -0700917 /**
Santos Cordon6b7f9552015-05-27 17:21:45 -0700918 * @return The extras associated with this call.
Nancy Chen10798dc2014-08-08 14:00:25 -0700919 */
920 public Bundle getExtras() {
921 return mExtras;
922 }
923
Santos Cordon6b7f9552015-05-27 17:21:45 -0700924 /**
925 * @return The extras used with the original intent to place this call.
926 */
927 public Bundle getIntentExtras() {
928 return mIntentExtras;
929 }
930
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700931 /**
932 * Returns the time when the call was first created and added to Telecom. This is the same
933 * time that is logged as the start time in the Call Log (see
934 * {@link android.provider.CallLog.Calls#DATE}). To determine when the call was connected
935 * (became active), see {@link #getConnectTimeMillis()}.
936 *
937 * @return The creation time of the call, in millis since the epoch.
938 */
939 public long getCreationTimeMillis() {
940 return mCreationTimeMillis;
941 }
942
Tyler Gunnd081f042018-12-04 12:56:45 -0800943 /**
Hall Liuef98bf82020-01-09 15:22:44 -0800944 * Returns the name of the caller on the remote end, as derived from a
945 * {@link android.provider.ContactsContract} lookup of the call's handle.
946 * @return The name of the caller, or {@code null} if the lookup is not yet complete, if
947 * there's no contacts entry for the caller, or if the {@link InCallService} does
948 * not hold the {@link android.Manifest.permission#READ_CONTACTS} permission.
949 */
950 public @Nullable String getContactDisplayName() {
951 return mContactDisplayName;
952 }
953
954 /**
Tyler Gunn94f8f112018-12-17 09:56:11 -0800955 * Indicates whether the call is an incoming or outgoing call.
956 * @return The call's direction.
957 */
958 public @CallDirection int getCallDirection() {
959 return mCallDirection;
960 }
961
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700962 /**
963 * Gets the verification status for the phone number of an incoming call as identified in
964 * ATIS-1000082.
965 * @return the verification status.
966 */
967 public @Connection.VerificationStatus int getCallerNumberVerificationStatus() {
968 return mCallerNumberVerificationStatus;
969 }
970
Ihab Awade63fadb2014-07-09 21:52:04 -0700971 @Override
972 public boolean equals(Object o) {
973 if (o instanceof Details) {
974 Details d = (Details) o;
975 return
976 Objects.equals(mHandle, d.mHandle) &&
977 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
978 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
979 Objects.equals(mCallerDisplayNamePresentation,
980 d.mCallerDisplayNamePresentation) &&
Evan Charlton8c8a0622014-07-20 12:31:00 -0700981 Objects.equals(mAccountHandle, d.mAccountHandle) &&
Ihab Awad5d0410f2014-07-30 10:07:40 -0700982 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Andrew Lee223ad142014-08-27 16:33:08 -0700983 Objects.equals(mCallProperties, d.mCallProperties) &&
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700984 Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
Ihab Awade63fadb2014-07-09 21:52:04 -0700985 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Andrew Lee85f5d422014-07-11 17:22:03 -0700986 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Evan Charlton5b49ade2014-07-15 17:03:20 -0700987 Objects.equals(mVideoState, d.mVideoState) &&
Nancy Chen10798dc2014-08-08 14:00:25 -0700988 Objects.equals(mStatusHints, d.mStatusHints) &&
Tyler Gunn1e9bfc62015-08-19 11:18:58 -0700989 areBundlesEqual(mExtras, d.mExtras) &&
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700990 areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
Tyler Gunnd081f042018-12-04 12:56:45 -0800991 Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis) &&
Hall Liuef98bf82020-01-09 15:22:44 -0800992 Objects.equals(mContactDisplayName, d.mContactDisplayName) &&
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700993 Objects.equals(mCallDirection, d.mCallDirection) &&
994 Objects.equals(mCallerNumberVerificationStatus,
995 d.mCallerNumberVerificationStatus);
Ihab Awade63fadb2014-07-09 21:52:04 -0700996 }
997 return false;
998 }
999
1000 @Override
1001 public int hashCode() {
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001002 return Objects.hash(mHandle,
1003 mHandlePresentation,
1004 mCallerDisplayName,
1005 mCallerDisplayNamePresentation,
1006 mAccountHandle,
1007 mCallCapabilities,
1008 mCallProperties,
1009 mDisconnectCause,
1010 mConnectTimeMillis,
1011 mGatewayInfo,
1012 mVideoState,
1013 mStatusHints,
1014 mExtras,
1015 mIntentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -08001016 mCreationTimeMillis,
Hall Liuef98bf82020-01-09 15:22:44 -08001017 mContactDisplayName,
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001018 mCallDirection,
1019 mCallerNumberVerificationStatus);
Ihab Awade63fadb2014-07-09 21:52:04 -07001020 }
1021
1022 /** {@hide} */
1023 public Details(
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001024 String telecomCallId,
Ihab Awade63fadb2014-07-09 21:52:04 -07001025 Uri handle,
1026 int handlePresentation,
1027 String callerDisplayName,
1028 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -07001029 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -07001030 int capabilities,
Andrew Lee223ad142014-08-27 16:33:08 -07001031 int properties,
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001032 DisconnectCause disconnectCause,
Ihab Awade63fadb2014-07-09 21:52:04 -07001033 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -07001034 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -07001035 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -07001036 StatusHints statusHints,
Santos Cordon6b7f9552015-05-27 17:21:45 -07001037 Bundle extras,
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001038 Bundle intentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -08001039 long creationTimeMillis,
Hall Liuef98bf82020-01-09 15:22:44 -08001040 String contactDisplayName,
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001041 int callDirection,
1042 int callerNumberVerificationStatus) {
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001043 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001044 mHandle = handle;
1045 mHandlePresentation = handlePresentation;
1046 mCallerDisplayName = callerDisplayName;
1047 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -07001048 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -07001049 mCallCapabilities = capabilities;
Andrew Lee223ad142014-08-27 16:33:08 -07001050 mCallProperties = properties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001051 mDisconnectCause = disconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -07001052 mConnectTimeMillis = connectTimeMillis;
1053 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -07001054 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -07001055 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -07001056 mExtras = extras;
Santos Cordon6b7f9552015-05-27 17:21:45 -07001057 mIntentExtras = intentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001058 mCreationTimeMillis = creationTimeMillis;
Hall Liuef98bf82020-01-09 15:22:44 -08001059 mContactDisplayName = contactDisplayName;
Tyler Gunn94f8f112018-12-17 09:56:11 -08001060 mCallDirection = callDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001061 mCallerNumberVerificationStatus = callerNumberVerificationStatus;
Ihab Awade63fadb2014-07-09 21:52:04 -07001062 }
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001063
1064 /** {@hide} */
1065 public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
1066 return new Details(
1067 parcelableCall.getId(),
1068 parcelableCall.getHandle(),
1069 parcelableCall.getHandlePresentation(),
1070 parcelableCall.getCallerDisplayName(),
1071 parcelableCall.getCallerDisplayNamePresentation(),
1072 parcelableCall.getAccountHandle(),
1073 parcelableCall.getCapabilities(),
1074 parcelableCall.getProperties(),
1075 parcelableCall.getDisconnectCause(),
1076 parcelableCall.getConnectTimeMillis(),
1077 parcelableCall.getGatewayInfo(),
1078 parcelableCall.getVideoState(),
1079 parcelableCall.getStatusHints(),
1080 parcelableCall.getExtras(),
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001081 parcelableCall.getIntentExtras(),
Tyler Gunnd081f042018-12-04 12:56:45 -08001082 parcelableCall.getCreationTimeMillis(),
Hall Liuef98bf82020-01-09 15:22:44 -08001083 parcelableCall.getContactDisplayName(),
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001084 parcelableCall.getCallDirection(),
1085 parcelableCall.getCallerNumberVerificationStatus());
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001086 }
Santos Cordon3c20d632016-02-25 16:12:35 -08001087
1088 @Override
1089 public String toString() {
1090 StringBuilder sb = new StringBuilder();
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001091 sb.append("[id: ");
1092 sb.append(mTelecomCallId);
1093 sb.append(", pa: ");
Santos Cordon3c20d632016-02-25 16:12:35 -08001094 sb.append(mAccountHandle);
1095 sb.append(", hdl: ");
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001096 sb.append(Log.piiHandle(mHandle));
1097 sb.append(", hdlPres: ");
1098 sb.append(mHandlePresentation);
1099 sb.append(", videoState: ");
1100 sb.append(VideoProfile.videoStateToString(mVideoState));
Santos Cordon3c20d632016-02-25 16:12:35 -08001101 sb.append(", caps: ");
1102 sb.append(capabilitiesToString(mCallCapabilities));
1103 sb.append(", props: ");
Tyler Gunn720c6642016-03-22 09:02:47 -07001104 sb.append(propertiesToString(mCallProperties));
Santos Cordon3c20d632016-02-25 16:12:35 -08001105 sb.append("]");
1106 return sb.toString();
1107 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001108 }
1109
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001110 /**
1111 * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
1112 * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
1113 * implementation.
1114 * <p>
1115 * You can handle these callbacks by extending the {@link Callback} class and overriding the
1116 * callbacks that your {@link InCallService} is interested in. The callback methods include the
1117 * {@link Call} for which the callback applies, allowing reuse of a single instance of your
1118 * {@link Callback} implementation, if desired.
1119 * <p>
1120 * Use {@link Call#registerCallback(Callback)} to register your callback(s). Ensure
1121 * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
1122 * (typically in {@link InCallService#onCallRemoved(Call)}).
1123 * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
1124 * reach your implementation of {@link Callback}, so it is important to register your callback
1125 * as soon as your {@link InCallService} is notified of a new call via
1126 * {@link InCallService#onCallAdded(Call)}.
1127 */
Andrew Leeda80c872015-04-15 14:09:50 -07001128 public static abstract class Callback {
Ihab Awade63fadb2014-07-09 21:52:04 -07001129 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001130 * @hide
1131 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001132 @IntDef(prefix = { "HANDOVER_" },
1133 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
Tyler Gunn5c60d712018-03-16 09:53:44 -07001134 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
Tyler Gunn9d127732018-03-02 15:45:51 -08001135 HANDOVER_FAILURE_UNKNOWN})
Sanket Padawea8eddd42017-11-03 11:07:35 -07001136 @Retention(RetentionPolicy.SOURCE)
1137 public @interface HandoverFailureErrors {}
1138
1139 /**
1140 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
Tyler Gunn9d127732018-03-02 15:45:51 -08001141 * to handover the call to rejects the handover request.
1142 * <p>
1143 * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
1144 * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
1145 * {@code null} {@link Connection} from
1146 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1147 * ConnectionRequest)}.
1148 * <p>
1149 * For more information on call handovers, see
1150 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001151 */
1152 public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
1153
1154 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001155 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1156 * is initiated but the source or destination app does not support handover.
1157 * <p>
1158 * Will be returned when a handover is requested via
1159 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
1160 * {@link PhoneAccountHandle} does not declare
1161 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}. May also be returned when a handover is
1162 * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
1163 * {@link Details#getAccountHandle()}) does not declare
1164 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
1165 * <p>
1166 * For more information on call handovers, see
1167 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001168 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001169 public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001170
1171 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001172 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
1173 * user rejects the handover request.
1174 * <p>
1175 * For more information on call handovers, see
1176 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001177 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001178 public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001179
Sanket Padawe85291f62017-12-01 13:59:27 -08001180 /**
1181 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
1182 * is ongoing emergency call.
Tyler Gunn9d127732018-03-02 15:45:51 -08001183 * <p>
1184 * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
1185 * called on an emergency call, or if any other call is an emergency call.
1186 * <p>
1187 * Handovers are not permitted while there are ongoing emergency calls.
1188 * <p>
1189 * For more information on call handovers, see
1190 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawe85291f62017-12-01 13:59:27 -08001191 */
Tyler Gunn5c60d712018-03-16 09:53:44 -07001192 public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
Sanket Padawe85291f62017-12-01 13:59:27 -08001193
Tyler Gunn9d127732018-03-02 15:45:51 -08001194 /**
1195 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1196 * fails for an unknown reason.
1197 * <p>
1198 * For more information on call handovers, see
1199 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
1200 */
1201 public static final int HANDOVER_FAILURE_UNKNOWN = 5;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001202
1203 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001204 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
1205 *
Ihab Awade63fadb2014-07-09 21:52:04 -07001206 * @param call The {@code Call} invoking this method.
1207 * @param state The new state of the {@code Call}.
1208 */
1209 public void onStateChanged(Call call, int state) {}
1210
1211 /**
1212 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
1213 *
1214 * @param call The {@code Call} invoking this method.
1215 * @param parent The new parent of the {@code Call}.
1216 */
1217 public void onParentChanged(Call call, Call parent) {}
1218
1219 /**
1220 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
1221 *
1222 * @param call The {@code Call} invoking this method.
1223 * @param children The new children of the {@code Call}.
1224 */
1225 public void onChildrenChanged(Call call, List<Call> children) {}
1226
1227 /**
1228 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
1229 *
1230 * @param call The {@code Call} invoking this method.
1231 * @param details A {@code Details} object describing the {@code Call}.
1232 */
1233 public void onDetailsChanged(Call call, Details details) {}
1234
1235 /**
1236 * Invoked when the text messages that can be used as responses to the incoming
1237 * {@code Call} are loaded from the relevant database.
1238 * See {@link #getCannedTextResponses()}.
1239 *
1240 * @param call The {@code Call} invoking this method.
1241 * @param cannedTextResponses The text messages useable as responses.
1242 */
1243 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
1244
1245 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001246 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
1247 * character. This causes the post-dial signals to stop pending user confirmation. An
1248 * implementation should present this choice to the user and invoke
1249 * {@link #postDialContinue(boolean)} when the user makes the choice.
1250 *
1251 * @param call The {@code Call} invoking this method.
1252 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
1253 */
1254 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
1255
1256 /**
Andrew Lee50aca232014-07-22 16:41:54 -07001257 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -07001258 *
1259 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -07001260 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001261 */
Andrew Lee50aca232014-07-22 16:41:54 -07001262 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -07001263
1264 /**
1265 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
1266 * up their UI for the {@code Call} in response to state transitions. Specifically,
1267 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
1268 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
1269 * clients should wait for this method to be invoked.
1270 *
1271 * @param call The {@code Call} being destroyed.
1272 */
1273 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001274
1275 /**
1276 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
1277 * conferenced.
1278 *
1279 * @param call The {@code Call} being updated.
1280 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
1281 * conferenced.
1282 */
1283 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001284
1285 /**
Tyler Gunn5567d742019-10-31 13:04:37 -07001286 * Invoked when a {@link Call} receives an event from its associated {@link Connection} or
1287 * {@link Conference}.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001288 * <p>
1289 * Where possible, the Call should make an attempt to handle {@link Connection} events which
1290 * are part of the {@code android.telecom.*} namespace. The Call should ignore any events
1291 * it does not wish to handle. Unexpected events should be handled gracefully, as it is
1292 * possible that a {@link ConnectionService} has defined its own Connection events which a
1293 * Call is not aware of.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001294 * <p>
Tyler Gunn5567d742019-10-31 13:04:37 -07001295 * See {@link Connection#sendConnectionEvent(String, Bundle)},
1296 * {@link Conference#sendConferenceEvent(String, Bundle)}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001297 *
1298 * @param call The {@code Call} receiving the event.
1299 * @param event The event.
1300 * @param extras Extras associated with the connection event.
1301 */
1302 public void onConnectionEvent(Call call, String event, Bundle extras) {}
Hall Liu95d55872017-01-25 17:12:49 -08001303
1304 /**
1305 * Invoked when the RTT mode changes for this call.
1306 * @param call The call whose RTT mode has changed.
1307 * @param mode the new RTT mode, one of
1308 * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
1309 * or {@link RttCall#RTT_MODE_VCO}
1310 */
1311 public void onRttModeChanged(Call call, int mode) {}
1312
1313 /**
1314 * Invoked when the call's RTT status changes, either from off to on or from on to off.
1315 * @param call The call whose RTT status has changed.
1316 * @param enabled whether RTT is now enabled or disabled
1317 * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
1318 * on, null otherwise.
1319 */
1320 public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
1321
1322 /**
1323 * Invoked when the remote end of the connection has requested that an RTT communication
1324 * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
1325 * with the same ID that this method is invoked with.
1326 * @param call The call which the RTT request was placed on
1327 * @param id The ID of the request.
1328 */
1329 public void onRttRequest(Call call, int id) {}
Hall Liu57006aa2017-02-06 10:49:48 -08001330
1331 /**
1332 * Invoked when the RTT session failed to initiate for some reason, including rejection
1333 * by the remote party.
1334 * @param call The call which the RTT initiation failure occurred on.
1335 * @param reason One of the status codes defined in
1336 * {@link android.telecom.Connection.RttModifyStatus}, with the exception of
1337 * {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
1338 */
1339 public void onRttInitiationFailure(Call call, int reason) {}
Sanket Padawea8eddd42017-11-03 11:07:35 -07001340
1341 /**
1342 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1343 * has completed successfully.
Tyler Gunn9d127732018-03-02 15:45:51 -08001344 * <p>
1345 * For a full discussion of the handover process and the APIs involved, see
1346 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1347 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001348 * @param call The call which had initiated handover.
1349 */
1350 public void onHandoverComplete(Call call) {}
1351
1352 /**
1353 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1354 * has failed.
Tyler Gunn9d127732018-03-02 15:45:51 -08001355 * <p>
1356 * For a full discussion of the handover process and the APIs involved, see
1357 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1358 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001359 * @param call The call which had initiated handover.
Tyler Gunn9d127732018-03-02 15:45:51 -08001360 * @param failureReason Error reason for failure.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001361 */
1362 public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
Hall Liu95d55872017-01-25 17:12:49 -08001363 }
1364
1365 /**
1366 * A class that holds the state that describes the state of the RTT channel to the remote
1367 * party, if it is active.
1368 */
1369 public static final class RttCall {
Hall Liu07094df2017-02-28 15:17:44 -08001370 /** @hide */
Hall Liu95d55872017-01-25 17:12:49 -08001371 @Retention(RetentionPolicy.SOURCE)
1372 @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
1373 public @interface RttAudioMode {}
1374
1375 /**
1376 * For metrics use. Default value in the proto.
1377 * @hide
1378 */
1379 public static final int RTT_MODE_INVALID = 0;
1380
1381 /**
1382 * Indicates that there should be a bidirectional audio stream between the two parties
1383 * on the call.
1384 */
1385 public static final int RTT_MODE_FULL = 1;
1386
1387 /**
1388 * Indicates that the local user should be able to hear the audio stream from the remote
1389 * user, but not vice versa. Equivalent to muting the microphone.
1390 */
1391 public static final int RTT_MODE_HCO = 2;
1392
1393 /**
1394 * Indicates that the remote user should be able to hear the audio stream from the local
1395 * user, but not vice versa. Equivalent to setting the volume to zero.
1396 */
1397 public static final int RTT_MODE_VCO = 3;
1398
1399 private static final int READ_BUFFER_SIZE = 1000;
1400
1401 private InputStreamReader mReceiveStream;
1402 private OutputStreamWriter mTransmitStream;
1403 private int mRttMode;
1404 private final InCallAdapter mInCallAdapter;
Hall Liu57006aa2017-02-06 10:49:48 -08001405 private final String mTelecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001406 private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
1407
1408 /**
1409 * @hide
1410 */
Hall Liu57006aa2017-02-06 10:49:48 -08001411 public RttCall(String telecomCallId, InputStreamReader receiveStream,
1412 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
1413 mTelecomCallId = telecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001414 mReceiveStream = receiveStream;
1415 mTransmitStream = transmitStream;
1416 mRttMode = mode;
1417 mInCallAdapter = inCallAdapter;
1418 }
1419
1420 /**
1421 * Returns the current RTT audio mode.
1422 * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
1423 * {@link #RTT_MODE_HCO}.
1424 */
1425 public int getRttAudioMode() {
1426 return mRttMode;
1427 }
1428
1429 /**
1430 * Sets the RTT audio mode. The requested mode change will be communicated through
1431 * {@link Callback#onRttModeChanged(Call, int)}.
1432 * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
1433 * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
1434 */
1435 public void setRttMode(@RttAudioMode int mode) {
Hall Liu57006aa2017-02-06 10:49:48 -08001436 mInCallAdapter.setRttMode(mTelecomCallId, mode);
Hall Liu95d55872017-01-25 17:12:49 -08001437 }
1438
1439 /**
1440 * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
1441 * RTT transmits text in real-time, this method should be called once for each character
1442 * the user enters into the device.
1443 *
1444 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1445 * lead to interleaved text.
1446 * @param input The message to send to the remote user.
1447 */
1448 public void write(String input) throws IOException {
1449 mTransmitStream.write(input);
1450 mTransmitStream.flush();
1451 }
1452
1453 /**
1454 * Reads a string from the remote user, blocking if there is no data available. Returns
1455 * {@code null} if the RTT conversation has been terminated and there is no further data
1456 * to read.
1457 *
1458 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1459 * lead to interleaved text.
1460 * @return A string containing text sent by the remote user, or {@code null} if the
1461 * conversation has been terminated or if there was an error while reading.
1462 */
Hall Liub1c8a772017-07-17 17:04:41 -07001463 public String read() {
1464 try {
1465 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1466 if (numRead < 0) {
1467 return null;
1468 }
1469 return new String(mReadBuffer, 0, numRead);
1470 } catch (IOException e) {
1471 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
Jeff Sharkey90396362017-06-12 16:26:53 -06001472 return null;
Hall Liuffa4a812017-03-02 16:11:00 -08001473 }
Hall Liuffa4a812017-03-02 16:11:00 -08001474 }
1475
1476 /**
1477 * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
1478 * be read.
1479 * @return A string containing text entered by the user, or {@code null} if the user has
1480 * not entered any new text yet.
1481 */
1482 public String readImmediately() throws IOException {
1483 if (mReceiveStream.ready()) {
Hall Liub1c8a772017-07-17 17:04:41 -07001484 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1485 if (numRead < 0) {
1486 return null;
1487 }
1488 return new String(mReadBuffer, 0, numRead);
Hall Liuffa4a812017-03-02 16:11:00 -08001489 } else {
Hall Liu95d55872017-01-25 17:12:49 -08001490 return null;
1491 }
1492 }
Hall Liue9041242018-02-09 16:40:03 -08001493
1494 /**
1495 * Closes the underlying file descriptors
1496 * @hide
1497 */
1498 public void close() {
1499 try {
1500 mReceiveStream.close();
1501 } catch (IOException e) {
1502 // ignore
1503 }
1504 try {
1505 mTransmitStream.close();
1506 } catch (IOException e) {
1507 // ignore
1508 }
1509 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001510 }
1511
Andrew Leeda80c872015-04-15 14:09:50 -07001512 /**
1513 * @deprecated Use {@code Call.Callback} instead.
1514 * @hide
1515 */
1516 @Deprecated
1517 @SystemApi
1518 public static abstract class Listener extends Callback { }
1519
Ihab Awade63fadb2014-07-09 21:52:04 -07001520 private final Phone mPhone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001521 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001522 private final InCallAdapter mInCallAdapter;
Santos Cordon823fd3c2014-08-07 18:35:18 -07001523 private final List<String> mChildrenIds = new ArrayList<>();
Ihab Awade63fadb2014-07-09 21:52:04 -07001524 private final List<Call> mChildren = new ArrayList<>();
1525 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Andrew Lee011728f2015-04-23 15:47:06 -07001526 private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001527 private final List<Call> mConferenceableCalls = new ArrayList<>();
1528 private final List<Call> mUnmodifiableConferenceableCalls =
1529 Collections.unmodifiableList(mConferenceableCalls);
1530
Santos Cordon823fd3c2014-08-07 18:35:18 -07001531 private boolean mChildrenCached;
1532 private String mParentId = null;
Hall Liuef98bf82020-01-09 15:22:44 -08001533 private String mActiveGenericConferenceChild = null;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001534 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -07001535 private List<String> mCannedTextResponses = null;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001536 private String mCallingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001537 private int mTargetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07001538 private String mRemainingPostDialSequence;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001539 private VideoCallImpl mVideoCallImpl;
Hall Liu95d55872017-01-25 17:12:49 -08001540 private RttCall mRttCall;
Ihab Awade63fadb2014-07-09 21:52:04 -07001541 private Details mDetails;
Tyler Gunndee56a82016-03-23 16:06:34 -07001542 private Bundle mExtras;
Ihab Awade63fadb2014-07-09 21:52:04 -07001543
1544 /**
1545 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
1546 *
1547 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
1548 * remaining or this {@code Call} is not in a post-dial state.
1549 */
1550 public String getRemainingPostDialSequence() {
1551 return mRemainingPostDialSequence;
1552 }
1553
1554 /**
1555 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001556 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -07001557 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001558 public void answer(@VideoProfile.VideoState int videoState) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001559 mInCallAdapter.answerCall(mTelecomCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -07001560 }
1561
1562 /**
Pooja Jaind34698d2017-12-28 14:15:31 +05301563 * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
1564 *
1565 * @param address The address to which the call will be deflected.
1566 */
1567 public void deflect(Uri address) {
1568 mInCallAdapter.deflectCall(mTelecomCallId, address);
1569 }
1570
1571 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001572 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
1573 *
1574 * @param rejectWithMessage Whether to reject with a text message.
1575 * @param textMessage An optional text message with which to respond.
1576 */
1577 public void reject(boolean rejectWithMessage, String textMessage) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001578 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
Ihab Awade63fadb2014-07-09 21:52:04 -07001579 }
1580
1581 /**
Tyler Gunnfacfdee2020-01-23 13:10:37 -08001582 * Instructs the {@link ConnectionService} providing this {@link #STATE_RINGING} call that the
1583 * user has chosen to reject the call and has indicated a reason why the call is being rejected.
1584 *
1585 * @param rejectReason the reason the call is being rejected.
1586 */
1587 public void reject(@RejectReason int rejectReason) {
1588 mInCallAdapter.rejectCall(mTelecomCallId, rejectReason);
1589 }
1590
1591 /**
Ravi Palurif4b38e72020-02-05 12:35:41 +05301592 * Instructs this {@code Call} to be transferred to another number.
1593 *
1594 * @param targetNumber The address to which the call will be transferred.
1595 * @param isConfirmationRequired if {@code true} it will initiate ASSURED transfer,
1596 * if {@code false}, it will initiate BLIND transfer.
1597 *
1598 * @hide
1599 */
1600 public void transfer(@NonNull Uri targetNumber, boolean isConfirmationRequired) {
1601 mInCallAdapter.transferCall(mTelecomCallId, targetNumber, isConfirmationRequired);
1602 }
1603
1604 /**
1605 * Instructs this {@code Call} to be transferred to another ongoing call.
1606 * This will initiate CONSULTATIVE transfer.
1607 * @param toCall The other ongoing {@code Call} to which this call will be transferred.
1608 *
1609 * @hide
1610 */
1611 public void transfer(@NonNull android.telecom.Call toCall) {
1612 mInCallAdapter.transferCall(mTelecomCallId, toCall.mTelecomCallId);
1613 }
1614
1615 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001616 * Instructs this {@code Call} to disconnect.
1617 */
1618 public void disconnect() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001619 mInCallAdapter.disconnectCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001620 }
1621
1622 /**
1623 * Instructs this {@code Call} to go on hold.
1624 */
1625 public void hold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001626 mInCallAdapter.holdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001627 }
1628
1629 /**
1630 * Instructs this {@link #STATE_HOLDING} call to release from hold.
1631 */
1632 public void unhold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001633 mInCallAdapter.unholdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001634 }
1635
1636 /**
Hall Liu6dfa2492019-10-01 17:20:39 -07001637 * Instructs Telecom to put the call into the background audio processing state.
1638 *
1639 * This method can be called either when the call is in {@link #STATE_RINGING} or
1640 * {@link #STATE_ACTIVE}. After Telecom acknowledges the request by setting the call's state to
1641 * {@link #STATE_AUDIO_PROCESSING}, your app may setup the audio paths with the audio stack in
1642 * order to capture and play audio on the call stream.
1643 *
1644 * This method can only be called by the default dialer app.
1645 * @hide
1646 */
1647 @SystemApi
1648 @TestApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001649 public void enterBackgroundAudioProcessing() {
1650 if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
1651 throw new IllegalStateException("Call must be active or ringing");
1652 }
1653 mInCallAdapter.enterBackgroundAudioProcessing(mTelecomCallId);
1654 }
1655
1656 /**
1657 * Instructs Telecom to come out of the background audio processing state requested by
1658 * {@link #enterBackgroundAudioProcessing()} or from the call screening service.
1659 *
1660 * This method can only be called when the call is in {@link #STATE_AUDIO_PROCESSING}.
1661 *
1662 * @param shouldRing If true, Telecom will put the call into the
1663 * {@link #STATE_SIMULATED_RINGING} state and notify other apps that there is
1664 * a ringing call. Otherwise, the call will go into {@link #STATE_ACTIVE}
1665 * immediately.
1666 * @hide
1667 */
1668 @SystemApi
1669 @TestApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001670 public void exitBackgroundAudioProcessing(boolean shouldRing) {
1671 if (mState != STATE_AUDIO_PROCESSING) {
1672 throw new IllegalStateException("Call must in the audio processing state");
1673 }
1674 mInCallAdapter.exitBackgroundAudioProcessing(mTelecomCallId, shouldRing);
1675 }
1676
1677 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001678 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
1679 *
1680 * Any other currently playing DTMF tone in the specified call is immediately stopped.
1681 *
1682 * @param digit A character representing the DTMF digit for which to play the tone. This
1683 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
1684 */
1685 public void playDtmfTone(char digit) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001686 mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
Ihab Awade63fadb2014-07-09 21:52:04 -07001687 }
1688
1689 /**
1690 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
1691 * currently playing.
1692 *
1693 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
1694 * currently playing, this method will do nothing.
1695 */
1696 public void stopDtmfTone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001697 mInCallAdapter.stopDtmfTone(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001698 }
1699
1700 /**
1701 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
1702 *
1703 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
1704 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -07001705 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001706 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -07001707 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
1708 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001709 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
Andrew Leeda80c872015-04-15 14:09:50 -07001710 * {@code Call} will pause playing the tones and notify callbacks via
1711 * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
Ihab Awade63fadb2014-07-09 21:52:04 -07001712 * should display to the user an indication of this state and an affordance to continue
1713 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
1714 * app should invoke the {@link #postDialContinue(boolean)} method.
1715 *
1716 * @param proceed Whether or not to continue with the post-dial sequence.
1717 */
1718 public void postDialContinue(boolean proceed) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001719 mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
Ihab Awade63fadb2014-07-09 21:52:04 -07001720 }
1721
1722 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -07001723 * Notifies this {@code Call} that an account has been selected and to proceed with placing
Nancy Chen36c62f32014-10-21 18:36:39 -07001724 * an outgoing call. Optionally sets this account as the default account.
Nancy Chen5da0fd52014-07-08 14:16:17 -07001725 */
Nancy Chen36c62f32014-10-21 18:36:39 -07001726 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
1727 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
Nancy Chen5da0fd52014-07-08 14:16:17 -07001728
1729 }
1730
1731 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001732 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001733 *
1734 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -07001735 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001736 public void conference(Call callToConferenceWith) {
1737 if (callToConferenceWith != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001738 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001739 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001740 }
1741
1742 /**
1743 * Instructs this {@code Call} to split from any conference call with which it may be
1744 * connected.
1745 */
1746 public void splitFromConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001747 mInCallAdapter.splitFromConference(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001748 }
1749
1750 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001751 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001752 */
1753 public void mergeConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001754 mInCallAdapter.mergeConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001755 }
1756
1757 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001758 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001759 */
1760 public void swapConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001761 mInCallAdapter.swapConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001762 }
1763
1764 /**
Ravi Paluri404babb2020-01-23 19:02:44 +05301765 * Pulls participants to existing call by forming a conference call.
1766 * See {@link Details#CAPABILITY_ADD_PARTICIPANT}.
1767 *
1768 * @param participants participants to be pulled to existing call.
Tyler Gunn0c62ef02020-02-11 14:39:43 -08001769 * @hide
Ravi Paluri404babb2020-01-23 19:02:44 +05301770 */
1771 public void addConferenceParticipants(@NonNull List<Uri> participants) {
1772 mInCallAdapter.addConferenceParticipants(mTelecomCallId, participants);
1773 }
1774
1775 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001776 * Initiates a request to the {@link ConnectionService} to pull an external call to the local
1777 * device.
1778 * <p>
1779 * Calls to this method are ignored if the call does not have the
1780 * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
1781 * <p>
1782 * An {@link InCallService} will only see calls which support this method if it has the
1783 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
1784 * in its manifest.
1785 */
1786 public void pullExternalCall() {
1787 // If this isn't an external call, ignore the request.
1788 if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
1789 return;
1790 }
1791
1792 mInCallAdapter.pullExternalCall(mTelecomCallId);
1793 }
1794
1795 /**
1796 * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
1797 * the {@link ConnectionService}.
1798 * <p>
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001799 * Call events are used to communicate point in time information from an {@link InCallService}
1800 * to a {@link ConnectionService}. A {@link ConnectionService} implementation could define
1801 * events which enable the {@link InCallService}, for example, toggle a unique feature of the
1802 * {@link ConnectionService}.
1803 * <p>
1804 * A {@link ConnectionService} can communicate to the {@link InCallService} using
1805 * {@link Connection#sendConnectionEvent(String, Bundle)}.
1806 * <p>
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001807 * Events are exposed to {@link ConnectionService} implementations via
1808 * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
1809 * <p>
1810 * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001811 * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
1812 * ignore some events altogether.
1813 * <p>
1814 * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
1815 * conflicts between {@link InCallService} implementations. Further, {@link InCallService}
1816 * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
1817 * they define their own event types in this namespace. When defining a custom event type,
1818 * ensure the contents of the extras {@link Bundle} is clearly defined. Extra keys for this
1819 * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
1820 * <p>
1821 * When defining events and the associated extras, it is important to keep their behavior
1822 * consistent when the associated {@link InCallService} is updated. Support for deprecated
1823 * events/extras should me maintained to ensure backwards compatibility with older
1824 * {@link ConnectionService} implementations which were built to support the older behavior.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001825 *
1826 * @param event The connection event.
1827 * @param extras Bundle containing extra information associated with the event.
1828 */
1829 public void sendCallEvent(String event, Bundle extras) {
Sanket Padawef6a9e5b2018-01-05 14:26:16 -08001830 mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001831 }
1832
1833 /**
Hall Liu95d55872017-01-25 17:12:49 -08001834 * Sends an RTT upgrade request to the remote end of the connection. Success is not
1835 * guaranteed, and notification of success will be via the
1836 * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1837 */
1838 public void sendRttRequest() {
Hall Liu57006aa2017-02-06 10:49:48 -08001839 mInCallAdapter.sendRttRequest(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001840 }
1841
1842 /**
1843 * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
1844 * callback.
1845 * The ID used here should be the same as the ID that was received via the callback.
1846 * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
1847 * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
1848 */
1849 public void respondToRttRequest(int id, boolean accept) {
Hall Liu57006aa2017-02-06 10:49:48 -08001850 mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
Hall Liu95d55872017-01-25 17:12:49 -08001851 }
1852
1853 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001854 * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
1855 * by {@code toHandle}. The videoState specified indicates the desired video state after the
1856 * handover.
1857 * <p>
Tyler Gunn9d127732018-03-02 15:45:51 -08001858 * A call handover is the process where an ongoing call is transferred from one app (i.e.
1859 * {@link ConnectionService} to another app. The user could, for example, choose to continue a
1860 * mobile network call in a video calling app. The mobile network call via the Telephony stack
1861 * is referred to as the source of the handover, and the video calling app is referred to as the
1862 * destination.
1863 * <p>
1864 * When considering a handover scenario the device this method is called on is considered the
1865 * <em>initiating</em> device (since the user initiates the handover from this device), and the
1866 * other device is considered the <em>receiving</em> device.
1867 * <p>
1868 * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
1869 * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
1870 * and invoke
1871 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1872 * ConnectionRequest)} to inform the destination app that a request has been made to handover a
1873 * call to it. The app returns an instance of {@link Connection} to represent the handover call
1874 * At this point the app should display UI to indicate to the user that a call
1875 * handover is in process.
1876 * <p>
1877 * The destination app is responsible for communicating the handover request from the
1878 * <em>initiating</em> device to the <em>receiving</em> device.
1879 * <p>
1880 * When the app on the <em>receiving</em> device receives the handover request, it calls
1881 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
1882 * process from the <em>initiating</em> device to the <em>receiving</em> device. At this point
1883 * the destination app on the <em>receiving</em> device should show UI to allow the user to
1884 * choose whether they want to continue their call in the destination app.
1885 * <p>
1886 * When the destination app on the <em>receiving</em> device calls
1887 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
1888 * {@link ConnectionService} and call
1889 * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
1890 * ConnectionRequest)} to inform it of the handover request. The app returns an instance of
1891 * {@link Connection} to represent the handover call.
1892 * <p>
1893 * If the user of the <em>receiving</em> device accepts the handover, the app calls
1894 * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
1895 * original call. If the user rejects the handover, the app calls
1896 * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
1897 * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
1898 * <p>
1899 * Telecom will only allow handovers from {@link PhoneAccount}s which declare
1900 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}. Similarly, the {@link PhoneAccount}
1901 * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
1902 * <p>
1903 * Errors in the handover process are reported to the {@link InCallService} via
1904 * {@link Callback#onHandoverFailed(Call, int)}. Errors in the handover process are reported to
1905 * the involved {@link ConnectionService}s via
1906 * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001907 *
1908 * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
1909 * this call to.
Tyler Gunn9d127732018-03-02 15:45:51 -08001910 * @param videoState Indicates the video state desired after the handover (see the
1911 * {@code STATE_*} constants defined in {@link VideoProfile}).
Sanket Padawea8eddd42017-11-03 11:07:35 -07001912 * @param extras Bundle containing extra information to be passed to the
1913 * {@link ConnectionService}
1914 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001915 public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
1916 Bundle extras) {
Sanket Padawea8eddd42017-11-03 11:07:35 -07001917 mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
1918 }
1919
1920 /**
Hall Liu95d55872017-01-25 17:12:49 -08001921 * Terminate the RTT session on this call. The resulting state change will be notified via
1922 * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1923 */
1924 public void stopRtt() {
Hall Liu57006aa2017-02-06 10:49:48 -08001925 mInCallAdapter.stopRtt(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001926 }
1927
1928 /**
Tyler Gunndee56a82016-03-23 16:06:34 -07001929 * Adds some extras to this {@link Call}. Existing keys are replaced and new ones are
1930 * added.
1931 * <p>
1932 * No assumptions should be made as to how an In-Call UI or service will handle these
1933 * extras. Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
1934 *
1935 * @param extras The extras to add.
1936 */
1937 public final void putExtras(Bundle extras) {
1938 if (extras == null) {
1939 return;
1940 }
1941
1942 if (mExtras == null) {
1943 mExtras = new Bundle();
1944 }
1945 mExtras.putAll(extras);
1946 mInCallAdapter.putExtras(mTelecomCallId, extras);
1947 }
1948
1949 /**
1950 * Adds a boolean extra to this {@link Call}.
1951 *
1952 * @param key The extra key.
1953 * @param value The value.
1954 * @hide
1955 */
1956 public final void putExtra(String key, boolean value) {
1957 if (mExtras == null) {
1958 mExtras = new Bundle();
1959 }
1960 mExtras.putBoolean(key, value);
1961 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1962 }
1963
1964 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001965 * Adds an integer extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001966 *
1967 * @param key The extra key.
1968 * @param value The value.
1969 * @hide
1970 */
1971 public final void putExtra(String key, int value) {
1972 if (mExtras == null) {
1973 mExtras = new Bundle();
1974 }
1975 mExtras.putInt(key, value);
1976 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1977 }
1978
1979 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001980 * Adds a string extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001981 *
1982 * @param key The extra key.
1983 * @param value The value.
1984 * @hide
1985 */
1986 public final void putExtra(String key, String value) {
1987 if (mExtras == null) {
1988 mExtras = new Bundle();
1989 }
1990 mExtras.putString(key, value);
1991 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1992 }
1993
1994 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001995 * Removes extras from this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001996 *
1997 * @param keys The keys of the extras to remove.
1998 */
1999 public final void removeExtras(List<String> keys) {
2000 if (mExtras != null) {
2001 for (String key : keys) {
2002 mExtras.remove(key);
2003 }
2004 if (mExtras.size() == 0) {
2005 mExtras = null;
2006 }
2007 }
2008 mInCallAdapter.removeExtras(mTelecomCallId, keys);
2009 }
2010
2011 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002012 * Removes extras from this {@link Call}.
2013 *
2014 * @param keys The keys of the extras to remove.
2015 */
2016 public final void removeExtras(String ... keys) {
2017 removeExtras(Arrays.asList(keys));
2018 }
2019
2020 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002021 * Obtains the parent of this {@code Call} in a conference, if any.
2022 *
2023 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
2024 * child of any conference {@code Call}s.
2025 */
2026 public Call getParent() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002027 if (mParentId != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002028 return mPhone.internalGetCallByTelecomId(mParentId);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002029 }
2030 return null;
Ihab Awade63fadb2014-07-09 21:52:04 -07002031 }
2032
2033 /**
2034 * Obtains the children of this conference {@code Call}, if any.
2035 *
2036 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
2037 * {@code List} otherwise.
2038 */
2039 public List<Call> getChildren() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002040 if (!mChildrenCached) {
2041 mChildrenCached = true;
2042 mChildren.clear();
2043
2044 for(String id : mChildrenIds) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002045 Call call = mPhone.internalGetCallByTelecomId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002046 if (call == null) {
2047 // At least one child was still not found, so do not save true for "cached"
2048 mChildrenCached = false;
2049 } else {
2050 mChildren.add(call);
2051 }
2052 }
2053 }
2054
Ihab Awade63fadb2014-07-09 21:52:04 -07002055 return mUnmodifiableChildren;
2056 }
2057
2058 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002059 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
2060 *
2061 * @return The list of conferenceable {@code Call}s.
2062 */
2063 public List<Call> getConferenceableCalls() {
2064 return mUnmodifiableConferenceableCalls;
2065 }
2066
2067 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002068 * Obtains the state of this {@code Call}.
2069 *
2070 * @return A state value, chosen from the {@code STATE_*} constants.
2071 */
2072 public int getState() {
2073 return mState;
2074 }
2075
2076 /**
Hall Liuef98bf82020-01-09 15:22:44 -08002077 * Returns the child {@link Call} in a generic conference that is currently active.
Hall Liu55085912020-02-27 18:34:11 -08002078 *
2079 * A "generic conference" is the mechanism used to support two simultaneous calls on a device
2080 * in CDMA networks. It is effectively equivalent to having one call active and one call on hold
2081 * in GSM or IMS calls. This method returns the currently active call.
2082 *
2083 * In a generic conference, the network exposes the conference to us as a single call, and we
2084 * switch between talking to the two participants using a CDMA flash command. Since the network
2085 * exposes no additional information about the call, the only way we know which caller we're
2086 * currently talking to is by keeping track of the flash commands that we've sent to the
2087 * network.
2088 *
Hall Liuef98bf82020-01-09 15:22:44 -08002089 * For calls that are not generic conferences, or when the generic conference has more than
2090 * 2 children, returns {@code null}.
2091 * @see Details#PROPERTY_GENERIC_CONFERENCE
2092 * @return The active child call.
2093 */
2094 public @Nullable Call getGenericConferenceActiveChildCall() {
2095 if (mActiveGenericConferenceChild != null) {
2096 return mPhone.internalGetCallByTelecomId(mActiveGenericConferenceChild);
2097 }
2098 return null;
2099 }
2100
2101 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002102 * Obtains a list of canned, pre-configured message responses to present to the user as
2103 * ways of rejecting this {@code Call} using via a text message.
2104 *
2105 * @see #reject(boolean, String)
2106 *
2107 * @return A list of canned text message responses.
2108 */
2109 public List<String> getCannedTextResponses() {
2110 return mCannedTextResponses;
2111 }
2112
2113 /**
2114 * Obtains an object that can be used to display video from this {@code Call}.
2115 *
Andrew Lee50aca232014-07-22 16:41:54 -07002116 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -07002117 */
Andrew Lee50aca232014-07-22 16:41:54 -07002118 public InCallService.VideoCall getVideoCall() {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002119 return mVideoCallImpl;
Ihab Awade63fadb2014-07-09 21:52:04 -07002120 }
2121
2122 /**
2123 * Obtains an object containing call details.
2124 *
2125 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
2126 * result may be {@code null}.
2127 */
2128 public Details getDetails() {
2129 return mDetails;
2130 }
2131
2132 /**
Hall Liu95d55872017-01-25 17:12:49 -08002133 * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
2134 * receive RTT text data, as well as to change the RTT mode.
2135 * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
2136 */
2137 public @Nullable RttCall getRttCall() {
2138 return mRttCall;
2139 }
2140
2141 /**
2142 * Returns whether this call has an active RTT connection.
2143 * @return true if there is a connection, false otherwise.
2144 */
2145 public boolean isRttActive() {
Hall Liue9041242018-02-09 16:40:03 -08002146 return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
Hall Liu95d55872017-01-25 17:12:49 -08002147 }
2148
2149 /**
Andrew Leeda80c872015-04-15 14:09:50 -07002150 * Registers a callback to this {@code Call}.
2151 *
2152 * @param callback A {@code Callback}.
2153 */
2154 public void registerCallback(Callback callback) {
Andrew Lee011728f2015-04-23 15:47:06 -07002155 registerCallback(callback, new Handler());
2156 }
2157
2158 /**
2159 * Registers a callback to this {@code Call}.
2160 *
2161 * @param callback A {@code Callback}.
2162 * @param handler A handler which command and status changes will be delivered to.
2163 */
2164 public void registerCallback(Callback callback, Handler handler) {
2165 unregisterCallback(callback);
Roshan Pius1ca62072015-07-07 17:34:51 -07002166 // Don't allow new callback registration if the call is already being destroyed.
2167 if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002168 mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
2169 }
Andrew Leeda80c872015-04-15 14:09:50 -07002170 }
2171
2172 /**
2173 * Unregisters a callback from this {@code Call}.
2174 *
2175 * @param callback A {@code Callback}.
2176 */
2177 public void unregisterCallback(Callback callback) {
Roshan Pius1ca62072015-07-07 17:34:51 -07002178 // Don't allow callback deregistration if the call is already being destroyed.
2179 if (callback != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002180 for (CallbackRecord<Callback> record : mCallbackRecords) {
2181 if (record.getCallback() == callback) {
2182 mCallbackRecords.remove(record);
2183 break;
2184 }
2185 }
Andrew Leeda80c872015-04-15 14:09:50 -07002186 }
2187 }
2188
Santos Cordon3c20d632016-02-25 16:12:35 -08002189 @Override
2190 public String toString() {
2191 return new StringBuilder().
2192 append("Call [id: ").
2193 append(mTelecomCallId).
2194 append(", state: ").
2195 append(stateToString(mState)).
2196 append(", details: ").
2197 append(mDetails).
2198 append("]").toString();
2199 }
2200
2201 /**
2202 * @param state An integer value of a {@code STATE_*} constant.
2203 * @return A string representation of the value.
2204 */
2205 private static String stateToString(int state) {
2206 switch (state) {
2207 case STATE_NEW:
2208 return "NEW";
2209 case STATE_RINGING:
2210 return "RINGING";
2211 case STATE_DIALING:
2212 return "DIALING";
2213 case STATE_ACTIVE:
2214 return "ACTIVE";
2215 case STATE_HOLDING:
2216 return "HOLDING";
2217 case STATE_DISCONNECTED:
2218 return "DISCONNECTED";
2219 case STATE_CONNECTING:
2220 return "CONNECTING";
2221 case STATE_DISCONNECTING:
2222 return "DISCONNECTING";
2223 case STATE_SELECT_PHONE_ACCOUNT:
2224 return "SELECT_PHONE_ACCOUNT";
Hall Liu4e35b642019-10-14 17:50:45 -07002225 case STATE_SIMULATED_RINGING:
2226 return "SIMULATED_RINGING";
2227 case STATE_AUDIO_PROCESSING:
2228 return "AUDIO_PROCESSING";
Santos Cordon3c20d632016-02-25 16:12:35 -08002229 default:
2230 Log.w(Call.class, "Unknown state %d", state);
2231 return "UNKNOWN";
2232 }
2233 }
2234
Andrew Leeda80c872015-04-15 14:09:50 -07002235 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002236 * Adds a listener to this {@code Call}.
2237 *
2238 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002239 * @deprecated Use {@link #registerCallback} instead.
2240 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002241 */
Andrew Leeda80c872015-04-15 14:09:50 -07002242 @Deprecated
2243 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002244 public void addListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002245 registerCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002246 }
2247
2248 /**
2249 * Removes a listener from this {@code Call}.
2250 *
2251 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002252 * @deprecated Use {@link #unregisterCallback} instead.
2253 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002254 */
Andrew Leeda80c872015-04-15 14:09:50 -07002255 @Deprecated
2256 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002257 public void removeListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002258 unregisterCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002259 }
2260
2261 /** {@hide} */
Tyler Gunn159f35c2017-03-02 09:28:37 -08002262 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
2263 int targetSdkVersion) {
Ihab Awade63fadb2014-07-09 21:52:04 -07002264 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002265 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002266 mInCallAdapter = inCallAdapter;
2267 mState = STATE_NEW;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002268 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002269 mTargetSdkVersion = targetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07002270 }
2271
2272 /** {@hide} */
Tyler Gunnb88b3112016-11-09 10:19:23 -08002273 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
Tyler Gunn159f35c2017-03-02 09:28:37 -08002274 String callingPackage, int targetSdkVersion) {
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002275 mPhone = phone;
2276 mTelecomCallId = telecomCallId;
2277 mInCallAdapter = inCallAdapter;
2278 mState = state;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002279 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002280 mTargetSdkVersion = targetSdkVersion;
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002281 }
2282
2283 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002284 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002285 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002286 }
2287
2288 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002289 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Tyler Gunnb88b3112016-11-09 10:19:23 -08002290
Ihab Awade63fadb2014-07-09 21:52:04 -07002291 // First, we update the internal state as far as possible before firing any updates.
Sailesh Nepal1bef3392016-01-24 18:21:53 -08002292 Details details = Details.createFromParcelableCall(parcelableCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07002293 boolean detailsChanged = !Objects.equals(mDetails, details);
2294 if (detailsChanged) {
2295 mDetails = details;
2296 }
2297
2298 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -07002299 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
2300 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
2301 mCannedTextResponses =
2302 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Yorke Leee886f632015-08-04 13:43:31 -07002303 cannedTextResponsesChanged = true;
Ihab Awade63fadb2014-07-09 21:52:04 -07002304 }
2305
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002306 IVideoProvider previousVideoProvider = mVideoCallImpl == null ? null :
2307 mVideoCallImpl.getVideoProvider();
2308 IVideoProvider newVideoProvider = parcelableCall.getVideoProvider();
2309
2310 // parcelableCall.isVideoCallProviderChanged is only true when we have a video provider
2311 // specified; so we should check if the actual IVideoProvider changes as well.
2312 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged()
2313 && !Objects.equals(previousVideoProvider, newVideoProvider);
Andrew Lee50aca232014-07-22 16:41:54 -07002314 if (videoCallChanged) {
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002315 if (mVideoCallImpl != null) {
2316 mVideoCallImpl.destroy();
2317 }
2318 mVideoCallImpl = parcelableCall.isVideoCallProviderChanged() ?
2319 parcelableCall.getVideoCallImpl(mCallingPackage, mTargetSdkVersion) : null;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002320 }
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002321
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002322 if (mVideoCallImpl != null) {
2323 mVideoCallImpl.setVideoState(getDetails().getVideoState());
Ihab Awade63fadb2014-07-09 21:52:04 -07002324 }
2325
Santos Cordone3c507b2015-04-23 14:44:19 -07002326 int state = parcelableCall.getState();
Hall Liu31de23d2019-10-11 15:38:29 -07002327 if (mTargetSdkVersion < Phone.SDK_VERSION_R && state == Call.STATE_SIMULATED_RINGING) {
2328 state = Call.STATE_RINGING;
2329 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002330 boolean stateChanged = mState != state;
2331 if (stateChanged) {
2332 mState = state;
2333 }
2334
Santos Cordon823fd3c2014-08-07 18:35:18 -07002335 String parentId = parcelableCall.getParentCallId();
2336 boolean parentChanged = !Objects.equals(mParentId, parentId);
2337 if (parentChanged) {
2338 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002339 }
2340
Santos Cordon823fd3c2014-08-07 18:35:18 -07002341 List<String> childCallIds = parcelableCall.getChildCallIds();
2342 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
2343 if (childrenChanged) {
2344 mChildrenIds.clear();
2345 mChildrenIds.addAll(parcelableCall.getChildCallIds());
2346 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -07002347 }
2348
Hall Liuef98bf82020-01-09 15:22:44 -08002349 String activeChildCallId = parcelableCall.getActiveChildCallId();
2350 boolean activeChildChanged = !Objects.equals(activeChildCallId,
2351 mActiveGenericConferenceChild);
2352 if (activeChildChanged) {
2353 mActiveGenericConferenceChild = activeChildCallId;
2354 }
2355
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002356 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
2357 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
2358 for (String otherId : conferenceableCallIds) {
2359 if (callIdMap.containsKey(otherId)) {
2360 conferenceableCalls.add(callIdMap.get(otherId));
2361 }
2362 }
2363
2364 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
2365 mConferenceableCalls.clear();
2366 mConferenceableCalls.addAll(conferenceableCalls);
2367 fireConferenceableCallsChanged();
2368 }
2369
Hall Liu95d55872017-01-25 17:12:49 -08002370 boolean isRttChanged = false;
2371 boolean rttModeChanged = false;
Hall Liue9041242018-02-09 16:40:03 -08002372 if (parcelableCall.getIsRttCallChanged()
2373 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
Hall Liu95d55872017-01-25 17:12:49 -08002374 ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
2375 InputStreamReader receiveStream = new InputStreamReader(
2376 new ParcelFileDescriptor.AutoCloseInputStream(
2377 parcelableRttCall.getReceiveStream()),
2378 StandardCharsets.UTF_8);
2379 OutputStreamWriter transmitStream = new OutputStreamWriter(
2380 new ParcelFileDescriptor.AutoCloseOutputStream(
2381 parcelableRttCall.getTransmitStream()),
2382 StandardCharsets.UTF_8);
Hall Liu57006aa2017-02-06 10:49:48 -08002383 RttCall newRttCall = new Call.RttCall(mTelecomCallId,
Hall Liu95d55872017-01-25 17:12:49 -08002384 receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
2385 if (mRttCall == null) {
2386 isRttChanged = true;
2387 } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
2388 rttModeChanged = true;
2389 }
2390 mRttCall = newRttCall;
2391 } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
2392 && parcelableCall.getIsRttCallChanged()) {
2393 isRttChanged = true;
2394 mRttCall = null;
2395 }
2396
Ihab Awade63fadb2014-07-09 21:52:04 -07002397 // Now we fire updates, ensuring that any client who listens to any of these notifications
2398 // gets the most up-to-date state.
2399
2400 if (stateChanged) {
2401 fireStateChanged(mState);
2402 }
2403 if (detailsChanged) {
2404 fireDetailsChanged(mDetails);
2405 }
2406 if (cannedTextResponsesChanged) {
2407 fireCannedTextResponsesLoaded(mCannedTextResponses);
2408 }
Andrew Lee50aca232014-07-22 16:41:54 -07002409 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002410 fireVideoCallChanged(mVideoCallImpl);
Ihab Awade63fadb2014-07-09 21:52:04 -07002411 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002412 if (parentChanged) {
2413 fireParentChanged(getParent());
2414 }
Hall Liuef98bf82020-01-09 15:22:44 -08002415 if (childrenChanged || activeChildChanged) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002416 fireChildrenChanged(getChildren());
2417 }
Hall Liu95d55872017-01-25 17:12:49 -08002418 if (isRttChanged) {
2419 fireOnIsRttChanged(mRttCall != null, mRttCall);
2420 }
2421 if (rttModeChanged) {
2422 fireOnRttModeChanged(mRttCall.getRttAudioMode());
2423 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002424
2425 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
2426 // remove ourselves from the Phone. Note that we do this after completing all state updates
2427 // so a client can cleanly transition all their UI to the state appropriate for a
2428 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
2429 if (mState == STATE_DISCONNECTED) {
2430 fireCallDestroyed();
Ihab Awade63fadb2014-07-09 21:52:04 -07002431 }
2432 }
2433
2434 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002435 final void internalSetPostDialWait(String remaining) {
2436 mRemainingPostDialSequence = remaining;
2437 firePostDialWait(mRemainingPostDialSequence);
2438 }
2439
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07002440 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -07002441 final void internalSetDisconnected() {
2442 if (mState != Call.STATE_DISCONNECTED) {
2443 mState = Call.STATE_DISCONNECTED;
2444 fireStateChanged(mState);
2445 fireCallDestroyed();
Santos Cordonf30d7e92014-08-26 09:54:33 -07002446 }
2447 }
2448
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002449 /** {@hide} */
2450 final void internalOnConnectionEvent(String event, Bundle extras) {
2451 fireOnConnectionEvent(event, extras);
2452 }
2453
Hall Liu95d55872017-01-25 17:12:49 -08002454 /** {@hide} */
2455 final void internalOnRttUpgradeRequest(final int requestId) {
2456 for (CallbackRecord<Callback> record : mCallbackRecords) {
2457 final Call call = this;
2458 final Callback callback = record.getCallback();
2459 record.getHandler().post(() -> callback.onRttRequest(call, requestId));
2460 }
2461 }
2462
Hall Liu57006aa2017-02-06 10:49:48 -08002463 /** @hide */
2464 final void internalOnRttInitiationFailure(int reason) {
2465 for (CallbackRecord<Callback> record : mCallbackRecords) {
2466 final Call call = this;
2467 final Callback callback = record.getCallback();
2468 record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
2469 }
2470 }
2471
Sanket Padawe85291f62017-12-01 13:59:27 -08002472 /** {@hide} */
2473 final void internalOnHandoverFailed(int error) {
2474 for (CallbackRecord<Callback> record : mCallbackRecords) {
2475 final Call call = this;
2476 final Callback callback = record.getCallback();
2477 record.getHandler().post(() -> callback.onHandoverFailed(call, error));
2478 }
2479 }
2480
Tyler Gunn858bfaf2018-01-22 15:17:54 -08002481 /** {@hide} */
2482 final void internalOnHandoverComplete() {
2483 for (CallbackRecord<Callback> record : mCallbackRecords) {
2484 final Call call = this;
2485 final Callback callback = record.getCallback();
2486 record.getHandler().post(() -> callback.onHandoverComplete(call));
2487 }
2488 }
2489
Andrew Lee011728f2015-04-23 15:47:06 -07002490 private void fireStateChanged(final int newState) {
2491 for (CallbackRecord<Callback> record : mCallbackRecords) {
2492 final Call call = this;
2493 final Callback callback = record.getCallback();
2494 record.getHandler().post(new Runnable() {
2495 @Override
2496 public void run() {
2497 callback.onStateChanged(call, newState);
2498 }
2499 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002500 }
2501 }
2502
Andrew Lee011728f2015-04-23 15:47:06 -07002503 private void fireParentChanged(final Call newParent) {
2504 for (CallbackRecord<Callback> record : mCallbackRecords) {
2505 final Call call = this;
2506 final Callback callback = record.getCallback();
2507 record.getHandler().post(new Runnable() {
2508 @Override
2509 public void run() {
2510 callback.onParentChanged(call, newParent);
2511 }
2512 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002513 }
2514 }
2515
Andrew Lee011728f2015-04-23 15:47:06 -07002516 private void fireChildrenChanged(final List<Call> children) {
2517 for (CallbackRecord<Callback> record : mCallbackRecords) {
2518 final Call call = this;
2519 final Callback callback = record.getCallback();
2520 record.getHandler().post(new Runnable() {
2521 @Override
2522 public void run() {
2523 callback.onChildrenChanged(call, children);
2524 }
2525 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002526 }
2527 }
2528
Andrew Lee011728f2015-04-23 15:47:06 -07002529 private void fireDetailsChanged(final Details details) {
2530 for (CallbackRecord<Callback> record : mCallbackRecords) {
2531 final Call call = this;
2532 final Callback callback = record.getCallback();
2533 record.getHandler().post(new Runnable() {
2534 @Override
2535 public void run() {
2536 callback.onDetailsChanged(call, details);
2537 }
2538 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002539 }
2540 }
2541
Andrew Lee011728f2015-04-23 15:47:06 -07002542 private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
2543 for (CallbackRecord<Callback> record : mCallbackRecords) {
2544 final Call call = this;
2545 final Callback callback = record.getCallback();
2546 record.getHandler().post(new Runnable() {
2547 @Override
2548 public void run() {
2549 callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
2550 }
2551 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002552 }
2553 }
2554
Andrew Lee011728f2015-04-23 15:47:06 -07002555 private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
2556 for (CallbackRecord<Callback> record : mCallbackRecords) {
2557 final Call call = this;
2558 final Callback callback = record.getCallback();
2559 record.getHandler().post(new Runnable() {
2560 @Override
2561 public void run() {
2562 callback.onVideoCallChanged(call, videoCall);
2563 }
2564 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002565 }
2566 }
2567
Andrew Lee011728f2015-04-23 15:47:06 -07002568 private void firePostDialWait(final String remainingPostDialSequence) {
2569 for (CallbackRecord<Callback> record : mCallbackRecords) {
2570 final Call call = this;
2571 final Callback callback = record.getCallback();
2572 record.getHandler().post(new Runnable() {
2573 @Override
2574 public void run() {
2575 callback.onPostDialWait(call, remainingPostDialSequence);
2576 }
2577 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002578 }
2579 }
2580
2581 private void fireCallDestroyed() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002582 /**
2583 * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
2584 * onCallRemoved callback, we remove this call from the Phone's record
2585 * only once all of the registered onCallDestroyed callbacks are executed.
2586 * All the callbacks get removed from our records as a part of this operation
2587 * since onCallDestroyed is the final callback.
2588 */
2589 final Call call = this;
2590 if (mCallbackRecords.isEmpty()) {
2591 // No callbacks registered, remove the call from Phone's record.
2592 mPhone.internalRemoveCall(call);
2593 }
2594 for (final CallbackRecord<Callback> record : mCallbackRecords) {
Andrew Lee011728f2015-04-23 15:47:06 -07002595 final Callback callback = record.getCallback();
2596 record.getHandler().post(new Runnable() {
2597 @Override
2598 public void run() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002599 boolean isFinalRemoval = false;
2600 RuntimeException toThrow = null;
2601 try {
2602 callback.onCallDestroyed(call);
2603 } catch (RuntimeException e) {
2604 toThrow = e;
2605 }
2606 synchronized(Call.this) {
2607 mCallbackRecords.remove(record);
2608 if (mCallbackRecords.isEmpty()) {
2609 isFinalRemoval = true;
2610 }
2611 }
2612 if (isFinalRemoval) {
2613 mPhone.internalRemoveCall(call);
2614 }
2615 if (toThrow != null) {
2616 throw toThrow;
2617 }
Andrew Lee011728f2015-04-23 15:47:06 -07002618 }
2619 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002620 }
2621 }
2622
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002623 private void fireConferenceableCallsChanged() {
Andrew Lee011728f2015-04-23 15:47:06 -07002624 for (CallbackRecord<Callback> record : mCallbackRecords) {
2625 final Call call = this;
2626 final Callback callback = record.getCallback();
2627 record.getHandler().post(new Runnable() {
2628 @Override
2629 public void run() {
2630 callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
2631 }
2632 });
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002633 }
2634 }
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002635
2636 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002637 * Notifies listeners of an incoming connection event.
2638 * <p>
2639 * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
2640 *
2641 * @param event
2642 * @param extras
2643 */
2644 private void fireOnConnectionEvent(final String event, final Bundle extras) {
2645 for (CallbackRecord<Callback> record : mCallbackRecords) {
2646 final Call call = this;
2647 final Callback callback = record.getCallback();
2648 record.getHandler().post(new Runnable() {
2649 @Override
2650 public void run() {
2651 callback.onConnectionEvent(call, event, extras);
2652 }
2653 });
2654 }
2655 }
2656
2657 /**
Hall Liu95d55872017-01-25 17:12:49 -08002658 * Notifies listeners of an RTT on/off change
2659 *
2660 * @param enabled True if RTT is now enabled, false otherwise
2661 */
2662 private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
2663 for (CallbackRecord<Callback> record : mCallbackRecords) {
2664 final Call call = this;
2665 final Callback callback = record.getCallback();
2666 record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
2667 }
2668 }
2669
2670 /**
2671 * Notifies listeners of a RTT mode change
2672 *
2673 * @param mode The new RTT mode
2674 */
2675 private void fireOnRttModeChanged(final int mode) {
2676 for (CallbackRecord<Callback> record : mCallbackRecords) {
2677 final Call call = this;
2678 final Callback callback = record.getCallback();
2679 record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
2680 }
2681 }
2682
2683 /**
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002684 * Determines if two bundles are equal.
2685 *
2686 * @param bundle The original bundle.
2687 * @param newBundle The bundle to compare with.
2688 * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
2689 */
2690 private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
2691 if (bundle == null || newBundle == null) {
2692 return bundle == newBundle;
2693 }
2694
2695 if (bundle.size() != newBundle.size()) {
2696 return false;
2697 }
2698
2699 for(String key : bundle.keySet()) {
2700 if (key != null) {
2701 final Object value = bundle.get(key);
2702 final Object newValue = newBundle.get(key);
2703 if (!Objects.equals(value, newValue)) {
2704 return false;
2705 }
2706 }
2707 }
2708 return true;
2709 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002710}