blob: c5fcf67c9be9f81adf31b1f2ded8b99f9784f174 [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.
2078 * For calls that are not generic conferences, or when the generic conference has more than
2079 * 2 children, returns {@code null}.
2080 * @see Details#PROPERTY_GENERIC_CONFERENCE
2081 * @return The active child call.
2082 */
2083 public @Nullable Call getGenericConferenceActiveChildCall() {
2084 if (mActiveGenericConferenceChild != null) {
2085 return mPhone.internalGetCallByTelecomId(mActiveGenericConferenceChild);
2086 }
2087 return null;
2088 }
2089
2090 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002091 * Obtains a list of canned, pre-configured message responses to present to the user as
2092 * ways of rejecting this {@code Call} using via a text message.
2093 *
2094 * @see #reject(boolean, String)
2095 *
2096 * @return A list of canned text message responses.
2097 */
2098 public List<String> getCannedTextResponses() {
2099 return mCannedTextResponses;
2100 }
2101
2102 /**
2103 * Obtains an object that can be used to display video from this {@code Call}.
2104 *
Andrew Lee50aca232014-07-22 16:41:54 -07002105 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -07002106 */
Andrew Lee50aca232014-07-22 16:41:54 -07002107 public InCallService.VideoCall getVideoCall() {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002108 return mVideoCallImpl;
Ihab Awade63fadb2014-07-09 21:52:04 -07002109 }
2110
2111 /**
2112 * Obtains an object containing call details.
2113 *
2114 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
2115 * result may be {@code null}.
2116 */
2117 public Details getDetails() {
2118 return mDetails;
2119 }
2120
2121 /**
Hall Liu95d55872017-01-25 17:12:49 -08002122 * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
2123 * receive RTT text data, as well as to change the RTT mode.
2124 * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
2125 */
2126 public @Nullable RttCall getRttCall() {
2127 return mRttCall;
2128 }
2129
2130 /**
2131 * Returns whether this call has an active RTT connection.
2132 * @return true if there is a connection, false otherwise.
2133 */
2134 public boolean isRttActive() {
Hall Liue9041242018-02-09 16:40:03 -08002135 return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
Hall Liu95d55872017-01-25 17:12:49 -08002136 }
2137
2138 /**
Andrew Leeda80c872015-04-15 14:09:50 -07002139 * Registers a callback to this {@code Call}.
2140 *
2141 * @param callback A {@code Callback}.
2142 */
2143 public void registerCallback(Callback callback) {
Andrew Lee011728f2015-04-23 15:47:06 -07002144 registerCallback(callback, new Handler());
2145 }
2146
2147 /**
2148 * Registers a callback to this {@code Call}.
2149 *
2150 * @param callback A {@code Callback}.
2151 * @param handler A handler which command and status changes will be delivered to.
2152 */
2153 public void registerCallback(Callback callback, Handler handler) {
2154 unregisterCallback(callback);
Roshan Pius1ca62072015-07-07 17:34:51 -07002155 // Don't allow new callback registration if the call is already being destroyed.
2156 if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002157 mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
2158 }
Andrew Leeda80c872015-04-15 14:09:50 -07002159 }
2160
2161 /**
2162 * Unregisters a callback from this {@code Call}.
2163 *
2164 * @param callback A {@code Callback}.
2165 */
2166 public void unregisterCallback(Callback callback) {
Roshan Pius1ca62072015-07-07 17:34:51 -07002167 // Don't allow callback deregistration if the call is already being destroyed.
2168 if (callback != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002169 for (CallbackRecord<Callback> record : mCallbackRecords) {
2170 if (record.getCallback() == callback) {
2171 mCallbackRecords.remove(record);
2172 break;
2173 }
2174 }
Andrew Leeda80c872015-04-15 14:09:50 -07002175 }
2176 }
2177
Santos Cordon3c20d632016-02-25 16:12:35 -08002178 @Override
2179 public String toString() {
2180 return new StringBuilder().
2181 append("Call [id: ").
2182 append(mTelecomCallId).
2183 append(", state: ").
2184 append(stateToString(mState)).
2185 append(", details: ").
2186 append(mDetails).
2187 append("]").toString();
2188 }
2189
2190 /**
2191 * @param state An integer value of a {@code STATE_*} constant.
2192 * @return A string representation of the value.
2193 */
2194 private static String stateToString(int state) {
2195 switch (state) {
2196 case STATE_NEW:
2197 return "NEW";
2198 case STATE_RINGING:
2199 return "RINGING";
2200 case STATE_DIALING:
2201 return "DIALING";
2202 case STATE_ACTIVE:
2203 return "ACTIVE";
2204 case STATE_HOLDING:
2205 return "HOLDING";
2206 case STATE_DISCONNECTED:
2207 return "DISCONNECTED";
2208 case STATE_CONNECTING:
2209 return "CONNECTING";
2210 case STATE_DISCONNECTING:
2211 return "DISCONNECTING";
2212 case STATE_SELECT_PHONE_ACCOUNT:
2213 return "SELECT_PHONE_ACCOUNT";
Hall Liu4e35b642019-10-14 17:50:45 -07002214 case STATE_SIMULATED_RINGING:
2215 return "SIMULATED_RINGING";
2216 case STATE_AUDIO_PROCESSING:
2217 return "AUDIO_PROCESSING";
Santos Cordon3c20d632016-02-25 16:12:35 -08002218 default:
2219 Log.w(Call.class, "Unknown state %d", state);
2220 return "UNKNOWN";
2221 }
2222 }
2223
Andrew Leeda80c872015-04-15 14:09:50 -07002224 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002225 * Adds a listener to this {@code Call}.
2226 *
2227 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002228 * @deprecated Use {@link #registerCallback} instead.
2229 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002230 */
Andrew Leeda80c872015-04-15 14:09:50 -07002231 @Deprecated
2232 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002233 public void addListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002234 registerCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002235 }
2236
2237 /**
2238 * Removes a listener from this {@code Call}.
2239 *
2240 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002241 * @deprecated Use {@link #unregisterCallback} instead.
2242 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002243 */
Andrew Leeda80c872015-04-15 14:09:50 -07002244 @Deprecated
2245 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002246 public void removeListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002247 unregisterCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002248 }
2249
2250 /** {@hide} */
Tyler Gunn159f35c2017-03-02 09:28:37 -08002251 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
2252 int targetSdkVersion) {
Ihab Awade63fadb2014-07-09 21:52:04 -07002253 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002254 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002255 mInCallAdapter = inCallAdapter;
2256 mState = STATE_NEW;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002257 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002258 mTargetSdkVersion = targetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07002259 }
2260
2261 /** {@hide} */
Tyler Gunnb88b3112016-11-09 10:19:23 -08002262 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
Tyler Gunn159f35c2017-03-02 09:28:37 -08002263 String callingPackage, int targetSdkVersion) {
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002264 mPhone = phone;
2265 mTelecomCallId = telecomCallId;
2266 mInCallAdapter = inCallAdapter;
2267 mState = state;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002268 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002269 mTargetSdkVersion = targetSdkVersion;
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002270 }
2271
2272 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002273 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002274 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002275 }
2276
2277 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002278 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Tyler Gunnb88b3112016-11-09 10:19:23 -08002279
Ihab Awade63fadb2014-07-09 21:52:04 -07002280 // First, we update the internal state as far as possible before firing any updates.
Sailesh Nepal1bef3392016-01-24 18:21:53 -08002281 Details details = Details.createFromParcelableCall(parcelableCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07002282 boolean detailsChanged = !Objects.equals(mDetails, details);
2283 if (detailsChanged) {
2284 mDetails = details;
2285 }
2286
2287 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -07002288 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
2289 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
2290 mCannedTextResponses =
2291 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Yorke Leee886f632015-08-04 13:43:31 -07002292 cannedTextResponsesChanged = true;
Ihab Awade63fadb2014-07-09 21:52:04 -07002293 }
2294
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002295 IVideoProvider previousVideoProvider = mVideoCallImpl == null ? null :
2296 mVideoCallImpl.getVideoProvider();
2297 IVideoProvider newVideoProvider = parcelableCall.getVideoProvider();
2298
2299 // parcelableCall.isVideoCallProviderChanged is only true when we have a video provider
2300 // specified; so we should check if the actual IVideoProvider changes as well.
2301 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged()
2302 && !Objects.equals(previousVideoProvider, newVideoProvider);
Andrew Lee50aca232014-07-22 16:41:54 -07002303 if (videoCallChanged) {
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002304 if (mVideoCallImpl != null) {
2305 mVideoCallImpl.destroy();
2306 }
2307 mVideoCallImpl = parcelableCall.isVideoCallProviderChanged() ?
2308 parcelableCall.getVideoCallImpl(mCallingPackage, mTargetSdkVersion) : null;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002309 }
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002310
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002311 if (mVideoCallImpl != null) {
2312 mVideoCallImpl.setVideoState(getDetails().getVideoState());
Ihab Awade63fadb2014-07-09 21:52:04 -07002313 }
2314
Santos Cordone3c507b2015-04-23 14:44:19 -07002315 int state = parcelableCall.getState();
Hall Liu31de23d2019-10-11 15:38:29 -07002316 if (mTargetSdkVersion < Phone.SDK_VERSION_R && state == Call.STATE_SIMULATED_RINGING) {
2317 state = Call.STATE_RINGING;
2318 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002319 boolean stateChanged = mState != state;
2320 if (stateChanged) {
2321 mState = state;
2322 }
2323
Santos Cordon823fd3c2014-08-07 18:35:18 -07002324 String parentId = parcelableCall.getParentCallId();
2325 boolean parentChanged = !Objects.equals(mParentId, parentId);
2326 if (parentChanged) {
2327 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002328 }
2329
Santos Cordon823fd3c2014-08-07 18:35:18 -07002330 List<String> childCallIds = parcelableCall.getChildCallIds();
2331 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
2332 if (childrenChanged) {
2333 mChildrenIds.clear();
2334 mChildrenIds.addAll(parcelableCall.getChildCallIds());
2335 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -07002336 }
2337
Hall Liuef98bf82020-01-09 15:22:44 -08002338 String activeChildCallId = parcelableCall.getActiveChildCallId();
2339 boolean activeChildChanged = !Objects.equals(activeChildCallId,
2340 mActiveGenericConferenceChild);
2341 if (activeChildChanged) {
2342 mActiveGenericConferenceChild = activeChildCallId;
2343 }
2344
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002345 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
2346 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
2347 for (String otherId : conferenceableCallIds) {
2348 if (callIdMap.containsKey(otherId)) {
2349 conferenceableCalls.add(callIdMap.get(otherId));
2350 }
2351 }
2352
2353 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
2354 mConferenceableCalls.clear();
2355 mConferenceableCalls.addAll(conferenceableCalls);
2356 fireConferenceableCallsChanged();
2357 }
2358
Hall Liu95d55872017-01-25 17:12:49 -08002359 boolean isRttChanged = false;
2360 boolean rttModeChanged = false;
Hall Liue9041242018-02-09 16:40:03 -08002361 if (parcelableCall.getIsRttCallChanged()
2362 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
Hall Liu95d55872017-01-25 17:12:49 -08002363 ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
2364 InputStreamReader receiveStream = new InputStreamReader(
2365 new ParcelFileDescriptor.AutoCloseInputStream(
2366 parcelableRttCall.getReceiveStream()),
2367 StandardCharsets.UTF_8);
2368 OutputStreamWriter transmitStream = new OutputStreamWriter(
2369 new ParcelFileDescriptor.AutoCloseOutputStream(
2370 parcelableRttCall.getTransmitStream()),
2371 StandardCharsets.UTF_8);
Hall Liu57006aa2017-02-06 10:49:48 -08002372 RttCall newRttCall = new Call.RttCall(mTelecomCallId,
Hall Liu95d55872017-01-25 17:12:49 -08002373 receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
2374 if (mRttCall == null) {
2375 isRttChanged = true;
2376 } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
2377 rttModeChanged = true;
2378 }
2379 mRttCall = newRttCall;
2380 } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
2381 && parcelableCall.getIsRttCallChanged()) {
2382 isRttChanged = true;
2383 mRttCall = null;
2384 }
2385
Ihab Awade63fadb2014-07-09 21:52:04 -07002386 // Now we fire updates, ensuring that any client who listens to any of these notifications
2387 // gets the most up-to-date state.
2388
2389 if (stateChanged) {
2390 fireStateChanged(mState);
2391 }
2392 if (detailsChanged) {
2393 fireDetailsChanged(mDetails);
2394 }
2395 if (cannedTextResponsesChanged) {
2396 fireCannedTextResponsesLoaded(mCannedTextResponses);
2397 }
Andrew Lee50aca232014-07-22 16:41:54 -07002398 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002399 fireVideoCallChanged(mVideoCallImpl);
Ihab Awade63fadb2014-07-09 21:52:04 -07002400 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002401 if (parentChanged) {
2402 fireParentChanged(getParent());
2403 }
Hall Liuef98bf82020-01-09 15:22:44 -08002404 if (childrenChanged || activeChildChanged) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002405 fireChildrenChanged(getChildren());
2406 }
Hall Liu95d55872017-01-25 17:12:49 -08002407 if (isRttChanged) {
2408 fireOnIsRttChanged(mRttCall != null, mRttCall);
2409 }
2410 if (rttModeChanged) {
2411 fireOnRttModeChanged(mRttCall.getRttAudioMode());
2412 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002413
2414 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
2415 // remove ourselves from the Phone. Note that we do this after completing all state updates
2416 // so a client can cleanly transition all their UI to the state appropriate for a
2417 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
2418 if (mState == STATE_DISCONNECTED) {
2419 fireCallDestroyed();
Ihab Awade63fadb2014-07-09 21:52:04 -07002420 }
2421 }
2422
2423 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002424 final void internalSetPostDialWait(String remaining) {
2425 mRemainingPostDialSequence = remaining;
2426 firePostDialWait(mRemainingPostDialSequence);
2427 }
2428
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07002429 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -07002430 final void internalSetDisconnected() {
2431 if (mState != Call.STATE_DISCONNECTED) {
2432 mState = Call.STATE_DISCONNECTED;
2433 fireStateChanged(mState);
2434 fireCallDestroyed();
Santos Cordonf30d7e92014-08-26 09:54:33 -07002435 }
2436 }
2437
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002438 /** {@hide} */
2439 final void internalOnConnectionEvent(String event, Bundle extras) {
2440 fireOnConnectionEvent(event, extras);
2441 }
2442
Hall Liu95d55872017-01-25 17:12:49 -08002443 /** {@hide} */
2444 final void internalOnRttUpgradeRequest(final int requestId) {
2445 for (CallbackRecord<Callback> record : mCallbackRecords) {
2446 final Call call = this;
2447 final Callback callback = record.getCallback();
2448 record.getHandler().post(() -> callback.onRttRequest(call, requestId));
2449 }
2450 }
2451
Hall Liu57006aa2017-02-06 10:49:48 -08002452 /** @hide */
2453 final void internalOnRttInitiationFailure(int reason) {
2454 for (CallbackRecord<Callback> record : mCallbackRecords) {
2455 final Call call = this;
2456 final Callback callback = record.getCallback();
2457 record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
2458 }
2459 }
2460
Sanket Padawe85291f62017-12-01 13:59:27 -08002461 /** {@hide} */
2462 final void internalOnHandoverFailed(int error) {
2463 for (CallbackRecord<Callback> record : mCallbackRecords) {
2464 final Call call = this;
2465 final Callback callback = record.getCallback();
2466 record.getHandler().post(() -> callback.onHandoverFailed(call, error));
2467 }
2468 }
2469
Tyler Gunn858bfaf2018-01-22 15:17:54 -08002470 /** {@hide} */
2471 final void internalOnHandoverComplete() {
2472 for (CallbackRecord<Callback> record : mCallbackRecords) {
2473 final Call call = this;
2474 final Callback callback = record.getCallback();
2475 record.getHandler().post(() -> callback.onHandoverComplete(call));
2476 }
2477 }
2478
Andrew Lee011728f2015-04-23 15:47:06 -07002479 private void fireStateChanged(final int newState) {
2480 for (CallbackRecord<Callback> record : mCallbackRecords) {
2481 final Call call = this;
2482 final Callback callback = record.getCallback();
2483 record.getHandler().post(new Runnable() {
2484 @Override
2485 public void run() {
2486 callback.onStateChanged(call, newState);
2487 }
2488 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002489 }
2490 }
2491
Andrew Lee011728f2015-04-23 15:47:06 -07002492 private void fireParentChanged(final Call newParent) {
2493 for (CallbackRecord<Callback> record : mCallbackRecords) {
2494 final Call call = this;
2495 final Callback callback = record.getCallback();
2496 record.getHandler().post(new Runnable() {
2497 @Override
2498 public void run() {
2499 callback.onParentChanged(call, newParent);
2500 }
2501 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002502 }
2503 }
2504
Andrew Lee011728f2015-04-23 15:47:06 -07002505 private void fireChildrenChanged(final List<Call> children) {
2506 for (CallbackRecord<Callback> record : mCallbackRecords) {
2507 final Call call = this;
2508 final Callback callback = record.getCallback();
2509 record.getHandler().post(new Runnable() {
2510 @Override
2511 public void run() {
2512 callback.onChildrenChanged(call, children);
2513 }
2514 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002515 }
2516 }
2517
Andrew Lee011728f2015-04-23 15:47:06 -07002518 private void fireDetailsChanged(final Details details) {
2519 for (CallbackRecord<Callback> record : mCallbackRecords) {
2520 final Call call = this;
2521 final Callback callback = record.getCallback();
2522 record.getHandler().post(new Runnable() {
2523 @Override
2524 public void run() {
2525 callback.onDetailsChanged(call, details);
2526 }
2527 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002528 }
2529 }
2530
Andrew Lee011728f2015-04-23 15:47:06 -07002531 private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
2532 for (CallbackRecord<Callback> record : mCallbackRecords) {
2533 final Call call = this;
2534 final Callback callback = record.getCallback();
2535 record.getHandler().post(new Runnable() {
2536 @Override
2537 public void run() {
2538 callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
2539 }
2540 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002541 }
2542 }
2543
Andrew Lee011728f2015-04-23 15:47:06 -07002544 private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
2545 for (CallbackRecord<Callback> record : mCallbackRecords) {
2546 final Call call = this;
2547 final Callback callback = record.getCallback();
2548 record.getHandler().post(new Runnable() {
2549 @Override
2550 public void run() {
2551 callback.onVideoCallChanged(call, videoCall);
2552 }
2553 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002554 }
2555 }
2556
Andrew Lee011728f2015-04-23 15:47:06 -07002557 private void firePostDialWait(final String remainingPostDialSequence) {
2558 for (CallbackRecord<Callback> record : mCallbackRecords) {
2559 final Call call = this;
2560 final Callback callback = record.getCallback();
2561 record.getHandler().post(new Runnable() {
2562 @Override
2563 public void run() {
2564 callback.onPostDialWait(call, remainingPostDialSequence);
2565 }
2566 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002567 }
2568 }
2569
2570 private void fireCallDestroyed() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002571 /**
2572 * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
2573 * onCallRemoved callback, we remove this call from the Phone's record
2574 * only once all of the registered onCallDestroyed callbacks are executed.
2575 * All the callbacks get removed from our records as a part of this operation
2576 * since onCallDestroyed is the final callback.
2577 */
2578 final Call call = this;
2579 if (mCallbackRecords.isEmpty()) {
2580 // No callbacks registered, remove the call from Phone's record.
2581 mPhone.internalRemoveCall(call);
2582 }
2583 for (final CallbackRecord<Callback> record : mCallbackRecords) {
Andrew Lee011728f2015-04-23 15:47:06 -07002584 final Callback callback = record.getCallback();
2585 record.getHandler().post(new Runnable() {
2586 @Override
2587 public void run() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002588 boolean isFinalRemoval = false;
2589 RuntimeException toThrow = null;
2590 try {
2591 callback.onCallDestroyed(call);
2592 } catch (RuntimeException e) {
2593 toThrow = e;
2594 }
2595 synchronized(Call.this) {
2596 mCallbackRecords.remove(record);
2597 if (mCallbackRecords.isEmpty()) {
2598 isFinalRemoval = true;
2599 }
2600 }
2601 if (isFinalRemoval) {
2602 mPhone.internalRemoveCall(call);
2603 }
2604 if (toThrow != null) {
2605 throw toThrow;
2606 }
Andrew Lee011728f2015-04-23 15:47:06 -07002607 }
2608 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002609 }
2610 }
2611
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002612 private void fireConferenceableCallsChanged() {
Andrew Lee011728f2015-04-23 15:47:06 -07002613 for (CallbackRecord<Callback> record : mCallbackRecords) {
2614 final Call call = this;
2615 final Callback callback = record.getCallback();
2616 record.getHandler().post(new Runnable() {
2617 @Override
2618 public void run() {
2619 callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
2620 }
2621 });
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002622 }
2623 }
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002624
2625 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002626 * Notifies listeners of an incoming connection event.
2627 * <p>
2628 * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
2629 *
2630 * @param event
2631 * @param extras
2632 */
2633 private void fireOnConnectionEvent(final String event, final Bundle extras) {
2634 for (CallbackRecord<Callback> record : mCallbackRecords) {
2635 final Call call = this;
2636 final Callback callback = record.getCallback();
2637 record.getHandler().post(new Runnable() {
2638 @Override
2639 public void run() {
2640 callback.onConnectionEvent(call, event, extras);
2641 }
2642 });
2643 }
2644 }
2645
2646 /**
Hall Liu95d55872017-01-25 17:12:49 -08002647 * Notifies listeners of an RTT on/off change
2648 *
2649 * @param enabled True if RTT is now enabled, false otherwise
2650 */
2651 private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
2652 for (CallbackRecord<Callback> record : mCallbackRecords) {
2653 final Call call = this;
2654 final Callback callback = record.getCallback();
2655 record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
2656 }
2657 }
2658
2659 /**
2660 * Notifies listeners of a RTT mode change
2661 *
2662 * @param mode The new RTT mode
2663 */
2664 private void fireOnRttModeChanged(final int mode) {
2665 for (CallbackRecord<Callback> record : mCallbackRecords) {
2666 final Call call = this;
2667 final Callback callback = record.getCallback();
2668 record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
2669 }
2670 }
2671
2672 /**
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002673 * Determines if two bundles are equal.
2674 *
2675 * @param bundle The original bundle.
2676 * @param newBundle The bundle to compare with.
2677 * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
2678 */
2679 private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
2680 if (bundle == null || newBundle == null) {
2681 return bundle == newBundle;
2682 }
2683
2684 if (bundle.size() != newBundle.size()) {
2685 return false;
2686 }
2687
2688 for(String key : bundle.keySet()) {
2689 if (key != null) {
2690 final Object value = bundle.get(key);
2691 final Object newValue = newBundle.get(key);
2692 if (!Objects.equals(value, newValue)) {
2693 return false;
2694 }
2695 }
2696 }
2697 return true;
2698 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002699}