blob: 826a89eb38bb5bd59e8c323aa4362746aa9cc3b4 [file] [log] [blame]
Ihab Awade63fadb2014-07-09 21:52:04 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tyler Gunnef9f6f92014-09-12 22:16:17 -070017package android.telecom;
Ihab Awade63fadb2014-07-09 21:52:04 -070018
Hall Liu95d55872017-01-25 17:12:49 -080019import android.annotation.IntDef;
20import android.annotation.Nullable;
Andrew Leeda80c872015-04-15 14:09:50 -070021import android.annotation.SystemApi;
Hall Liu6dfa2492019-10-01 17:20:39 -070022import android.annotation.TestApi;
Artur Satayev53ada2a2019-12-10 17:47:56 +000023import android.compat.annotation.UnsupportedAppUsage;
Ihab Awade63fadb2014-07-09 21:52:04 -070024import android.net.Uri;
Tyler Gunn6e3ecc42018-11-12 11:30:56 -080025import android.os.Build;
Nancy Chen10798dc2014-08-08 14:00:25 -070026import android.os.Bundle;
Andrew Lee011728f2015-04-23 15:47:06 -070027import android.os.Handler;
Hall Liu95d55872017-01-25 17:12:49 -080028import android.os.ParcelFileDescriptor;
Ihab Awade63fadb2014-07-09 21:52:04 -070029
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -080030import com.android.internal.telecom.IVideoProvider;
31
Hall Liu95d55872017-01-25 17:12:49 -080032import java.io.IOException;
33import java.io.InputStreamReader;
34import java.io.OutputStreamWriter;
Hall Liu95d55872017-01-25 17:12:49 -080035import java.lang.annotation.Retention;
36import java.lang.annotation.RetentionPolicy;
37import java.nio.charset.StandardCharsets;
Ihab Awade63fadb2014-07-09 21:52:04 -070038import java.util.ArrayList;
Tyler Gunn071be6f2016-05-10 14:52:33 -070039import java.util.Arrays;
Ihab Awade63fadb2014-07-09 21:52:04 -070040import java.util.Collections;
41import java.util.List;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070042import java.util.Map;
Ihab Awade63fadb2014-07-09 21:52:04 -070043import java.util.Objects;
Jay Shrauner229e3822014-08-15 09:23:07 -070044import java.util.concurrent.CopyOnWriteArrayList;
Ihab Awade63fadb2014-07-09 21:52:04 -070045
46/**
47 * Represents an ongoing phone call that the in-call app should present to the user.
48 */
49public final class Call {
50 /**
51 * The state of a {@code Call} when newly created.
52 */
53 public static final int STATE_NEW = 0;
54
55 /**
56 * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
57 */
58 public static final int STATE_DIALING = 1;
59
60 /**
61 * The state of an incoming {@code Call} when ringing locally, but not yet connected.
62 */
63 public static final int STATE_RINGING = 2;
64
65 /**
66 * The state of a {@code Call} when in a holding state.
67 */
68 public static final int STATE_HOLDING = 3;
69
70 /**
71 * The state of a {@code Call} when actively supporting conversation.
72 */
73 public static final int STATE_ACTIVE = 4;
74
75 /**
76 * The state of a {@code Call} when no further voice or other communication is being
77 * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
78 * is no longer active, and the local data transport has or inevitably will release resources
79 * associated with this {@code Call}.
80 */
81 public static final int STATE_DISCONNECTED = 7;
82
Nancy Chen5da0fd52014-07-08 14:16:17 -070083 /**
Santos Cordone3c507b2015-04-23 14:44:19 -070084 * The state of an outgoing {@code Call} when waiting on user to select a
85 * {@link PhoneAccount} through which to place the call.
Nancy Chen5da0fd52014-07-08 14:16:17 -070086 */
Santos Cordone3c507b2015-04-23 14:44:19 -070087 public static final int STATE_SELECT_PHONE_ACCOUNT = 8;
88
89 /**
90 * @hide
91 * @deprecated use STATE_SELECT_PHONE_ACCOUNT.
92 */
93 @Deprecated
94 @SystemApi
95 public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT;
Nancy Chen5da0fd52014-07-08 14:16:17 -070096
Nancy Chene20930f2014-08-07 16:17:21 -070097 /**
Nancy Chene9b7a8e2014-08-08 14:26:27 -070098 * The initial state of an outgoing {@code Call}.
99 * Common transitions are to {@link #STATE_DIALING} state for a successful call or
100 * {@link #STATE_DISCONNECTED} if it failed.
Nancy Chene20930f2014-08-07 16:17:21 -0700101 */
102 public static final int STATE_CONNECTING = 9;
103
Nancy Chen513c8922014-09-17 14:47:20 -0700104 /**
Tyler Gunn4afc6af2014-10-07 10:14:55 -0700105 * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
106 * call has not yet been disconnected by the underlying {@code ConnectionService}. The next
107 * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
108 */
109 public static final int STATE_DISCONNECTING = 10;
110
111 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700112 * The state of an external call which is in the process of being pulled from a remote device to
113 * the local device.
114 * <p>
115 * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
116 * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
117 * <p>
118 * An {@link InCallService} will only see this state if it has the
119 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
120 * manifest.
121 */
122 public static final int STATE_PULLING_CALL = 11;
123
124 /**
Hall Liu6dfa2492019-10-01 17:20:39 -0700125 * The state of a call that is active with the network, but the audio from the call is
126 * being intercepted by an app on the local device. Telecom does not hold audio focus in this
127 * state, and the call will be invisible to the user except for a persistent notification.
128 */
129 public static final int STATE_AUDIO_PROCESSING = 12;
130
131 /**
132 * The state of a call that is being presented to the user after being in
133 * {@link #STATE_AUDIO_PROCESSING}. The call is still active with the network in this case, and
134 * Telecom will hold audio focus and play a ringtone if appropriate.
135 */
136 public static final int STATE_SIMULATED_RINGING = 13;
137
138 /**
Nancy Chen513c8922014-09-17 14:47:20 -0700139 * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
140 * extras. Used to pass the phone accounts to display on the front end to the user in order to
141 * select phone accounts to (for example) place a call.
Hall Liu34d9e242018-11-21 17:05:58 -0800142 * @deprecated Use the list from {@link #EXTRA_SUGGESTED_PHONE_ACCOUNTS} instead.
Nancy Chen513c8922014-09-17 14:47:20 -0700143 */
Hall Liu34d9e242018-11-21 17:05:58 -0800144 @Deprecated
Nancy Chen513c8922014-09-17 14:47:20 -0700145 public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
146
mike dooley4af561f2016-12-20 08:55:17 -0800147 /**
Hall Liu34d9e242018-11-21 17:05:58 -0800148 * Key for extra used to pass along a list of {@link PhoneAccountSuggestion}s to the in-call
149 * UI when a call enters the {@link #STATE_SELECT_PHONE_ACCOUNT} state. The list included here
150 * will have the same length and be in the same order as the list passed with
151 * {@link #AVAILABLE_PHONE_ACCOUNTS}.
152 */
153 public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS =
154 "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS";
155
156 /**
mike dooley91217422017-03-09 12:58:42 -0800157 * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC)
158 * when the last outgoing emergency call was made. This is used to identify potential emergency
159 * callbacks.
mike dooley4af561f2016-12-20 08:55:17 -0800160 */
161 public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
162 "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
163
Usman Abdullahb0dc29a2019-03-06 15:54:56 -0800164
165 /**
166 * Extra key used to indicate whether a {@link CallScreeningService} has requested to silence
167 * the ringtone for a call. If the {@link InCallService} declares
168 * {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} in its manifest, it should not
169 * play a ringtone for an incoming call with this extra key set.
170 */
171 public static final String EXTRA_SILENT_RINGING_REQUESTED =
172 "android.telecom.extra.SILENT_RINGING_REQUESTED";
173
Tyler Gunn8bf76572017-04-06 15:30:08 -0700174 /**
175 * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
176 * Telecom that the user has requested that the current {@link Call} should be handed over
177 * to another {@link ConnectionService}.
178 * <p>
179 * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
180 * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
181 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700182 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
183 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700184 */
185 public static final String EVENT_REQUEST_HANDOVER =
186 "android.telecom.event.REQUEST_HANDOVER";
187
188 /**
189 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
190 * {@link PhoneAccountHandle} to which a call should be handed over to.
191 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700192 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
193 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700194 */
195 public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
196 "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
197
198 /**
199 * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
200 * video state of the call when it is handed over to the new {@link PhoneAccount}.
201 * <p>
202 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
203 * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
204 * {@link VideoProfile#STATE_TX_ENABLED}.
205 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700206 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
207 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700208 */
209 public static final String EXTRA_HANDOVER_VIDEO_STATE =
210 "android.telecom.extra.HANDOVER_VIDEO_STATE";
211
212 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700213 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Used by the
214 * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra
215 * information to the handover {@link ConnectionService} specified by
216 * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}.
217 * <p>
218 * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the
219 * {@link ConnectionService} via the request extras when
220 * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
221 * is called to initate the handover.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700222 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700223 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
224 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700225 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700226 public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700227
228 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700229 * Call event sent from Telecom to the handover {@link ConnectionService} via
230 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
231 * to the {@link ConnectionService} has completed successfully.
232 * <p>
233 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700234 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700235 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
236 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700237 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700238 public static final String EVENT_HANDOVER_COMPLETE =
239 "android.telecom.event.HANDOVER_COMPLETE";
Tyler Gunn34a2b312017-06-23 08:32:00 -0700240
241 /**
242 * Call event sent from Telecom to the handover destination {@link ConnectionService} via
243 * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the
244 * source connection has disconnected. The {@link Bundle} parameter for the call event will be
245 * {@code null}.
246 * <p>
247 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
248 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700249 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
250 * APIs instead.
Tyler Gunn34a2b312017-06-23 08:32:00 -0700251 */
252 public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
253 "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
254
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700255 /**
256 * Call event sent from Telecom to the handover {@link ConnectionService} via
257 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
258 * to the {@link ConnectionService} has failed.
259 * <p>
260 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
261 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700262 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
263 * APIs instead.
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700264 */
265 public static final String EVENT_HANDOVER_FAILED =
266 "android.telecom.event.HANDOVER_FAILED";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700267
Ihab Awade63fadb2014-07-09 21:52:04 -0700268 public static class Details {
Tyler Gunn94f8f112018-12-17 09:56:11 -0800269 /** @hide */
270 @Retention(RetentionPolicy.SOURCE)
271 @IntDef(
272 prefix = { "DIRECTION_" },
273 value = {DIRECTION_UNKNOWN, DIRECTION_INCOMING, DIRECTION_OUTGOING})
274 public @interface CallDirection {}
275
276 /**
277 * Indicates that the call is neither and incoming nor an outgoing call. This can be the
278 * case for calls reported directly by a {@link ConnectionService} in special cases such as
279 * call handovers.
280 */
281 public static final int DIRECTION_UNKNOWN = -1;
282
283 /**
284 * Indicates that the call is an incoming call.
285 */
286 public static final int DIRECTION_INCOMING = 0;
287
288 /**
289 * Indicates that the call is an outgoing call.
290 */
291 public static final int DIRECTION_OUTGOING = 1;
292
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800293 /** Call can currently be put on hold or unheld. */
294 public static final int CAPABILITY_HOLD = 0x00000001;
295
296 /** Call supports the hold feature. */
297 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
298
299 /**
300 * Calls within a conference can be merged. A {@link ConnectionService} has the option to
301 * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
302 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
303 * capability allows a merge button to be shown while the conference call is in the foreground
304 * of the in-call UI.
305 * <p>
306 * This is only intended for use by a {@link Conference}.
307 */
308 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
309
310 /**
311 * Calls within a conference can be swapped between foreground and background.
312 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
313 * <p>
314 * This is only intended for use by a {@link Conference}.
315 */
316 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
317
318 /**
319 * @hide
320 */
Andrew Lee2378ea72015-04-29 14:38:11 -0700321 public static final int CAPABILITY_UNUSED_1 = 0x00000010;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800322
323 /** Call supports responding via text option. */
324 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
325
326 /** Call can be muted. */
327 public static final int CAPABILITY_MUTE = 0x00000040;
328
329 /**
330 * Call supports conference call management. This capability only applies to {@link Conference}
331 * calls which can have {@link Connection}s as children.
332 */
333 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
334
335 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700336 * Local device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800337 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700338 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800339
340 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700341 * Local device supports transmitting video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800342 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700343 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800344
345 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700346 * Local device supports bidirectional video calling.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800347 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700348 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700349 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800350
351 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700352 * Remote device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800353 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700354 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
355
356 /**
357 * Remote device supports transmitting video.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700358 */
359 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
360
361 /**
362 * Remote device supports bidirectional video calling.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700363 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700364 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700365 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800366
367 /**
368 * Call is able to be separated from its parent {@code Conference}, if any.
369 */
370 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
371
372 /**
373 * Call is able to be individually disconnected when in a {@code Conference}.
374 */
375 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
376
377 /**
Dong Zhou89f41eb2015-03-15 11:59:49 -0500378 * Speed up audio setup for MT call.
379 * @hide
380 */
Tyler Gunn96d6c402015-03-18 12:39:23 -0700381 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
382
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700383 /**
384 * Call can be upgraded to a video call.
Rekha Kumar07366812015-03-24 16:42:31 -0700385 * @hide
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800386 * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
387 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call
388 * whether or not video calling is supported.
Rekha Kumar07366812015-03-24 16:42:31 -0700389 */
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800390 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
Rekha Kumar07366812015-03-24 16:42:31 -0700391 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
392
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700393 /**
394 * For video calls, indicates whether the outgoing video for the call can be paused using
Yorke Lee32f24732015-05-12 16:18:03 -0700395 * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700396 */
397 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
398
Bryce Lee81901682015-08-28 16:38:02 -0700399 /**
400 * Call sends responses through connection.
401 * @hide
402 */
Tyler Gunnf97a0092016-01-19 15:59:34 -0800403 public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;
404
405 /**
406 * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
407 * <p>
408 * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
409 * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
410 * downgraded from a video call back to a VideoState of
411 * {@link VideoProfile#STATE_AUDIO_ONLY}.
412 * <p>
413 * Intuitively, a call which can be downgraded to audio should also have local and remote
414 * video
415 * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
416 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
417 */
418 public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
Bryce Lee81901682015-08-28 16:38:02 -0700419
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700420 /**
421 * When set for an external call, indicates that this {@code Call} can be pulled from a
422 * remote device to the current device.
423 * <p>
424 * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
425 * <p>
426 * An {@link InCallService} will only see calls with this capability if it has the
427 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
428 * in its manifest.
429 * <p>
430 * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
Tyler Gunn720c6642016-03-22 09:02:47 -0700431 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700432 */
433 public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
434
Pooja Jaind34698d2017-12-28 14:15:31 +0530435 /** Call supports the deflect feature. */
436 public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
437
Tyler Gunnd11a3152015-03-18 13:09:14 -0700438 //******************************************************************************************
Pooja Jaind34698d2017-12-28 14:15:31 +0530439 // Next CAPABILITY value: 0x02000000
Andrew Lee2378ea72015-04-29 14:38:11 -0700440 //******************************************************************************************
441
442 /**
443 * Whether the call is currently a conference.
444 */
445 public static final int PROPERTY_CONFERENCE = 0x00000001;
446
447 /**
448 * Whether the call is a generic conference, where we do not know the precise state of
449 * participants in the conference (eg. on CDMA).
450 */
451 public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
452
453 /**
454 * Whether the call is made while the device is in emergency callback mode.
455 */
456 public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
457
458 /**
459 * Connection is using WIFI.
460 */
461 public static final int PROPERTY_WIFI = 0x00000008;
462
463 /**
Tyler Gunn6b6ae552018-10-11 10:42:10 -0700464 * When set, the UI should indicate to the user that a call is using high definition
465 * audio.
466 * <p>
467 * The underlying {@link ConnectionService} is responsible for reporting this
468 * property. It is important to note that this property is not intended to report the
469 * actual audio codec being used for a Call, but whether the call should be indicated
470 * to the user as high definition.
471 * <p>
472 * The Android Telephony stack reports this property for calls based on a number
473 * of factors, including which audio codec is used and whether a call is using an HD
474 * codec end-to-end. Some mobile operators choose to suppress display of an HD indication,
475 * and in these cases this property will not be set for a call even if the underlying audio
476 * codec is in fact "high definition".
Andrew Lee2378ea72015-04-29 14:38:11 -0700477 */
478 public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
479
Tony Maka68dcce2015-12-17 09:31:18 +0000480 /**
Tony Mak53b5df42016-05-19 13:40:38 +0100481 * Whether the call is associated with the work profile.
482 */
483 public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;
484
485 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700486 * When set, indicates that this {@code Call} does not actually exist locally for the
487 * {@link ConnectionService}.
488 * <p>
489 * Consider, for example, a scenario where a user has two phones with the same phone number.
490 * When a user places a call on one device, the telephony stack can represent that call on
491 * the other device by adding it to the {@link ConnectionService} with the
Tyler Gunn720c6642016-03-22 09:02:47 -0700492 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700493 * <p>
494 * An {@link InCallService} will only see calls with this property if it has the
495 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
496 * in its manifest.
497 * <p>
Tyler Gunn720c6642016-03-22 09:02:47 -0700498 * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700499 */
500 public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
501
Brad Ebinger15847072016-05-18 11:08:36 -0700502 /**
503 * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
504 */
505 public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
506
Tyler Gunn24e18332017-02-10 09:42:49 -0800507 /**
508 * Indicates that the call is from a self-managed {@link ConnectionService}.
509 * <p>
510 * See also {@link Connection#PROPERTY_SELF_MANAGED}
511 */
512 public static final int PROPERTY_SELF_MANAGED = 0x00000100;
513
Eric Erfanianec881872017-12-06 16:27:53 -0800514 /**
515 * Indicates the call used Assisted Dialing.
Tyler Gunn5567d742019-10-31 13:04:37 -0700516 *
517 * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING
Eric Erfanianec881872017-12-06 16:27:53 -0800518 */
519 public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200;
520
Hall Liue9041242018-02-09 16:40:03 -0800521 /**
522 * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
523 * {@link RttCall} object that is used to send and receive text.
524 */
525 public static final int PROPERTY_RTT = 0x00000400;
526
Tyler Gunn5bd90852018-09-21 09:37:07 -0700527 /**
528 * Indicates that the call has been identified as the network as an emergency call. This
529 * property may be set for both incoming and outgoing calls which the network identifies as
530 * emergency calls.
531 */
532 public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 0x00000800;
533
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700534 /**
535 * Indicates that the call is using VoIP audio mode.
536 * <p>
537 * When this property is set, the {@link android.media.AudioManager} audio mode for this
538 * call will be {@link android.media.AudioManager#MODE_IN_COMMUNICATION}. When this
539 * property is not set, the audio mode for this call will be
540 * {@link android.media.AudioManager#MODE_IN_CALL}.
541 * <p>
542 * This property reflects changes made using {@link Connection#setAudioModeIsVoip(boolean)}.
543 * <p>
544 * You can use this property to determine whether an un-answered incoming call or a held
545 * call will use VoIP audio mode (if the call does not currently have focus, the system
546 * audio mode may not reflect the mode the call will use).
547 */
548 public static final int PROPERTY_VOIP_AUDIO_MODE = 0x00001000;
549
Andrew Lee2378ea72015-04-29 14:38:11 -0700550 //******************************************************************************************
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700551 // Next PROPERTY value: 0x00002000
Tyler Gunnd11a3152015-03-18 13:09:14 -0700552 //******************************************************************************************
Tyler Gunn068085b2015-02-06 13:56:52 -0800553
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800554 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700555 private final Uri mHandle;
556 private final int mHandlePresentation;
557 private final String mCallerDisplayName;
558 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700559 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700560 private final int mCallCapabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700561 private final int mCallProperties;
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800562 private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700563 private final DisconnectCause mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700564 private final long mConnectTimeMillis;
565 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700566 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700567 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700568 private final Bundle mExtras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700569 private final Bundle mIntentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700570 private final long mCreationTimeMillis;
Hall Liuef98bf82020-01-09 15:22:44 -0800571 private final String mContactDisplayName;
Tyler Gunn94f8f112018-12-17 09:56:11 -0800572 private final @CallDirection int mCallDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700573 private final @Connection.VerificationStatus int mCallerNumberVerificationStatus;
Ihab Awade63fadb2014-07-09 21:52:04 -0700574
575 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800576 * Whether the supplied capabilities supports the specified capability.
577 *
578 * @param capabilities A bit field of capabilities.
579 * @param capability The capability to check capabilities for.
580 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800581 */
582 public static boolean can(int capabilities, int capability) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800583 return (capabilities & capability) == capability;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800584 }
585
586 /**
587 * Whether the capabilities of this {@code Details} supports the specified capability.
588 *
589 * @param capability The capability to check capabilities for.
590 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800591 */
592 public boolean can(int capability) {
593 return can(mCallCapabilities, capability);
594 }
595
596 /**
597 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
598 *
599 * @param capabilities A capability bit field.
600 * @return A human readable string representation.
601 */
602 public static String capabilitiesToString(int capabilities) {
603 StringBuilder builder = new StringBuilder();
604 builder.append("[Capabilities:");
605 if (can(capabilities, CAPABILITY_HOLD)) {
606 builder.append(" CAPABILITY_HOLD");
607 }
608 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
609 builder.append(" CAPABILITY_SUPPORT_HOLD");
610 }
611 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
612 builder.append(" CAPABILITY_MERGE_CONFERENCE");
613 }
614 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
615 builder.append(" CAPABILITY_SWAP_CONFERENCE");
616 }
617 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
618 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
619 }
620 if (can(capabilities, CAPABILITY_MUTE)) {
621 builder.append(" CAPABILITY_MUTE");
622 }
623 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
624 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
625 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700626 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
627 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
628 }
629 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
630 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
631 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700632 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
633 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800634 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700635 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
636 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
637 }
638 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
639 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
640 }
Tyler Gunnf97a0092016-01-19 15:59:34 -0800641 if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
642 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
643 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700644 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
645 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800646 }
Dong Zhou89f41eb2015-03-15 11:59:49 -0500647 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
Tyler Gunnd11a3152015-03-18 13:09:14 -0700648 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
Dong Zhou89f41eb2015-03-15 11:59:49 -0500649 }
Rekha Kumar07366812015-03-24 16:42:31 -0700650 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
651 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
652 }
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700653 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
654 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
655 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700656 if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
657 builder.append(" CAPABILITY_CAN_PULL_CALL");
658 }
Pooja Jaind34698d2017-12-28 14:15:31 +0530659 if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
660 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
661 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800662 builder.append("]");
663 return builder.toString();
664 }
665
666 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700667 * Whether the supplied properties includes the specified property.
668 *
669 * @param properties A bit field of properties.
670 * @param property The property to check properties for.
671 * @return Whether the specified property is supported.
672 */
673 public static boolean hasProperty(int properties, int property) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800674 return (properties & property) == property;
Andrew Lee2378ea72015-04-29 14:38:11 -0700675 }
676
677 /**
678 * Whether the properties of this {@code Details} includes the specified property.
679 *
680 * @param property The property to check properties for.
681 * @return Whether the specified property is supported.
682 */
683 public boolean hasProperty(int property) {
684 return hasProperty(mCallProperties, property);
685 }
686
687 /**
688 * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
689 *
690 * @param properties A property bit field.
691 * @return A human readable string representation.
692 */
693 public static String propertiesToString(int properties) {
694 StringBuilder builder = new StringBuilder();
695 builder.append("[Properties:");
696 if (hasProperty(properties, PROPERTY_CONFERENCE)) {
697 builder.append(" PROPERTY_CONFERENCE");
698 }
699 if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
700 builder.append(" PROPERTY_GENERIC_CONFERENCE");
701 }
702 if (hasProperty(properties, PROPERTY_WIFI)) {
703 builder.append(" PROPERTY_WIFI");
704 }
705 if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
706 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
707 }
708 if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
Yorke Leebe2a4a22015-06-12 10:10:55 -0700709 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
Andrew Lee2378ea72015-04-29 14:38:11 -0700710 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700711 if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
712 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
713 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700714 if (hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
Brad Ebinger15847072016-05-18 11:08:36 -0700715 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
716 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700717 if (hasProperty(properties, PROPERTY_ASSISTED_DIALING_USED)) {
Eric Erfanianec881872017-12-06 16:27:53 -0800718 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
719 }
Tyler Gunn5bd90852018-09-21 09:37:07 -0700720 if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
721 builder.append(" PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL");
722 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700723 if (hasProperty(properties, PROPERTY_RTT)) {
724 builder.append(" PROPERTY_RTT");
725 }
726 if (hasProperty(properties, PROPERTY_VOIP_AUDIO_MODE)) {
727 builder.append(" PROPERTY_VOIP_AUDIO_MODE");
728 }
Andrew Lee2378ea72015-04-29 14:38:11 -0700729 builder.append("]");
730 return builder.toString();
731 }
732
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800733 /** {@hide} */
Hall Liu31de23d2019-10-11 15:38:29 -0700734 @TestApi
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800735 public String getTelecomCallId() {
736 return mTelecomCallId;
737 }
738
Andrew Lee2378ea72015-04-29 14:38:11 -0700739 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700740 * @return The handle (e.g., phone number) to which the {@code Call} is currently
741 * connected.
742 */
743 public Uri getHandle() {
744 return mHandle;
745 }
746
747 /**
748 * @return The presentation requirements for the handle. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700749 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700750 */
751 public int getHandlePresentation() {
752 return mHandlePresentation;
753 }
754
755 /**
Tyler Gunnd081f042018-12-04 12:56:45 -0800756 * The display name for the caller.
757 * <p>
758 * This is the name as reported by the {@link ConnectionService} associated with this call.
Tyler Gunnd081f042018-12-04 12:56:45 -0800759 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700760 * @return The display name for the caller.
761 */
762 public String getCallerDisplayName() {
763 return mCallerDisplayName;
764 }
765
766 /**
767 * @return The presentation requirements for the caller display name. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700768 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700769 */
770 public int getCallerDisplayNamePresentation() {
771 return mCallerDisplayNamePresentation;
772 }
773
774 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700775 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
776 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700777 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700778 public PhoneAccountHandle getAccountHandle() {
779 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -0700780 }
781
782 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800783 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
784 * {@code CAPABILITY_*} constants in this class.
Ihab Awade63fadb2014-07-09 21:52:04 -0700785 */
Ihab Awad5d0410f2014-07-30 10:07:40 -0700786 public int getCallCapabilities() {
787 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700788 }
789
790 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700791 * @return A bitmask of the properties of the {@code Call}, as defined by the various
792 * {@code PROPERTY_*} constants in this class.
Andrew Lee223ad142014-08-27 16:33:08 -0700793 */
794 public int getCallProperties() {
795 return mCallProperties;
796 }
797
798 /**
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800799 * @return a bitmask of the audio routes available for the call.
800 *
801 * @hide
802 */
803 public int getSupportedAudioRoutes() {
804 return mSupportedAudioRoutes;
805 }
806
807 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700808 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
Nancy Chenf4cf77c2014-09-19 10:53:21 -0700809 * by {@link android.telecom.DisconnectCause}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700810 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700811 public DisconnectCause getDisconnectCause() {
812 return mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700813 }
814
815 /**
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700816 * Returns the time the {@link Call} connected (i.e. became active). This information is
817 * updated periodically, but user interfaces should not rely on this to display the "call
818 * time clock". For the time when the call was first added to Telecom, see
819 * {@link #getCreationTimeMillis()}.
820 *
821 * @return The time the {@link Call} connected in milliseconds since the epoch.
Ihab Awade63fadb2014-07-09 21:52:04 -0700822 */
Jay Shrauner164a0ac2015-04-14 18:16:10 -0700823 public final long getConnectTimeMillis() {
Ihab Awade63fadb2014-07-09 21:52:04 -0700824 return mConnectTimeMillis;
825 }
826
827 /**
828 * @return Information about any calling gateway the {@code Call} may be using.
829 */
830 public GatewayInfo getGatewayInfo() {
831 return mGatewayInfo;
832 }
833
Andrew Lee7a341382014-07-15 17:05:08 -0700834 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -0700835 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -0700836 */
837 public int getVideoState() {
838 return mVideoState;
839 }
840
Ihab Awad5d0410f2014-07-30 10:07:40 -0700841 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700842 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
Ihab Awad5d0410f2014-07-30 10:07:40 -0700843 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -0700844 */
845 public StatusHints getStatusHints() {
846 return mStatusHints;
847 }
848
Nancy Chen10798dc2014-08-08 14:00:25 -0700849 /**
Santos Cordon6b7f9552015-05-27 17:21:45 -0700850 * @return The extras associated with this call.
Nancy Chen10798dc2014-08-08 14:00:25 -0700851 */
852 public Bundle getExtras() {
853 return mExtras;
854 }
855
Santos Cordon6b7f9552015-05-27 17:21:45 -0700856 /**
857 * @return The extras used with the original intent to place this call.
858 */
859 public Bundle getIntentExtras() {
860 return mIntentExtras;
861 }
862
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700863 /**
864 * Returns the time when the call was first created and added to Telecom. This is the same
865 * time that is logged as the start time in the Call Log (see
866 * {@link android.provider.CallLog.Calls#DATE}). To determine when the call was connected
867 * (became active), see {@link #getConnectTimeMillis()}.
868 *
869 * @return The creation time of the call, in millis since the epoch.
870 */
871 public long getCreationTimeMillis() {
872 return mCreationTimeMillis;
873 }
874
Tyler Gunnd081f042018-12-04 12:56:45 -0800875 /**
Hall Liuef98bf82020-01-09 15:22:44 -0800876 * Returns the name of the caller on the remote end, as derived from a
877 * {@link android.provider.ContactsContract} lookup of the call's handle.
878 * @return The name of the caller, or {@code null} if the lookup is not yet complete, if
879 * there's no contacts entry for the caller, or if the {@link InCallService} does
880 * not hold the {@link android.Manifest.permission#READ_CONTACTS} permission.
881 */
882 public @Nullable String getContactDisplayName() {
883 return mContactDisplayName;
884 }
885
886 /**
Tyler Gunn94f8f112018-12-17 09:56:11 -0800887 * Indicates whether the call is an incoming or outgoing call.
888 * @return The call's direction.
889 */
890 public @CallDirection int getCallDirection() {
891 return mCallDirection;
892 }
893
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700894 /**
895 * Gets the verification status for the phone number of an incoming call as identified in
896 * ATIS-1000082.
897 * @return the verification status.
898 */
899 public @Connection.VerificationStatus int getCallerNumberVerificationStatus() {
900 return mCallerNumberVerificationStatus;
901 }
902
Ihab Awade63fadb2014-07-09 21:52:04 -0700903 @Override
904 public boolean equals(Object o) {
905 if (o instanceof Details) {
906 Details d = (Details) o;
907 return
908 Objects.equals(mHandle, d.mHandle) &&
909 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
910 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
911 Objects.equals(mCallerDisplayNamePresentation,
912 d.mCallerDisplayNamePresentation) &&
Evan Charlton8c8a0622014-07-20 12:31:00 -0700913 Objects.equals(mAccountHandle, d.mAccountHandle) &&
Ihab Awad5d0410f2014-07-30 10:07:40 -0700914 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Andrew Lee223ad142014-08-27 16:33:08 -0700915 Objects.equals(mCallProperties, d.mCallProperties) &&
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700916 Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
Ihab Awade63fadb2014-07-09 21:52:04 -0700917 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Andrew Lee85f5d422014-07-11 17:22:03 -0700918 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Evan Charlton5b49ade2014-07-15 17:03:20 -0700919 Objects.equals(mVideoState, d.mVideoState) &&
Nancy Chen10798dc2014-08-08 14:00:25 -0700920 Objects.equals(mStatusHints, d.mStatusHints) &&
Tyler Gunn1e9bfc62015-08-19 11:18:58 -0700921 areBundlesEqual(mExtras, d.mExtras) &&
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700922 areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
Tyler Gunnd081f042018-12-04 12:56:45 -0800923 Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis) &&
Hall Liuef98bf82020-01-09 15:22:44 -0800924 Objects.equals(mContactDisplayName, d.mContactDisplayName) &&
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700925 Objects.equals(mCallDirection, d.mCallDirection) &&
926 Objects.equals(mCallerNumberVerificationStatus,
927 d.mCallerNumberVerificationStatus);
Ihab Awade63fadb2014-07-09 21:52:04 -0700928 }
929 return false;
930 }
931
932 @Override
933 public int hashCode() {
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700934 return Objects.hash(mHandle,
935 mHandlePresentation,
936 mCallerDisplayName,
937 mCallerDisplayNamePresentation,
938 mAccountHandle,
939 mCallCapabilities,
940 mCallProperties,
941 mDisconnectCause,
942 mConnectTimeMillis,
943 mGatewayInfo,
944 mVideoState,
945 mStatusHints,
946 mExtras,
947 mIntentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -0800948 mCreationTimeMillis,
Hall Liuef98bf82020-01-09 15:22:44 -0800949 mContactDisplayName,
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700950 mCallDirection,
951 mCallerNumberVerificationStatus);
Ihab Awade63fadb2014-07-09 21:52:04 -0700952 }
953
954 /** {@hide} */
955 public Details(
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800956 String telecomCallId,
Ihab Awade63fadb2014-07-09 21:52:04 -0700957 Uri handle,
958 int handlePresentation,
959 String callerDisplayName,
960 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -0700961 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -0700962 int capabilities,
Andrew Lee223ad142014-08-27 16:33:08 -0700963 int properties,
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700964 DisconnectCause disconnectCause,
Ihab Awade63fadb2014-07-09 21:52:04 -0700965 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -0700966 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -0700967 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -0700968 StatusHints statusHints,
Santos Cordon6b7f9552015-05-27 17:21:45 -0700969 Bundle extras,
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700970 Bundle intentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -0800971 long creationTimeMillis,
Hall Liuef98bf82020-01-09 15:22:44 -0800972 String contactDisplayName,
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700973 int callDirection,
974 int callerNumberVerificationStatus) {
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800975 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700976 mHandle = handle;
977 mHandlePresentation = handlePresentation;
978 mCallerDisplayName = callerDisplayName;
979 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700980 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700981 mCallCapabilities = capabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700982 mCallProperties = properties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700983 mDisconnectCause = disconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700984 mConnectTimeMillis = connectTimeMillis;
985 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700986 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700987 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700988 mExtras = extras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700989 mIntentExtras = intentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700990 mCreationTimeMillis = creationTimeMillis;
Hall Liuef98bf82020-01-09 15:22:44 -0800991 mContactDisplayName = contactDisplayName;
Tyler Gunn94f8f112018-12-17 09:56:11 -0800992 mCallDirection = callDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700993 mCallerNumberVerificationStatus = callerNumberVerificationStatus;
Ihab Awade63fadb2014-07-09 21:52:04 -0700994 }
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800995
996 /** {@hide} */
997 public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
998 return new Details(
999 parcelableCall.getId(),
1000 parcelableCall.getHandle(),
1001 parcelableCall.getHandlePresentation(),
1002 parcelableCall.getCallerDisplayName(),
1003 parcelableCall.getCallerDisplayNamePresentation(),
1004 parcelableCall.getAccountHandle(),
1005 parcelableCall.getCapabilities(),
1006 parcelableCall.getProperties(),
1007 parcelableCall.getDisconnectCause(),
1008 parcelableCall.getConnectTimeMillis(),
1009 parcelableCall.getGatewayInfo(),
1010 parcelableCall.getVideoState(),
1011 parcelableCall.getStatusHints(),
1012 parcelableCall.getExtras(),
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001013 parcelableCall.getIntentExtras(),
Tyler Gunnd081f042018-12-04 12:56:45 -08001014 parcelableCall.getCreationTimeMillis(),
Hall Liuef98bf82020-01-09 15:22:44 -08001015 parcelableCall.getContactDisplayName(),
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001016 parcelableCall.getCallDirection(),
1017 parcelableCall.getCallerNumberVerificationStatus());
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001018 }
Santos Cordon3c20d632016-02-25 16:12:35 -08001019
1020 @Override
1021 public String toString() {
1022 StringBuilder sb = new StringBuilder();
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001023 sb.append("[id: ");
1024 sb.append(mTelecomCallId);
1025 sb.append(", pa: ");
Santos Cordon3c20d632016-02-25 16:12:35 -08001026 sb.append(mAccountHandle);
1027 sb.append(", hdl: ");
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001028 sb.append(Log.piiHandle(mHandle));
1029 sb.append(", hdlPres: ");
1030 sb.append(mHandlePresentation);
1031 sb.append(", videoState: ");
1032 sb.append(VideoProfile.videoStateToString(mVideoState));
Santos Cordon3c20d632016-02-25 16:12:35 -08001033 sb.append(", caps: ");
1034 sb.append(capabilitiesToString(mCallCapabilities));
1035 sb.append(", props: ");
Tyler Gunn720c6642016-03-22 09:02:47 -07001036 sb.append(propertiesToString(mCallProperties));
Santos Cordon3c20d632016-02-25 16:12:35 -08001037 sb.append("]");
1038 return sb.toString();
1039 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001040 }
1041
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001042 /**
1043 * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
1044 * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
1045 * implementation.
1046 * <p>
1047 * You can handle these callbacks by extending the {@link Callback} class and overriding the
1048 * callbacks that your {@link InCallService} is interested in. The callback methods include the
1049 * {@link Call} for which the callback applies, allowing reuse of a single instance of your
1050 * {@link Callback} implementation, if desired.
1051 * <p>
1052 * Use {@link Call#registerCallback(Callback)} to register your callback(s). Ensure
1053 * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
1054 * (typically in {@link InCallService#onCallRemoved(Call)}).
1055 * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
1056 * reach your implementation of {@link Callback}, so it is important to register your callback
1057 * as soon as your {@link InCallService} is notified of a new call via
1058 * {@link InCallService#onCallAdded(Call)}.
1059 */
Andrew Leeda80c872015-04-15 14:09:50 -07001060 public static abstract class Callback {
Ihab Awade63fadb2014-07-09 21:52:04 -07001061 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001062 * @hide
1063 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001064 @IntDef(prefix = { "HANDOVER_" },
1065 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
Tyler Gunn5c60d712018-03-16 09:53:44 -07001066 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
Tyler Gunn9d127732018-03-02 15:45:51 -08001067 HANDOVER_FAILURE_UNKNOWN})
Sanket Padawea8eddd42017-11-03 11:07:35 -07001068 @Retention(RetentionPolicy.SOURCE)
1069 public @interface HandoverFailureErrors {}
1070
1071 /**
1072 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
Tyler Gunn9d127732018-03-02 15:45:51 -08001073 * to handover the call to rejects the handover request.
1074 * <p>
1075 * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
1076 * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
1077 * {@code null} {@link Connection} from
1078 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1079 * ConnectionRequest)}.
1080 * <p>
1081 * For more information on call handovers, see
1082 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001083 */
1084 public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
1085
1086 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001087 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1088 * is initiated but the source or destination app does not support handover.
1089 * <p>
1090 * Will be returned when a handover is requested via
1091 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
1092 * {@link PhoneAccountHandle} does not declare
1093 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}. May also be returned when a handover is
1094 * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
1095 * {@link Details#getAccountHandle()}) does not declare
1096 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
1097 * <p>
1098 * For more information on call handovers, see
1099 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001100 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001101 public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001102
1103 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001104 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
1105 * user rejects the handover request.
1106 * <p>
1107 * For more information on call handovers, see
1108 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001109 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001110 public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001111
Sanket Padawe85291f62017-12-01 13:59:27 -08001112 /**
1113 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
1114 * is ongoing emergency call.
Tyler Gunn9d127732018-03-02 15:45:51 -08001115 * <p>
1116 * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
1117 * called on an emergency call, or if any other call is an emergency call.
1118 * <p>
1119 * Handovers are not permitted while there are ongoing emergency calls.
1120 * <p>
1121 * For more information on call handovers, see
1122 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawe85291f62017-12-01 13:59:27 -08001123 */
Tyler Gunn5c60d712018-03-16 09:53:44 -07001124 public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
Sanket Padawe85291f62017-12-01 13:59:27 -08001125
Tyler Gunn9d127732018-03-02 15:45:51 -08001126 /**
1127 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1128 * fails for an unknown reason.
1129 * <p>
1130 * For more information on call handovers, see
1131 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
1132 */
1133 public static final int HANDOVER_FAILURE_UNKNOWN = 5;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001134
1135 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001136 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
1137 *
Ihab Awade63fadb2014-07-09 21:52:04 -07001138 * @param call The {@code Call} invoking this method.
1139 * @param state The new state of the {@code Call}.
1140 */
1141 public void onStateChanged(Call call, int state) {}
1142
1143 /**
1144 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
1145 *
1146 * @param call The {@code Call} invoking this method.
1147 * @param parent The new parent of the {@code Call}.
1148 */
1149 public void onParentChanged(Call call, Call parent) {}
1150
1151 /**
1152 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
1153 *
1154 * @param call The {@code Call} invoking this method.
1155 * @param children The new children of the {@code Call}.
1156 */
1157 public void onChildrenChanged(Call call, List<Call> children) {}
1158
1159 /**
1160 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
1161 *
1162 * @param call The {@code Call} invoking this method.
1163 * @param details A {@code Details} object describing the {@code Call}.
1164 */
1165 public void onDetailsChanged(Call call, Details details) {}
1166
1167 /**
1168 * Invoked when the text messages that can be used as responses to the incoming
1169 * {@code Call} are loaded from the relevant database.
1170 * See {@link #getCannedTextResponses()}.
1171 *
1172 * @param call The {@code Call} invoking this method.
1173 * @param cannedTextResponses The text messages useable as responses.
1174 */
1175 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
1176
1177 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001178 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
1179 * character. This causes the post-dial signals to stop pending user confirmation. An
1180 * implementation should present this choice to the user and invoke
1181 * {@link #postDialContinue(boolean)} when the user makes the choice.
1182 *
1183 * @param call The {@code Call} invoking this method.
1184 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
1185 */
1186 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
1187
1188 /**
Andrew Lee50aca232014-07-22 16:41:54 -07001189 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -07001190 *
1191 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -07001192 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001193 */
Andrew Lee50aca232014-07-22 16:41:54 -07001194 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -07001195
1196 /**
1197 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
1198 * up their UI for the {@code Call} in response to state transitions. Specifically,
1199 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
1200 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
1201 * clients should wait for this method to be invoked.
1202 *
1203 * @param call The {@code Call} being destroyed.
1204 */
1205 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001206
1207 /**
1208 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
1209 * conferenced.
1210 *
1211 * @param call The {@code Call} being updated.
1212 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
1213 * conferenced.
1214 */
1215 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001216
1217 /**
Tyler Gunn5567d742019-10-31 13:04:37 -07001218 * Invoked when a {@link Call} receives an event from its associated {@link Connection} or
1219 * {@link Conference}.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001220 * <p>
1221 * Where possible, the Call should make an attempt to handle {@link Connection} events which
1222 * are part of the {@code android.telecom.*} namespace. The Call should ignore any events
1223 * it does not wish to handle. Unexpected events should be handled gracefully, as it is
1224 * possible that a {@link ConnectionService} has defined its own Connection events which a
1225 * Call is not aware of.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001226 * <p>
Tyler Gunn5567d742019-10-31 13:04:37 -07001227 * See {@link Connection#sendConnectionEvent(String, Bundle)},
1228 * {@link Conference#sendConferenceEvent(String, Bundle)}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001229 *
1230 * @param call The {@code Call} receiving the event.
1231 * @param event The event.
1232 * @param extras Extras associated with the connection event.
1233 */
1234 public void onConnectionEvent(Call call, String event, Bundle extras) {}
Hall Liu95d55872017-01-25 17:12:49 -08001235
1236 /**
1237 * Invoked when the RTT mode changes for this call.
1238 * @param call The call whose RTT mode has changed.
1239 * @param mode the new RTT mode, one of
1240 * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
1241 * or {@link RttCall#RTT_MODE_VCO}
1242 */
1243 public void onRttModeChanged(Call call, int mode) {}
1244
1245 /**
1246 * Invoked when the call's RTT status changes, either from off to on or from on to off.
1247 * @param call The call whose RTT status has changed.
1248 * @param enabled whether RTT is now enabled or disabled
1249 * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
1250 * on, null otherwise.
1251 */
1252 public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
1253
1254 /**
1255 * Invoked when the remote end of the connection has requested that an RTT communication
1256 * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
1257 * with the same ID that this method is invoked with.
1258 * @param call The call which the RTT request was placed on
1259 * @param id The ID of the request.
1260 */
1261 public void onRttRequest(Call call, int id) {}
Hall Liu57006aa2017-02-06 10:49:48 -08001262
1263 /**
1264 * Invoked when the RTT session failed to initiate for some reason, including rejection
1265 * by the remote party.
1266 * @param call The call which the RTT initiation failure occurred on.
1267 * @param reason One of the status codes defined in
1268 * {@link android.telecom.Connection.RttModifyStatus}, with the exception of
1269 * {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
1270 */
1271 public void onRttInitiationFailure(Call call, int reason) {}
Sanket Padawea8eddd42017-11-03 11:07:35 -07001272
1273 /**
1274 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1275 * has completed successfully.
Tyler Gunn9d127732018-03-02 15:45:51 -08001276 * <p>
1277 * For a full discussion of the handover process and the APIs involved, see
1278 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1279 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001280 * @param call The call which had initiated handover.
1281 */
1282 public void onHandoverComplete(Call call) {}
1283
1284 /**
1285 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1286 * has failed.
Tyler Gunn9d127732018-03-02 15:45:51 -08001287 * <p>
1288 * For a full discussion of the handover process and the APIs involved, see
1289 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1290 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001291 * @param call The call which had initiated handover.
Tyler Gunn9d127732018-03-02 15:45:51 -08001292 * @param failureReason Error reason for failure.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001293 */
1294 public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
Hall Liu95d55872017-01-25 17:12:49 -08001295 }
1296
1297 /**
1298 * A class that holds the state that describes the state of the RTT channel to the remote
1299 * party, if it is active.
1300 */
1301 public static final class RttCall {
Hall Liu07094df2017-02-28 15:17:44 -08001302 /** @hide */
Hall Liu95d55872017-01-25 17:12:49 -08001303 @Retention(RetentionPolicy.SOURCE)
1304 @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
1305 public @interface RttAudioMode {}
1306
1307 /**
1308 * For metrics use. Default value in the proto.
1309 * @hide
1310 */
1311 public static final int RTT_MODE_INVALID = 0;
1312
1313 /**
1314 * Indicates that there should be a bidirectional audio stream between the two parties
1315 * on the call.
1316 */
1317 public static final int RTT_MODE_FULL = 1;
1318
1319 /**
1320 * Indicates that the local user should be able to hear the audio stream from the remote
1321 * user, but not vice versa. Equivalent to muting the microphone.
1322 */
1323 public static final int RTT_MODE_HCO = 2;
1324
1325 /**
1326 * Indicates that the remote user should be able to hear the audio stream from the local
1327 * user, but not vice versa. Equivalent to setting the volume to zero.
1328 */
1329 public static final int RTT_MODE_VCO = 3;
1330
1331 private static final int READ_BUFFER_SIZE = 1000;
1332
1333 private InputStreamReader mReceiveStream;
1334 private OutputStreamWriter mTransmitStream;
1335 private int mRttMode;
1336 private final InCallAdapter mInCallAdapter;
Hall Liu57006aa2017-02-06 10:49:48 -08001337 private final String mTelecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001338 private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
1339
1340 /**
1341 * @hide
1342 */
Hall Liu57006aa2017-02-06 10:49:48 -08001343 public RttCall(String telecomCallId, InputStreamReader receiveStream,
1344 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
1345 mTelecomCallId = telecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001346 mReceiveStream = receiveStream;
1347 mTransmitStream = transmitStream;
1348 mRttMode = mode;
1349 mInCallAdapter = inCallAdapter;
1350 }
1351
1352 /**
1353 * Returns the current RTT audio mode.
1354 * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
1355 * {@link #RTT_MODE_HCO}.
1356 */
1357 public int getRttAudioMode() {
1358 return mRttMode;
1359 }
1360
1361 /**
1362 * Sets the RTT audio mode. The requested mode change will be communicated through
1363 * {@link Callback#onRttModeChanged(Call, int)}.
1364 * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
1365 * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
1366 */
1367 public void setRttMode(@RttAudioMode int mode) {
Hall Liu57006aa2017-02-06 10:49:48 -08001368 mInCallAdapter.setRttMode(mTelecomCallId, mode);
Hall Liu95d55872017-01-25 17:12:49 -08001369 }
1370
1371 /**
1372 * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
1373 * RTT transmits text in real-time, this method should be called once for each character
1374 * the user enters into the device.
1375 *
1376 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1377 * lead to interleaved text.
1378 * @param input The message to send to the remote user.
1379 */
1380 public void write(String input) throws IOException {
1381 mTransmitStream.write(input);
1382 mTransmitStream.flush();
1383 }
1384
1385 /**
1386 * Reads a string from the remote user, blocking if there is no data available. Returns
1387 * {@code null} if the RTT conversation has been terminated and there is no further data
1388 * to read.
1389 *
1390 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1391 * lead to interleaved text.
1392 * @return A string containing text sent by the remote user, or {@code null} if the
1393 * conversation has been terminated or if there was an error while reading.
1394 */
Hall Liub1c8a772017-07-17 17:04:41 -07001395 public String read() {
1396 try {
1397 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1398 if (numRead < 0) {
1399 return null;
1400 }
1401 return new String(mReadBuffer, 0, numRead);
1402 } catch (IOException e) {
1403 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
Jeff Sharkey90396362017-06-12 16:26:53 -06001404 return null;
Hall Liuffa4a812017-03-02 16:11:00 -08001405 }
Hall Liuffa4a812017-03-02 16:11:00 -08001406 }
1407
1408 /**
1409 * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
1410 * be read.
1411 * @return A string containing text entered by the user, or {@code null} if the user has
1412 * not entered any new text yet.
1413 */
1414 public String readImmediately() throws IOException {
1415 if (mReceiveStream.ready()) {
Hall Liub1c8a772017-07-17 17:04:41 -07001416 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1417 if (numRead < 0) {
1418 return null;
1419 }
1420 return new String(mReadBuffer, 0, numRead);
Hall Liuffa4a812017-03-02 16:11:00 -08001421 } else {
Hall Liu95d55872017-01-25 17:12:49 -08001422 return null;
1423 }
1424 }
Hall Liue9041242018-02-09 16:40:03 -08001425
1426 /**
1427 * Closes the underlying file descriptors
1428 * @hide
1429 */
1430 public void close() {
1431 try {
1432 mReceiveStream.close();
1433 } catch (IOException e) {
1434 // ignore
1435 }
1436 try {
1437 mTransmitStream.close();
1438 } catch (IOException e) {
1439 // ignore
1440 }
1441 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001442 }
1443
Andrew Leeda80c872015-04-15 14:09:50 -07001444 /**
1445 * @deprecated Use {@code Call.Callback} instead.
1446 * @hide
1447 */
1448 @Deprecated
1449 @SystemApi
1450 public static abstract class Listener extends Callback { }
1451
Ihab Awade63fadb2014-07-09 21:52:04 -07001452 private final Phone mPhone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001453 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001454 private final InCallAdapter mInCallAdapter;
Santos Cordon823fd3c2014-08-07 18:35:18 -07001455 private final List<String> mChildrenIds = new ArrayList<>();
Ihab Awade63fadb2014-07-09 21:52:04 -07001456 private final List<Call> mChildren = new ArrayList<>();
1457 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Andrew Lee011728f2015-04-23 15:47:06 -07001458 private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001459 private final List<Call> mConferenceableCalls = new ArrayList<>();
1460 private final List<Call> mUnmodifiableConferenceableCalls =
1461 Collections.unmodifiableList(mConferenceableCalls);
1462
Santos Cordon823fd3c2014-08-07 18:35:18 -07001463 private boolean mChildrenCached;
1464 private String mParentId = null;
Hall Liuef98bf82020-01-09 15:22:44 -08001465 private String mActiveGenericConferenceChild = null;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001466 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -07001467 private List<String> mCannedTextResponses = null;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001468 private String mCallingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001469 private int mTargetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07001470 private String mRemainingPostDialSequence;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001471 private VideoCallImpl mVideoCallImpl;
Hall Liu95d55872017-01-25 17:12:49 -08001472 private RttCall mRttCall;
Ihab Awade63fadb2014-07-09 21:52:04 -07001473 private Details mDetails;
Tyler Gunndee56a82016-03-23 16:06:34 -07001474 private Bundle mExtras;
Ihab Awade63fadb2014-07-09 21:52:04 -07001475
1476 /**
1477 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
1478 *
1479 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
1480 * remaining or this {@code Call} is not in a post-dial state.
1481 */
1482 public String getRemainingPostDialSequence() {
1483 return mRemainingPostDialSequence;
1484 }
1485
1486 /**
1487 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001488 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -07001489 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001490 public void answer(@VideoProfile.VideoState int videoState) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001491 mInCallAdapter.answerCall(mTelecomCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -07001492 }
1493
1494 /**
Pooja Jaind34698d2017-12-28 14:15:31 +05301495 * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
1496 *
1497 * @param address The address to which the call will be deflected.
1498 */
1499 public void deflect(Uri address) {
1500 mInCallAdapter.deflectCall(mTelecomCallId, address);
1501 }
1502
1503 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001504 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
1505 *
1506 * @param rejectWithMessage Whether to reject with a text message.
1507 * @param textMessage An optional text message with which to respond.
1508 */
1509 public void reject(boolean rejectWithMessage, String textMessage) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001510 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
Ihab Awade63fadb2014-07-09 21:52:04 -07001511 }
1512
1513 /**
1514 * Instructs this {@code Call} to disconnect.
1515 */
1516 public void disconnect() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001517 mInCallAdapter.disconnectCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001518 }
1519
1520 /**
1521 * Instructs this {@code Call} to go on hold.
1522 */
1523 public void hold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001524 mInCallAdapter.holdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001525 }
1526
1527 /**
1528 * Instructs this {@link #STATE_HOLDING} call to release from hold.
1529 */
1530 public void unhold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001531 mInCallAdapter.unholdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001532 }
1533
1534 /**
Hall Liu6dfa2492019-10-01 17:20:39 -07001535 * Instructs Telecom to put the call into the background audio processing state.
1536 *
1537 * This method can be called either when the call is in {@link #STATE_RINGING} or
1538 * {@link #STATE_ACTIVE}. After Telecom acknowledges the request by setting the call's state to
1539 * {@link #STATE_AUDIO_PROCESSING}, your app may setup the audio paths with the audio stack in
1540 * order to capture and play audio on the call stream.
1541 *
1542 * This method can only be called by the default dialer app.
1543 * @hide
1544 */
1545 @SystemApi
1546 @TestApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001547 public void enterBackgroundAudioProcessing() {
1548 if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
1549 throw new IllegalStateException("Call must be active or ringing");
1550 }
1551 mInCallAdapter.enterBackgroundAudioProcessing(mTelecomCallId);
1552 }
1553
1554 /**
1555 * Instructs Telecom to come out of the background audio processing state requested by
1556 * {@link #enterBackgroundAudioProcessing()} or from the call screening service.
1557 *
1558 * This method can only be called when the call is in {@link #STATE_AUDIO_PROCESSING}.
1559 *
1560 * @param shouldRing If true, Telecom will put the call into the
1561 * {@link #STATE_SIMULATED_RINGING} state and notify other apps that there is
1562 * a ringing call. Otherwise, the call will go into {@link #STATE_ACTIVE}
1563 * immediately.
1564 * @hide
1565 */
1566 @SystemApi
1567 @TestApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001568 public void exitBackgroundAudioProcessing(boolean shouldRing) {
1569 if (mState != STATE_AUDIO_PROCESSING) {
1570 throw new IllegalStateException("Call must in the audio processing state");
1571 }
1572 mInCallAdapter.exitBackgroundAudioProcessing(mTelecomCallId, shouldRing);
1573 }
1574
1575 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001576 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
1577 *
1578 * Any other currently playing DTMF tone in the specified call is immediately stopped.
1579 *
1580 * @param digit A character representing the DTMF digit for which to play the tone. This
1581 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
1582 */
1583 public void playDtmfTone(char digit) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001584 mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
Ihab Awade63fadb2014-07-09 21:52:04 -07001585 }
1586
1587 /**
1588 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
1589 * currently playing.
1590 *
1591 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
1592 * currently playing, this method will do nothing.
1593 */
1594 public void stopDtmfTone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001595 mInCallAdapter.stopDtmfTone(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001596 }
1597
1598 /**
1599 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
1600 *
1601 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
1602 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -07001603 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001604 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -07001605 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
1606 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001607 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
Andrew Leeda80c872015-04-15 14:09:50 -07001608 * {@code Call} will pause playing the tones and notify callbacks via
1609 * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
Ihab Awade63fadb2014-07-09 21:52:04 -07001610 * should display to the user an indication of this state and an affordance to continue
1611 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
1612 * app should invoke the {@link #postDialContinue(boolean)} method.
1613 *
1614 * @param proceed Whether or not to continue with the post-dial sequence.
1615 */
1616 public void postDialContinue(boolean proceed) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001617 mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
Ihab Awade63fadb2014-07-09 21:52:04 -07001618 }
1619
1620 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -07001621 * Notifies this {@code Call} that an account has been selected and to proceed with placing
Nancy Chen36c62f32014-10-21 18:36:39 -07001622 * an outgoing call. Optionally sets this account as the default account.
Nancy Chen5da0fd52014-07-08 14:16:17 -07001623 */
Nancy Chen36c62f32014-10-21 18:36:39 -07001624 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
1625 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
Nancy Chen5da0fd52014-07-08 14:16:17 -07001626
1627 }
1628
1629 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001630 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001631 *
1632 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -07001633 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001634 public void conference(Call callToConferenceWith) {
1635 if (callToConferenceWith != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001636 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001637 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001638 }
1639
1640 /**
1641 * Instructs this {@code Call} to split from any conference call with which it may be
1642 * connected.
1643 */
1644 public void splitFromConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001645 mInCallAdapter.splitFromConference(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001646 }
1647
1648 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001649 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001650 */
1651 public void mergeConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001652 mInCallAdapter.mergeConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001653 }
1654
1655 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001656 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001657 */
1658 public void swapConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001659 mInCallAdapter.swapConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001660 }
1661
1662 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001663 * Initiates a request to the {@link ConnectionService} to pull an external call to the local
1664 * device.
1665 * <p>
1666 * Calls to this method are ignored if the call does not have the
1667 * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
1668 * <p>
1669 * An {@link InCallService} will only see calls which support this method if it has the
1670 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
1671 * in its manifest.
1672 */
1673 public void pullExternalCall() {
1674 // If this isn't an external call, ignore the request.
1675 if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
1676 return;
1677 }
1678
1679 mInCallAdapter.pullExternalCall(mTelecomCallId);
1680 }
1681
1682 /**
1683 * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
1684 * the {@link ConnectionService}.
1685 * <p>
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001686 * Call events are used to communicate point in time information from an {@link InCallService}
1687 * to a {@link ConnectionService}. A {@link ConnectionService} implementation could define
1688 * events which enable the {@link InCallService}, for example, toggle a unique feature of the
1689 * {@link ConnectionService}.
1690 * <p>
1691 * A {@link ConnectionService} can communicate to the {@link InCallService} using
1692 * {@link Connection#sendConnectionEvent(String, Bundle)}.
1693 * <p>
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001694 * Events are exposed to {@link ConnectionService} implementations via
1695 * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
1696 * <p>
1697 * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001698 * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
1699 * ignore some events altogether.
1700 * <p>
1701 * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
1702 * conflicts between {@link InCallService} implementations. Further, {@link InCallService}
1703 * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
1704 * they define their own event types in this namespace. When defining a custom event type,
1705 * ensure the contents of the extras {@link Bundle} is clearly defined. Extra keys for this
1706 * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
1707 * <p>
1708 * When defining events and the associated extras, it is important to keep their behavior
1709 * consistent when the associated {@link InCallService} is updated. Support for deprecated
1710 * events/extras should me maintained to ensure backwards compatibility with older
1711 * {@link ConnectionService} implementations which were built to support the older behavior.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001712 *
1713 * @param event The connection event.
1714 * @param extras Bundle containing extra information associated with the event.
1715 */
1716 public void sendCallEvent(String event, Bundle extras) {
Sanket Padawef6a9e5b2018-01-05 14:26:16 -08001717 mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001718 }
1719
1720 /**
Hall Liu95d55872017-01-25 17:12:49 -08001721 * Sends an RTT upgrade request to the remote end of the connection. Success is not
1722 * guaranteed, and notification of success will be via the
1723 * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1724 */
1725 public void sendRttRequest() {
Hall Liu57006aa2017-02-06 10:49:48 -08001726 mInCallAdapter.sendRttRequest(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001727 }
1728
1729 /**
1730 * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
1731 * callback.
1732 * The ID used here should be the same as the ID that was received via the callback.
1733 * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
1734 * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
1735 */
1736 public void respondToRttRequest(int id, boolean accept) {
Hall Liu57006aa2017-02-06 10:49:48 -08001737 mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
Hall Liu95d55872017-01-25 17:12:49 -08001738 }
1739
1740 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001741 * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
1742 * by {@code toHandle}. The videoState specified indicates the desired video state after the
1743 * handover.
1744 * <p>
Tyler Gunn9d127732018-03-02 15:45:51 -08001745 * A call handover is the process where an ongoing call is transferred from one app (i.e.
1746 * {@link ConnectionService} to another app. The user could, for example, choose to continue a
1747 * mobile network call in a video calling app. The mobile network call via the Telephony stack
1748 * is referred to as the source of the handover, and the video calling app is referred to as the
1749 * destination.
1750 * <p>
1751 * When considering a handover scenario the device this method is called on is considered the
1752 * <em>initiating</em> device (since the user initiates the handover from this device), and the
1753 * other device is considered the <em>receiving</em> device.
1754 * <p>
1755 * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
1756 * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
1757 * and invoke
1758 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1759 * ConnectionRequest)} to inform the destination app that a request has been made to handover a
1760 * call to it. The app returns an instance of {@link Connection} to represent the handover call
1761 * At this point the app should display UI to indicate to the user that a call
1762 * handover is in process.
1763 * <p>
1764 * The destination app is responsible for communicating the handover request from the
1765 * <em>initiating</em> device to the <em>receiving</em> device.
1766 * <p>
1767 * When the app on the <em>receiving</em> device receives the handover request, it calls
1768 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
1769 * process from the <em>initiating</em> device to the <em>receiving</em> device. At this point
1770 * the destination app on the <em>receiving</em> device should show UI to allow the user to
1771 * choose whether they want to continue their call in the destination app.
1772 * <p>
1773 * When the destination app on the <em>receiving</em> device calls
1774 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
1775 * {@link ConnectionService} and call
1776 * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
1777 * ConnectionRequest)} to inform it of the handover request. The app returns an instance of
1778 * {@link Connection} to represent the handover call.
1779 * <p>
1780 * If the user of the <em>receiving</em> device accepts the handover, the app calls
1781 * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
1782 * original call. If the user rejects the handover, the app calls
1783 * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
1784 * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
1785 * <p>
1786 * Telecom will only allow handovers from {@link PhoneAccount}s which declare
1787 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}. Similarly, the {@link PhoneAccount}
1788 * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
1789 * <p>
1790 * Errors in the handover process are reported to the {@link InCallService} via
1791 * {@link Callback#onHandoverFailed(Call, int)}. Errors in the handover process are reported to
1792 * the involved {@link ConnectionService}s via
1793 * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001794 *
1795 * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
1796 * this call to.
Tyler Gunn9d127732018-03-02 15:45:51 -08001797 * @param videoState Indicates the video state desired after the handover (see the
1798 * {@code STATE_*} constants defined in {@link VideoProfile}).
Sanket Padawea8eddd42017-11-03 11:07:35 -07001799 * @param extras Bundle containing extra information to be passed to the
1800 * {@link ConnectionService}
1801 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001802 public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
1803 Bundle extras) {
Sanket Padawea8eddd42017-11-03 11:07:35 -07001804 mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
1805 }
1806
1807 /**
Hall Liu95d55872017-01-25 17:12:49 -08001808 * Terminate the RTT session on this call. The resulting state change will be notified via
1809 * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1810 */
1811 public void stopRtt() {
Hall Liu57006aa2017-02-06 10:49:48 -08001812 mInCallAdapter.stopRtt(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001813 }
1814
1815 /**
Tyler Gunndee56a82016-03-23 16:06:34 -07001816 * Adds some extras to this {@link Call}. Existing keys are replaced and new ones are
1817 * added.
1818 * <p>
1819 * No assumptions should be made as to how an In-Call UI or service will handle these
1820 * extras. Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
1821 *
1822 * @param extras The extras to add.
1823 */
1824 public final void putExtras(Bundle extras) {
1825 if (extras == null) {
1826 return;
1827 }
1828
1829 if (mExtras == null) {
1830 mExtras = new Bundle();
1831 }
1832 mExtras.putAll(extras);
1833 mInCallAdapter.putExtras(mTelecomCallId, extras);
1834 }
1835
1836 /**
1837 * Adds a boolean extra to this {@link Call}.
1838 *
1839 * @param key The extra key.
1840 * @param value The value.
1841 * @hide
1842 */
1843 public final void putExtra(String key, boolean value) {
1844 if (mExtras == null) {
1845 mExtras = new Bundle();
1846 }
1847 mExtras.putBoolean(key, value);
1848 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1849 }
1850
1851 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001852 * Adds an integer extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001853 *
1854 * @param key The extra key.
1855 * @param value The value.
1856 * @hide
1857 */
1858 public final void putExtra(String key, int value) {
1859 if (mExtras == null) {
1860 mExtras = new Bundle();
1861 }
1862 mExtras.putInt(key, value);
1863 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1864 }
1865
1866 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001867 * Adds a string extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001868 *
1869 * @param key The extra key.
1870 * @param value The value.
1871 * @hide
1872 */
1873 public final void putExtra(String key, String value) {
1874 if (mExtras == null) {
1875 mExtras = new Bundle();
1876 }
1877 mExtras.putString(key, value);
1878 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1879 }
1880
1881 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001882 * Removes extras from this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001883 *
1884 * @param keys The keys of the extras to remove.
1885 */
1886 public final void removeExtras(List<String> keys) {
1887 if (mExtras != null) {
1888 for (String key : keys) {
1889 mExtras.remove(key);
1890 }
1891 if (mExtras.size() == 0) {
1892 mExtras = null;
1893 }
1894 }
1895 mInCallAdapter.removeExtras(mTelecomCallId, keys);
1896 }
1897
1898 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001899 * Removes extras from this {@link Call}.
1900 *
1901 * @param keys The keys of the extras to remove.
1902 */
1903 public final void removeExtras(String ... keys) {
1904 removeExtras(Arrays.asList(keys));
1905 }
1906
1907 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001908 * Obtains the parent of this {@code Call} in a conference, if any.
1909 *
1910 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
1911 * child of any conference {@code Call}s.
1912 */
1913 public Call getParent() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001914 if (mParentId != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001915 return mPhone.internalGetCallByTelecomId(mParentId);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001916 }
1917 return null;
Ihab Awade63fadb2014-07-09 21:52:04 -07001918 }
1919
1920 /**
1921 * Obtains the children of this conference {@code Call}, if any.
1922 *
1923 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
1924 * {@code List} otherwise.
1925 */
1926 public List<Call> getChildren() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001927 if (!mChildrenCached) {
1928 mChildrenCached = true;
1929 mChildren.clear();
1930
1931 for(String id : mChildrenIds) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001932 Call call = mPhone.internalGetCallByTelecomId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001933 if (call == null) {
1934 // At least one child was still not found, so do not save true for "cached"
1935 mChildrenCached = false;
1936 } else {
1937 mChildren.add(call);
1938 }
1939 }
1940 }
1941
Ihab Awade63fadb2014-07-09 21:52:04 -07001942 return mUnmodifiableChildren;
1943 }
1944
1945 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001946 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
1947 *
1948 * @return The list of conferenceable {@code Call}s.
1949 */
1950 public List<Call> getConferenceableCalls() {
1951 return mUnmodifiableConferenceableCalls;
1952 }
1953
1954 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001955 * Obtains the state of this {@code Call}.
1956 *
1957 * @return A state value, chosen from the {@code STATE_*} constants.
1958 */
1959 public int getState() {
1960 return mState;
1961 }
1962
1963 /**
Hall Liuef98bf82020-01-09 15:22:44 -08001964 * Returns the child {@link Call} in a generic conference that is currently active.
1965 * For calls that are not generic conferences, or when the generic conference has more than
1966 * 2 children, returns {@code null}.
1967 * @see Details#PROPERTY_GENERIC_CONFERENCE
1968 * @return The active child call.
1969 */
1970 public @Nullable Call getGenericConferenceActiveChildCall() {
1971 if (mActiveGenericConferenceChild != null) {
1972 return mPhone.internalGetCallByTelecomId(mActiveGenericConferenceChild);
1973 }
1974 return null;
1975 }
1976
1977 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001978 * Obtains a list of canned, pre-configured message responses to present to the user as
1979 * ways of rejecting this {@code Call} using via a text message.
1980 *
1981 * @see #reject(boolean, String)
1982 *
1983 * @return A list of canned text message responses.
1984 */
1985 public List<String> getCannedTextResponses() {
1986 return mCannedTextResponses;
1987 }
1988
1989 /**
1990 * Obtains an object that can be used to display video from this {@code Call}.
1991 *
Andrew Lee50aca232014-07-22 16:41:54 -07001992 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001993 */
Andrew Lee50aca232014-07-22 16:41:54 -07001994 public InCallService.VideoCall getVideoCall() {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001995 return mVideoCallImpl;
Ihab Awade63fadb2014-07-09 21:52:04 -07001996 }
1997
1998 /**
1999 * Obtains an object containing call details.
2000 *
2001 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
2002 * result may be {@code null}.
2003 */
2004 public Details getDetails() {
2005 return mDetails;
2006 }
2007
2008 /**
Hall Liu95d55872017-01-25 17:12:49 -08002009 * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
2010 * receive RTT text data, as well as to change the RTT mode.
2011 * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
2012 */
2013 public @Nullable RttCall getRttCall() {
2014 return mRttCall;
2015 }
2016
2017 /**
2018 * Returns whether this call has an active RTT connection.
2019 * @return true if there is a connection, false otherwise.
2020 */
2021 public boolean isRttActive() {
Hall Liue9041242018-02-09 16:40:03 -08002022 return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
Hall Liu95d55872017-01-25 17:12:49 -08002023 }
2024
2025 /**
Andrew Leeda80c872015-04-15 14:09:50 -07002026 * Registers a callback to this {@code Call}.
2027 *
2028 * @param callback A {@code Callback}.
2029 */
2030 public void registerCallback(Callback callback) {
Andrew Lee011728f2015-04-23 15:47:06 -07002031 registerCallback(callback, new Handler());
2032 }
2033
2034 /**
2035 * Registers a callback to this {@code Call}.
2036 *
2037 * @param callback A {@code Callback}.
2038 * @param handler A handler which command and status changes will be delivered to.
2039 */
2040 public void registerCallback(Callback callback, Handler handler) {
2041 unregisterCallback(callback);
Roshan Pius1ca62072015-07-07 17:34:51 -07002042 // Don't allow new callback registration if the call is already being destroyed.
2043 if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002044 mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
2045 }
Andrew Leeda80c872015-04-15 14:09:50 -07002046 }
2047
2048 /**
2049 * Unregisters a callback from this {@code Call}.
2050 *
2051 * @param callback A {@code Callback}.
2052 */
2053 public void unregisterCallback(Callback callback) {
Roshan Pius1ca62072015-07-07 17:34:51 -07002054 // Don't allow callback deregistration if the call is already being destroyed.
2055 if (callback != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002056 for (CallbackRecord<Callback> record : mCallbackRecords) {
2057 if (record.getCallback() == callback) {
2058 mCallbackRecords.remove(record);
2059 break;
2060 }
2061 }
Andrew Leeda80c872015-04-15 14:09:50 -07002062 }
2063 }
2064
Santos Cordon3c20d632016-02-25 16:12:35 -08002065 @Override
2066 public String toString() {
2067 return new StringBuilder().
2068 append("Call [id: ").
2069 append(mTelecomCallId).
2070 append(", state: ").
2071 append(stateToString(mState)).
2072 append(", details: ").
2073 append(mDetails).
2074 append("]").toString();
2075 }
2076
2077 /**
2078 * @param state An integer value of a {@code STATE_*} constant.
2079 * @return A string representation of the value.
2080 */
2081 private static String stateToString(int state) {
2082 switch (state) {
2083 case STATE_NEW:
2084 return "NEW";
2085 case STATE_RINGING:
2086 return "RINGING";
2087 case STATE_DIALING:
2088 return "DIALING";
2089 case STATE_ACTIVE:
2090 return "ACTIVE";
2091 case STATE_HOLDING:
2092 return "HOLDING";
2093 case STATE_DISCONNECTED:
2094 return "DISCONNECTED";
2095 case STATE_CONNECTING:
2096 return "CONNECTING";
2097 case STATE_DISCONNECTING:
2098 return "DISCONNECTING";
2099 case STATE_SELECT_PHONE_ACCOUNT:
2100 return "SELECT_PHONE_ACCOUNT";
Hall Liu4e35b642019-10-14 17:50:45 -07002101 case STATE_SIMULATED_RINGING:
2102 return "SIMULATED_RINGING";
2103 case STATE_AUDIO_PROCESSING:
2104 return "AUDIO_PROCESSING";
Santos Cordon3c20d632016-02-25 16:12:35 -08002105 default:
2106 Log.w(Call.class, "Unknown state %d", state);
2107 return "UNKNOWN";
2108 }
2109 }
2110
Andrew Leeda80c872015-04-15 14:09:50 -07002111 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002112 * Adds a listener to this {@code Call}.
2113 *
2114 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002115 * @deprecated Use {@link #registerCallback} instead.
2116 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002117 */
Andrew Leeda80c872015-04-15 14:09:50 -07002118 @Deprecated
2119 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002120 public void addListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002121 registerCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002122 }
2123
2124 /**
2125 * Removes a listener from this {@code Call}.
2126 *
2127 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002128 * @deprecated Use {@link #unregisterCallback} instead.
2129 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002130 */
Andrew Leeda80c872015-04-15 14:09:50 -07002131 @Deprecated
2132 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002133 public void removeListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002134 unregisterCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002135 }
2136
2137 /** {@hide} */
Tyler Gunn159f35c2017-03-02 09:28:37 -08002138 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
2139 int targetSdkVersion) {
Ihab Awade63fadb2014-07-09 21:52:04 -07002140 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002141 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002142 mInCallAdapter = inCallAdapter;
2143 mState = STATE_NEW;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002144 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002145 mTargetSdkVersion = targetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07002146 }
2147
2148 /** {@hide} */
Tyler Gunnb88b3112016-11-09 10:19:23 -08002149 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
Tyler Gunn159f35c2017-03-02 09:28:37 -08002150 String callingPackage, int targetSdkVersion) {
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002151 mPhone = phone;
2152 mTelecomCallId = telecomCallId;
2153 mInCallAdapter = inCallAdapter;
2154 mState = state;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002155 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002156 mTargetSdkVersion = targetSdkVersion;
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002157 }
2158
2159 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002160 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002161 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002162 }
2163
2164 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002165 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Tyler Gunnb88b3112016-11-09 10:19:23 -08002166
Ihab Awade63fadb2014-07-09 21:52:04 -07002167 // First, we update the internal state as far as possible before firing any updates.
Sailesh Nepal1bef3392016-01-24 18:21:53 -08002168 Details details = Details.createFromParcelableCall(parcelableCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07002169 boolean detailsChanged = !Objects.equals(mDetails, details);
2170 if (detailsChanged) {
2171 mDetails = details;
2172 }
2173
2174 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -07002175 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
2176 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
2177 mCannedTextResponses =
2178 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Yorke Leee886f632015-08-04 13:43:31 -07002179 cannedTextResponsesChanged = true;
Ihab Awade63fadb2014-07-09 21:52:04 -07002180 }
2181
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002182 IVideoProvider previousVideoProvider = mVideoCallImpl == null ? null :
2183 mVideoCallImpl.getVideoProvider();
2184 IVideoProvider newVideoProvider = parcelableCall.getVideoProvider();
2185
2186 // parcelableCall.isVideoCallProviderChanged is only true when we have a video provider
2187 // specified; so we should check if the actual IVideoProvider changes as well.
2188 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged()
2189 && !Objects.equals(previousVideoProvider, newVideoProvider);
Andrew Lee50aca232014-07-22 16:41:54 -07002190 if (videoCallChanged) {
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002191 if (mVideoCallImpl != null) {
2192 mVideoCallImpl.destroy();
2193 }
2194 mVideoCallImpl = parcelableCall.isVideoCallProviderChanged() ?
2195 parcelableCall.getVideoCallImpl(mCallingPackage, mTargetSdkVersion) : null;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002196 }
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002197
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002198 if (mVideoCallImpl != null) {
2199 mVideoCallImpl.setVideoState(getDetails().getVideoState());
Ihab Awade63fadb2014-07-09 21:52:04 -07002200 }
2201
Santos Cordone3c507b2015-04-23 14:44:19 -07002202 int state = parcelableCall.getState();
Hall Liu31de23d2019-10-11 15:38:29 -07002203 if (mTargetSdkVersion < Phone.SDK_VERSION_R && state == Call.STATE_SIMULATED_RINGING) {
2204 state = Call.STATE_RINGING;
2205 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002206 boolean stateChanged = mState != state;
2207 if (stateChanged) {
2208 mState = state;
2209 }
2210
Santos Cordon823fd3c2014-08-07 18:35:18 -07002211 String parentId = parcelableCall.getParentCallId();
2212 boolean parentChanged = !Objects.equals(mParentId, parentId);
2213 if (parentChanged) {
2214 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002215 }
2216
Santos Cordon823fd3c2014-08-07 18:35:18 -07002217 List<String> childCallIds = parcelableCall.getChildCallIds();
2218 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
2219 if (childrenChanged) {
2220 mChildrenIds.clear();
2221 mChildrenIds.addAll(parcelableCall.getChildCallIds());
2222 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -07002223 }
2224
Hall Liuef98bf82020-01-09 15:22:44 -08002225 String activeChildCallId = parcelableCall.getActiveChildCallId();
2226 boolean activeChildChanged = !Objects.equals(activeChildCallId,
2227 mActiveGenericConferenceChild);
2228 if (activeChildChanged) {
2229 mActiveGenericConferenceChild = activeChildCallId;
2230 }
2231
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002232 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
2233 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
2234 for (String otherId : conferenceableCallIds) {
2235 if (callIdMap.containsKey(otherId)) {
2236 conferenceableCalls.add(callIdMap.get(otherId));
2237 }
2238 }
2239
2240 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
2241 mConferenceableCalls.clear();
2242 mConferenceableCalls.addAll(conferenceableCalls);
2243 fireConferenceableCallsChanged();
2244 }
2245
Hall Liu95d55872017-01-25 17:12:49 -08002246 boolean isRttChanged = false;
2247 boolean rttModeChanged = false;
Hall Liue9041242018-02-09 16:40:03 -08002248 if (parcelableCall.getIsRttCallChanged()
2249 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
Hall Liu95d55872017-01-25 17:12:49 -08002250 ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
2251 InputStreamReader receiveStream = new InputStreamReader(
2252 new ParcelFileDescriptor.AutoCloseInputStream(
2253 parcelableRttCall.getReceiveStream()),
2254 StandardCharsets.UTF_8);
2255 OutputStreamWriter transmitStream = new OutputStreamWriter(
2256 new ParcelFileDescriptor.AutoCloseOutputStream(
2257 parcelableRttCall.getTransmitStream()),
2258 StandardCharsets.UTF_8);
Hall Liu57006aa2017-02-06 10:49:48 -08002259 RttCall newRttCall = new Call.RttCall(mTelecomCallId,
Hall Liu95d55872017-01-25 17:12:49 -08002260 receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
2261 if (mRttCall == null) {
2262 isRttChanged = true;
2263 } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
2264 rttModeChanged = true;
2265 }
2266 mRttCall = newRttCall;
2267 } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
2268 && parcelableCall.getIsRttCallChanged()) {
2269 isRttChanged = true;
2270 mRttCall = null;
2271 }
2272
Ihab Awade63fadb2014-07-09 21:52:04 -07002273 // Now we fire updates, ensuring that any client who listens to any of these notifications
2274 // gets the most up-to-date state.
2275
2276 if (stateChanged) {
2277 fireStateChanged(mState);
2278 }
2279 if (detailsChanged) {
2280 fireDetailsChanged(mDetails);
2281 }
2282 if (cannedTextResponsesChanged) {
2283 fireCannedTextResponsesLoaded(mCannedTextResponses);
2284 }
Andrew Lee50aca232014-07-22 16:41:54 -07002285 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002286 fireVideoCallChanged(mVideoCallImpl);
Ihab Awade63fadb2014-07-09 21:52:04 -07002287 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002288 if (parentChanged) {
2289 fireParentChanged(getParent());
2290 }
Hall Liuef98bf82020-01-09 15:22:44 -08002291 if (childrenChanged || activeChildChanged) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002292 fireChildrenChanged(getChildren());
2293 }
Hall Liu95d55872017-01-25 17:12:49 -08002294 if (isRttChanged) {
2295 fireOnIsRttChanged(mRttCall != null, mRttCall);
2296 }
2297 if (rttModeChanged) {
2298 fireOnRttModeChanged(mRttCall.getRttAudioMode());
2299 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002300
2301 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
2302 // remove ourselves from the Phone. Note that we do this after completing all state updates
2303 // so a client can cleanly transition all their UI to the state appropriate for a
2304 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
2305 if (mState == STATE_DISCONNECTED) {
2306 fireCallDestroyed();
Ihab Awade63fadb2014-07-09 21:52:04 -07002307 }
2308 }
2309
2310 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002311 final void internalSetPostDialWait(String remaining) {
2312 mRemainingPostDialSequence = remaining;
2313 firePostDialWait(mRemainingPostDialSequence);
2314 }
2315
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07002316 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -07002317 final void internalSetDisconnected() {
2318 if (mState != Call.STATE_DISCONNECTED) {
2319 mState = Call.STATE_DISCONNECTED;
2320 fireStateChanged(mState);
2321 fireCallDestroyed();
Santos Cordonf30d7e92014-08-26 09:54:33 -07002322 }
2323 }
2324
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002325 /** {@hide} */
2326 final void internalOnConnectionEvent(String event, Bundle extras) {
2327 fireOnConnectionEvent(event, extras);
2328 }
2329
Hall Liu95d55872017-01-25 17:12:49 -08002330 /** {@hide} */
2331 final void internalOnRttUpgradeRequest(final int requestId) {
2332 for (CallbackRecord<Callback> record : mCallbackRecords) {
2333 final Call call = this;
2334 final Callback callback = record.getCallback();
2335 record.getHandler().post(() -> callback.onRttRequest(call, requestId));
2336 }
2337 }
2338
Hall Liu57006aa2017-02-06 10:49:48 -08002339 /** @hide */
2340 final void internalOnRttInitiationFailure(int reason) {
2341 for (CallbackRecord<Callback> record : mCallbackRecords) {
2342 final Call call = this;
2343 final Callback callback = record.getCallback();
2344 record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
2345 }
2346 }
2347
Sanket Padawe85291f62017-12-01 13:59:27 -08002348 /** {@hide} */
2349 final void internalOnHandoverFailed(int error) {
2350 for (CallbackRecord<Callback> record : mCallbackRecords) {
2351 final Call call = this;
2352 final Callback callback = record.getCallback();
2353 record.getHandler().post(() -> callback.onHandoverFailed(call, error));
2354 }
2355 }
2356
Tyler Gunn858bfaf2018-01-22 15:17:54 -08002357 /** {@hide} */
2358 final void internalOnHandoverComplete() {
2359 for (CallbackRecord<Callback> record : mCallbackRecords) {
2360 final Call call = this;
2361 final Callback callback = record.getCallback();
2362 record.getHandler().post(() -> callback.onHandoverComplete(call));
2363 }
2364 }
2365
Andrew Lee011728f2015-04-23 15:47:06 -07002366 private void fireStateChanged(final int newState) {
2367 for (CallbackRecord<Callback> record : mCallbackRecords) {
2368 final Call call = this;
2369 final Callback callback = record.getCallback();
2370 record.getHandler().post(new Runnable() {
2371 @Override
2372 public void run() {
2373 callback.onStateChanged(call, newState);
2374 }
2375 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002376 }
2377 }
2378
Andrew Lee011728f2015-04-23 15:47:06 -07002379 private void fireParentChanged(final Call newParent) {
2380 for (CallbackRecord<Callback> record : mCallbackRecords) {
2381 final Call call = this;
2382 final Callback callback = record.getCallback();
2383 record.getHandler().post(new Runnable() {
2384 @Override
2385 public void run() {
2386 callback.onParentChanged(call, newParent);
2387 }
2388 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002389 }
2390 }
2391
Andrew Lee011728f2015-04-23 15:47:06 -07002392 private void fireChildrenChanged(final List<Call> children) {
2393 for (CallbackRecord<Callback> record : mCallbackRecords) {
2394 final Call call = this;
2395 final Callback callback = record.getCallback();
2396 record.getHandler().post(new Runnable() {
2397 @Override
2398 public void run() {
2399 callback.onChildrenChanged(call, children);
2400 }
2401 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002402 }
2403 }
2404
Andrew Lee011728f2015-04-23 15:47:06 -07002405 private void fireDetailsChanged(final Details details) {
2406 for (CallbackRecord<Callback> record : mCallbackRecords) {
2407 final Call call = this;
2408 final Callback callback = record.getCallback();
2409 record.getHandler().post(new Runnable() {
2410 @Override
2411 public void run() {
2412 callback.onDetailsChanged(call, details);
2413 }
2414 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002415 }
2416 }
2417
Andrew Lee011728f2015-04-23 15:47:06 -07002418 private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
2419 for (CallbackRecord<Callback> record : mCallbackRecords) {
2420 final Call call = this;
2421 final Callback callback = record.getCallback();
2422 record.getHandler().post(new Runnable() {
2423 @Override
2424 public void run() {
2425 callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
2426 }
2427 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002428 }
2429 }
2430
Andrew Lee011728f2015-04-23 15:47:06 -07002431 private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
2432 for (CallbackRecord<Callback> record : mCallbackRecords) {
2433 final Call call = this;
2434 final Callback callback = record.getCallback();
2435 record.getHandler().post(new Runnable() {
2436 @Override
2437 public void run() {
2438 callback.onVideoCallChanged(call, videoCall);
2439 }
2440 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002441 }
2442 }
2443
Andrew Lee011728f2015-04-23 15:47:06 -07002444 private void firePostDialWait(final String remainingPostDialSequence) {
2445 for (CallbackRecord<Callback> record : mCallbackRecords) {
2446 final Call call = this;
2447 final Callback callback = record.getCallback();
2448 record.getHandler().post(new Runnable() {
2449 @Override
2450 public void run() {
2451 callback.onPostDialWait(call, remainingPostDialSequence);
2452 }
2453 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002454 }
2455 }
2456
2457 private void fireCallDestroyed() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002458 /**
2459 * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
2460 * onCallRemoved callback, we remove this call from the Phone's record
2461 * only once all of the registered onCallDestroyed callbacks are executed.
2462 * All the callbacks get removed from our records as a part of this operation
2463 * since onCallDestroyed is the final callback.
2464 */
2465 final Call call = this;
2466 if (mCallbackRecords.isEmpty()) {
2467 // No callbacks registered, remove the call from Phone's record.
2468 mPhone.internalRemoveCall(call);
2469 }
2470 for (final CallbackRecord<Callback> record : mCallbackRecords) {
Andrew Lee011728f2015-04-23 15:47:06 -07002471 final Callback callback = record.getCallback();
2472 record.getHandler().post(new Runnable() {
2473 @Override
2474 public void run() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002475 boolean isFinalRemoval = false;
2476 RuntimeException toThrow = null;
2477 try {
2478 callback.onCallDestroyed(call);
2479 } catch (RuntimeException e) {
2480 toThrow = e;
2481 }
2482 synchronized(Call.this) {
2483 mCallbackRecords.remove(record);
2484 if (mCallbackRecords.isEmpty()) {
2485 isFinalRemoval = true;
2486 }
2487 }
2488 if (isFinalRemoval) {
2489 mPhone.internalRemoveCall(call);
2490 }
2491 if (toThrow != null) {
2492 throw toThrow;
2493 }
Andrew Lee011728f2015-04-23 15:47:06 -07002494 }
2495 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002496 }
2497 }
2498
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002499 private void fireConferenceableCallsChanged() {
Andrew Lee011728f2015-04-23 15:47:06 -07002500 for (CallbackRecord<Callback> record : mCallbackRecords) {
2501 final Call call = this;
2502 final Callback callback = record.getCallback();
2503 record.getHandler().post(new Runnable() {
2504 @Override
2505 public void run() {
2506 callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
2507 }
2508 });
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002509 }
2510 }
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002511
2512 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002513 * Notifies listeners of an incoming connection event.
2514 * <p>
2515 * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
2516 *
2517 * @param event
2518 * @param extras
2519 */
2520 private void fireOnConnectionEvent(final String event, final Bundle extras) {
2521 for (CallbackRecord<Callback> record : mCallbackRecords) {
2522 final Call call = this;
2523 final Callback callback = record.getCallback();
2524 record.getHandler().post(new Runnable() {
2525 @Override
2526 public void run() {
2527 callback.onConnectionEvent(call, event, extras);
2528 }
2529 });
2530 }
2531 }
2532
2533 /**
Hall Liu95d55872017-01-25 17:12:49 -08002534 * Notifies listeners of an RTT on/off change
2535 *
2536 * @param enabled True if RTT is now enabled, false otherwise
2537 */
2538 private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
2539 for (CallbackRecord<Callback> record : mCallbackRecords) {
2540 final Call call = this;
2541 final Callback callback = record.getCallback();
2542 record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
2543 }
2544 }
2545
2546 /**
2547 * Notifies listeners of a RTT mode change
2548 *
2549 * @param mode The new RTT mode
2550 */
2551 private void fireOnRttModeChanged(final int mode) {
2552 for (CallbackRecord<Callback> record : mCallbackRecords) {
2553 final Call call = this;
2554 final Callback callback = record.getCallback();
2555 record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
2556 }
2557 }
2558
2559 /**
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002560 * Determines if two bundles are equal.
2561 *
2562 * @param bundle The original bundle.
2563 * @param newBundle The bundle to compare with.
2564 * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
2565 */
2566 private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
2567 if (bundle == null || newBundle == null) {
2568 return bundle == newBundle;
2569 }
2570
2571 if (bundle.size() != newBundle.size()) {
2572 return false;
2573 }
2574
2575 for(String key : bundle.keySet()) {
2576 if (key != null) {
2577 final Object value = bundle.get(key);
2578 final Object newValue = newBundle.get(key);
2579 if (!Objects.equals(value, newValue)) {
2580 return false;
2581 }
2582 }
2583 }
2584 return true;
2585 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002586}