blob: 5bdcdf4d63efc84ce543dff047ec3502d56454a4 [file] [log] [blame]
Ihab Awade63fadb2014-07-09 21:52:04 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tyler Gunnef9f6f92014-09-12 22:16:17 -070017package android.telecom;
Ihab Awade63fadb2014-07-09 21:52:04 -070018
Hall Liu95d55872017-01-25 17:12:49 -080019import android.annotation.IntDef;
Ravi Paluri404babb2020-01-23 19:02:44 +053020import android.annotation.NonNull;
Hall Liu95d55872017-01-25 17:12:49 -080021import android.annotation.Nullable;
Andrew Leeda80c872015-04-15 14:09:50 -070022import android.annotation.SystemApi;
Hall Liu6dfa2492019-10-01 17:20:39 -070023import android.annotation.TestApi;
Artur Satayev53ada2a2019-12-10 17:47:56 +000024import android.compat.annotation.UnsupportedAppUsage;
Tyler Gunn460b7d42020-05-15 10:19:32 -070025import android.content.pm.ServiceInfo;
Ihab Awade63fadb2014-07-09 21:52:04 -070026import android.net.Uri;
qing723dac62022-10-28 03:40:43 +000027import android.os.BadParcelableException;
Tyler Gunn6e3ecc42018-11-12 11:30:56 -080028import android.os.Build;
Nancy Chen10798dc2014-08-08 14:00:25 -070029import android.os.Bundle;
Andrew Lee011728f2015-04-23 15:47:06 -070030import android.os.Handler;
Hall Liu95d55872017-01-25 17:12:49 -080031import android.os.ParcelFileDescriptor;
Ihab Awade63fadb2014-07-09 21:52:04 -070032
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -080033import com.android.internal.telecom.IVideoProvider;
34
Hall Liu95d55872017-01-25 17:12:49 -080035import java.io.IOException;
36import java.io.InputStreamReader;
37import java.io.OutputStreamWriter;
Hall Liu95d55872017-01-25 17:12:49 -080038import java.lang.annotation.Retention;
39import java.lang.annotation.RetentionPolicy;
40import java.nio.charset.StandardCharsets;
Ihab Awade63fadb2014-07-09 21:52:04 -070041import java.util.ArrayList;
Tyler Gunn071be6f2016-05-10 14:52:33 -070042import java.util.Arrays;
Ihab Awade63fadb2014-07-09 21:52:04 -070043import java.util.Collections;
44import java.util.List;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070045import java.util.Map;
Ihab Awade63fadb2014-07-09 21:52:04 -070046import java.util.Objects;
Jay Shrauner229e3822014-08-15 09:23:07 -070047import java.util.concurrent.CopyOnWriteArrayList;
Ihab Awade63fadb2014-07-09 21:52:04 -070048
49/**
50 * Represents an ongoing phone call that the in-call app should present to the user.
51 */
52public final class Call {
53 /**
54 * The state of a {@code Call} when newly created.
55 */
56 public static final int STATE_NEW = 0;
57
58 /**
59 * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
60 */
61 public static final int STATE_DIALING = 1;
62
63 /**
64 * The state of an incoming {@code Call} when ringing locally, but not yet connected.
65 */
66 public static final int STATE_RINGING = 2;
67
68 /**
69 * The state of a {@code Call} when in a holding state.
70 */
71 public static final int STATE_HOLDING = 3;
72
73 /**
74 * The state of a {@code Call} when actively supporting conversation.
75 */
76 public static final int STATE_ACTIVE = 4;
77
78 /**
79 * The state of a {@code Call} when no further voice or other communication is being
80 * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
81 * is no longer active, and the local data transport has or inevitably will release resources
82 * associated with this {@code Call}.
83 */
84 public static final int STATE_DISCONNECTED = 7;
85
Nancy Chen5da0fd52014-07-08 14:16:17 -070086 /**
Santos Cordone3c507b2015-04-23 14:44:19 -070087 * The state of an outgoing {@code Call} when waiting on user to select a
88 * {@link PhoneAccount} through which to place the call.
Nancy Chen5da0fd52014-07-08 14:16:17 -070089 */
Santos Cordone3c507b2015-04-23 14:44:19 -070090 public static final int STATE_SELECT_PHONE_ACCOUNT = 8;
91
92 /**
93 * @hide
94 * @deprecated use STATE_SELECT_PHONE_ACCOUNT.
95 */
96 @Deprecated
97 @SystemApi
98 public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT;
Nancy Chen5da0fd52014-07-08 14:16:17 -070099
Nancy Chene20930f2014-08-07 16:17:21 -0700100 /**
Nancy Chene9b7a8e2014-08-08 14:26:27 -0700101 * The initial state of an outgoing {@code Call}.
102 * Common transitions are to {@link #STATE_DIALING} state for a successful call or
103 * {@link #STATE_DISCONNECTED} if it failed.
Nancy Chene20930f2014-08-07 16:17:21 -0700104 */
105 public static final int STATE_CONNECTING = 9;
106
Nancy Chen513c8922014-09-17 14:47:20 -0700107 /**
Tyler Gunn4afc6af2014-10-07 10:14:55 -0700108 * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
109 * call has not yet been disconnected by the underlying {@code ConnectionService}. The next
110 * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
111 */
112 public static final int STATE_DISCONNECTING = 10;
113
114 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700115 * The state of an external call which is in the process of being pulled from a remote device to
116 * the local device.
117 * <p>
118 * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
119 * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
120 * <p>
121 * An {@link InCallService} will only see this state if it has the
122 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
123 * manifest.
124 */
125 public static final int STATE_PULLING_CALL = 11;
126
127 /**
Hall Liu6dfa2492019-10-01 17:20:39 -0700128 * The state of a call that is active with the network, but the audio from the call is
129 * being intercepted by an app on the local device. Telecom does not hold audio focus in this
130 * state, and the call will be invisible to the user except for a persistent notification.
131 */
132 public static final int STATE_AUDIO_PROCESSING = 12;
133
134 /**
135 * The state of a call that is being presented to the user after being in
136 * {@link #STATE_AUDIO_PROCESSING}. The call is still active with the network in this case, and
137 * Telecom will hold audio focus and play a ringtone if appropriate.
138 */
139 public static final int STATE_SIMULATED_RINGING = 13;
140
141 /**
Tyler Gunn1e406ca2021-03-18 16:47:14 -0700142 * @hide
143 */
144 @IntDef(prefix = { "STATE_" },
145 value = {
146 STATE_NEW,
147 STATE_DIALING,
148 STATE_RINGING,
149 STATE_HOLDING,
150 STATE_ACTIVE,
151 STATE_DISCONNECTED,
152 STATE_SELECT_PHONE_ACCOUNT,
153 STATE_CONNECTING,
154 STATE_DISCONNECTING,
155 STATE_PULLING_CALL,
156 STATE_AUDIO_PROCESSING,
157 STATE_SIMULATED_RINGING
158 })
159 @Retention(RetentionPolicy.SOURCE)
160 public @interface CallState {};
161
162 /**
Nancy Chen513c8922014-09-17 14:47:20 -0700163 * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
164 * extras. Used to pass the phone accounts to display on the front end to the user in order to
165 * select phone accounts to (for example) place a call.
Hall Liu34d9e242018-11-21 17:05:58 -0800166 * @deprecated Use the list from {@link #EXTRA_SUGGESTED_PHONE_ACCOUNTS} instead.
Nancy Chen513c8922014-09-17 14:47:20 -0700167 */
Hall Liu34d9e242018-11-21 17:05:58 -0800168 @Deprecated
Nancy Chen513c8922014-09-17 14:47:20 -0700169 public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
170
mike dooley4af561f2016-12-20 08:55:17 -0800171 /**
Thomas Stuart5ca875eb2022-08-03 18:39:57 -0700172 * Extra key intended for {@link InCallService}s that notify the user of an incoming call. When
173 * EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB returns true, the {@link InCallService} should not
174 * interrupt the user of the incoming call because the call is being suppressed by Do Not
175 * Disturb settings.
176 *
177 * This extra will be removed from the {@link Call} object for {@link InCallService}s that do
178 * not hold the {@link android.Manifest.permission#READ_CONTACTS} permission.
179 */
180 public static final String EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB =
181 "android.telecom.extra.IS_SUPPRESSED_BY_DO_NOT_DISTURB";
182
183 /**
Hall Liu34d9e242018-11-21 17:05:58 -0800184 * Key for extra used to pass along a list of {@link PhoneAccountSuggestion}s to the in-call
185 * UI when a call enters the {@link #STATE_SELECT_PHONE_ACCOUNT} state. The list included here
186 * will have the same length and be in the same order as the list passed with
187 * {@link #AVAILABLE_PHONE_ACCOUNTS}.
188 */
189 public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS =
190 "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS";
191
192 /**
mike dooley91217422017-03-09 12:58:42 -0800193 * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC)
194 * when the last outgoing emergency call was made. This is used to identify potential emergency
195 * callbacks.
mike dooley4af561f2016-12-20 08:55:17 -0800196 */
197 public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
198 "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
199
Usman Abdullahb0dc29a2019-03-06 15:54:56 -0800200
201 /**
202 * Extra key used to indicate whether a {@link CallScreeningService} has requested to silence
203 * the ringtone for a call. If the {@link InCallService} declares
204 * {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} in its manifest, it should not
205 * play a ringtone for an incoming call with this extra key set.
206 */
207 public static final String EXTRA_SILENT_RINGING_REQUESTED =
208 "android.telecom.extra.SILENT_RINGING_REQUESTED";
209
Tyler Gunn8bf76572017-04-06 15:30:08 -0700210 /**
211 * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
212 * Telecom that the user has requested that the current {@link Call} should be handed over
213 * to another {@link ConnectionService}.
214 * <p>
215 * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
216 * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
217 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700218 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
219 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700220 */
221 public static final String EVENT_REQUEST_HANDOVER =
222 "android.telecom.event.REQUEST_HANDOVER";
223
224 /**
225 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
226 * {@link PhoneAccountHandle} to which a call should be handed over to.
227 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700228 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
229 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700230 */
231 public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
232 "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
233
234 /**
235 * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
236 * video state of the call when it is handed over to the new {@link PhoneAccount}.
237 * <p>
238 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
239 * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
240 * {@link VideoProfile#STATE_TX_ENABLED}.
241 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700242 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
243 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700244 */
245 public static final String EXTRA_HANDOVER_VIDEO_STATE =
246 "android.telecom.extra.HANDOVER_VIDEO_STATE";
247
248 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700249 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Used by the
250 * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra
251 * information to the handover {@link ConnectionService} specified by
252 * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}.
253 * <p>
254 * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the
255 * {@link ConnectionService} via the request extras when
256 * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
257 * is called to initate the handover.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700258 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700259 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
260 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700261 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700262 public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700263
264 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700265 * Call event sent from Telecom to the handover {@link ConnectionService} via
266 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
267 * to the {@link ConnectionService} has completed successfully.
268 * <p>
269 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700270 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700271 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
272 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700273 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700274 public static final String EVENT_HANDOVER_COMPLETE =
275 "android.telecom.event.HANDOVER_COMPLETE";
Tyler Gunn34a2b312017-06-23 08:32:00 -0700276
277 /**
278 * Call event sent from Telecom to the handover destination {@link ConnectionService} via
279 * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the
280 * source connection has disconnected. The {@link Bundle} parameter for the call event will be
281 * {@code null}.
282 * <p>
283 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
284 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700285 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
286 * APIs instead.
Tyler Gunn34a2b312017-06-23 08:32:00 -0700287 */
288 public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
289 "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
290
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700291 /**
292 * Call event sent from Telecom to the handover {@link ConnectionService} via
293 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
294 * to the {@link ConnectionService} has failed.
295 * <p>
296 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
297 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700298 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
299 * APIs instead.
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700300 */
301 public static final String EVENT_HANDOVER_FAILED =
302 "android.telecom.event.HANDOVER_FAILED";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700303
Tyler Gunnd5821842021-02-05 11:12:57 -0800304 /**
305 * Event reported from the Telecom stack to report an in-call diagnostic message which the
306 * dialer app may opt to display to the user. A diagnostic message is used to communicate
307 * scenarios the device has detected which may impact the quality of the ongoing call.
308 * <p>
309 * For example a problem with a bluetooth headset may generate a recommendation for the user to
310 * try using the speakerphone instead, or if the device detects it has entered a poor service
311 * area, the user might be warned so that they can finish their call prior to it dropping.
312 * <p>
313 * A diagnostic message is considered persistent in nature. When the user enters a poor service
314 * area, for example, the accompanying diagnostic message persists until they leave the area
315 * of poor service. Each message is accompanied with a {@link #EXTRA_DIAGNOSTIC_MESSAGE_ID}
316 * which uniquely identifies the diagnostic condition being reported. The framework raises a
317 * call event of type {@link #EVENT_CLEAR_DIAGNOSTIC_MESSAGE} when the condition reported has
318 * been cleared. The dialer app should display the diagnostic message until it is cleared.
319 * If multiple diagnostic messages are sent with different IDs (which have not yet been cleared)
320 * the dialer app should prioritize the most recently received message, but still provide the
321 * user with a means to review past messages.
322 * <p>
323 * The text of the message is found in {@link #EXTRA_DIAGNOSTIC_MESSAGE} in the form of a human
324 * readable {@link CharSequence} which is intended for display in the call UX.
325 * <p>
326 * The telecom framework audibly notifies the user of the presence of a diagnostic message, so
327 * the dialer app needs only to concern itself with visually displaying the message.
328 * <p>
329 * The dialer app receives this event via
330 * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)}.
331 */
332 public static final String EVENT_DISPLAY_DIAGNOSTIC_MESSAGE =
333 "android.telecom.event.DISPLAY_DIAGNOSTIC_MESSAGE";
334
335 /**
336 * Event reported from the telecom framework when a diagnostic message previously raised with
337 * {@link #EVENT_DISPLAY_DIAGNOSTIC_MESSAGE} has cleared and is no longer pertinent.
338 * <p>
339 * The {@link #EXTRA_DIAGNOSTIC_MESSAGE_ID} indicates the diagnostic message which has been
340 * cleared.
341 * <p>
342 * The dialer app receives this event via
343 * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)}.
344 */
345 public static final String EVENT_CLEAR_DIAGNOSTIC_MESSAGE =
346 "android.telecom.event.CLEAR_DIAGNOSTIC_MESSAGE";
347
348 /**
349 * Integer extra representing a message ID for a message posted via
350 * {@link #EVENT_DISPLAY_DIAGNOSTIC_MESSAGE}. Used to ensure that the dialer app knows when
351 * the message in question has cleared via {@link #EVENT_CLEAR_DIAGNOSTIC_MESSAGE}.
352 */
353 public static final String EXTRA_DIAGNOSTIC_MESSAGE_ID =
354 "android.telecom.extra.DIAGNOSTIC_MESSAGE_ID";
355
356 /**
357 * {@link CharSequence} extra used with {@link #EVENT_DISPLAY_DIAGNOSTIC_MESSAGE}. This is the
358 * diagnostic message the dialer app should display.
359 */
360 public static final String EXTRA_DIAGNOSTIC_MESSAGE =
361 "android.telecom.extra.DIAGNOSTIC_MESSAGE";
Tyler Gunnfacfdee2020-01-23 13:10:37 -0800362
363 /**
Thomas Nguyeneb427672023-02-15 15:42:34 -0800364 * Event reported from the Telecom stack to indicate that the {@link Connection} is not able to
365 * find any network and likely will not get connected. Upon receiving this event, the dialer
366 * app should show satellite SOS button if satellite is provisioned.
367 * <p>
368 * The dialer app receives this event via
369 * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)}.
370 * @hide
371 */
372 public static final String EVENT_DISPLAY_SOS_MESSAGE =
373 "android.telecom.event.DISPLAY_SOS_MESSAGE";
374
375 /**
Tyler Gunnfacfdee2020-01-23 13:10:37 -0800376 * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
377 * call because they have declined to answer it. This typically means that they are unable
378 * to answer the call at this time and would prefer it be sent to voicemail.
379 */
380 public static final int REJECT_REASON_DECLINED = 1;
381
382 /**
383 * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
384 * call because it is an unwanted call. This allows the user to indicate that they are
385 * rejecting a call because it is likely a nuisance call.
386 */
387 public static final int REJECT_REASON_UNWANTED = 2;
388
389 /**
390 * @hide
391 */
392 @IntDef(prefix = { "REJECT_REASON_" },
393 value = {REJECT_REASON_DECLINED, REJECT_REASON_UNWANTED})
394 @Retention(RetentionPolicy.SOURCE)
395 public @interface RejectReason {};
396
Ihab Awade63fadb2014-07-09 21:52:04 -0700397 public static class Details {
Tyler Gunn94f8f112018-12-17 09:56:11 -0800398 /** @hide */
399 @Retention(RetentionPolicy.SOURCE)
400 @IntDef(
401 prefix = { "DIRECTION_" },
402 value = {DIRECTION_UNKNOWN, DIRECTION_INCOMING, DIRECTION_OUTGOING})
403 public @interface CallDirection {}
404
405 /**
406 * Indicates that the call is neither and incoming nor an outgoing call. This can be the
407 * case for calls reported directly by a {@link ConnectionService} in special cases such as
408 * call handovers.
409 */
410 public static final int DIRECTION_UNKNOWN = -1;
411
412 /**
413 * Indicates that the call is an incoming call.
414 */
415 public static final int DIRECTION_INCOMING = 0;
416
417 /**
418 * Indicates that the call is an outgoing call.
419 */
420 public static final int DIRECTION_OUTGOING = 1;
421
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800422 /** Call can currently be put on hold or unheld. */
423 public static final int CAPABILITY_HOLD = 0x00000001;
424
425 /** Call supports the hold feature. */
426 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
427
428 /**
429 * Calls within a conference can be merged. A {@link ConnectionService} has the option to
430 * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
431 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
432 * capability allows a merge button to be shown while the conference call is in the foreground
433 * of the in-call UI.
434 * <p>
435 * This is only intended for use by a {@link Conference}.
436 */
437 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
438
439 /**
440 * Calls within a conference can be swapped between foreground and background.
441 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
442 * <p>
443 * This is only intended for use by a {@link Conference}.
444 */
445 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
446
447 /**
448 * @hide
449 */
Andrew Lee2378ea72015-04-29 14:38:11 -0700450 public static final int CAPABILITY_UNUSED_1 = 0x00000010;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800451
452 /** Call supports responding via text option. */
453 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
454
455 /** Call can be muted. */
456 public static final int CAPABILITY_MUTE = 0x00000040;
457
458 /**
459 * Call supports conference call management. This capability only applies to {@link Conference}
460 * calls which can have {@link Connection}s as children.
461 */
462 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
463
464 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700465 * Local device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800466 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700467 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800468
469 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700470 * Local device supports transmitting video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800471 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700472 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800473
474 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700475 * Local device supports bidirectional video calling.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800476 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700477 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700478 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800479
480 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700481 * Remote device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800482 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700483 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
484
485 /**
486 * Remote device supports transmitting video.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700487 */
488 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
489
490 /**
491 * Remote device supports bidirectional video calling.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700492 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700493 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700494 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800495
496 /**
497 * Call is able to be separated from its parent {@code Conference}, if any.
498 */
499 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
500
501 /**
502 * Call is able to be individually disconnected when in a {@code Conference}.
503 */
504 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
505
506 /**
Dong Zhou89f41eb2015-03-15 11:59:49 -0500507 * Speed up audio setup for MT call.
508 * @hide
509 */
Tyler Gunn96d6c402015-03-18 12:39:23 -0700510 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
511
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700512 /**
513 * Call can be upgraded to a video call.
Rekha Kumar07366812015-03-24 16:42:31 -0700514 * @hide
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800515 * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
516 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call
517 * whether or not video calling is supported.
Rekha Kumar07366812015-03-24 16:42:31 -0700518 */
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800519 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
Rekha Kumar07366812015-03-24 16:42:31 -0700520 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
521
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700522 /**
523 * For video calls, indicates whether the outgoing video for the call can be paused using
Yorke Lee32f24732015-05-12 16:18:03 -0700524 * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700525 */
526 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
527
Bryce Lee81901682015-08-28 16:38:02 -0700528 /**
529 * Call sends responses through connection.
530 * @hide
531 */
Tyler Gunnf97a0092016-01-19 15:59:34 -0800532 public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;
533
534 /**
535 * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
536 * <p>
537 * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
538 * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
539 * downgraded from a video call back to a VideoState of
540 * {@link VideoProfile#STATE_AUDIO_ONLY}.
541 * <p>
542 * Intuitively, a call which can be downgraded to audio should also have local and remote
543 * video
544 * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
545 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
546 */
547 public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
Bryce Lee81901682015-08-28 16:38:02 -0700548
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700549 /**
550 * When set for an external call, indicates that this {@code Call} can be pulled from a
551 * remote device to the current device.
552 * <p>
553 * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
554 * <p>
555 * An {@link InCallService} will only see calls with this capability if it has the
556 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
557 * in its manifest.
558 * <p>
559 * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
Tyler Gunn720c6642016-03-22 09:02:47 -0700560 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700561 */
562 public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
563
Pooja Jaind34698d2017-12-28 14:15:31 +0530564 /** Call supports the deflect feature. */
565 public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
566
Tyler Gunn0c62ef02020-02-11 14:39:43 -0800567 /**
568 * Call supports adding participants to the call via
Grace Jia8587ee52020-07-10 15:42:32 -0700569 * {@link #addConferenceParticipants(List)}. Once participants are added, the call becomes
570 * an adhoc conference call ({@link #PROPERTY_IS_ADHOC_CONFERENCE}).
Tyler Gunn0c62ef02020-02-11 14:39:43 -0800571 */
Ravi Paluri404babb2020-01-23 19:02:44 +0530572 public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
Ravi Palurif4b38e72020-02-05 12:35:41 +0530573
574 /**
575 * When set for a call, indicates that this {@code Call} can be transferred to another
576 * number.
Tyler Gunn460360d2020-07-29 10:21:45 -0700577 * Call supports the confirmed and unconfirmed call transfer feature.
Ravi Palurif4b38e72020-02-05 12:35:41 +0530578 *
579 * @hide
580 */
581 public static final int CAPABILITY_TRANSFER = 0x04000000;
582
583 /**
584 * When set for a call, indicates that this {@code Call} can be transferred to another
585 * ongoing call.
586 * Call supports the consultative call transfer feature.
587 *
588 * @hide
589 */
590 public static final int CAPABILITY_TRANSFER_CONSULTATIVE = 0x08000000;
591
Alvin Dey2f37d772018-05-18 23:16:10 +0530592 /**
593 * Indicates whether the remote party supports RTT or not to the UI.
594 */
595
596 public static final int CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT = 0x10000000;
597
Tyler Gunnd11a3152015-03-18 13:09:14 -0700598 //******************************************************************************************
Alvin Dey2f37d772018-05-18 23:16:10 +0530599 // Next CAPABILITY value: 0x20000000
Andrew Lee2378ea72015-04-29 14:38:11 -0700600 //******************************************************************************************
601
602 /**
603 * Whether the call is currently a conference.
604 */
605 public static final int PROPERTY_CONFERENCE = 0x00000001;
606
607 /**
608 * Whether the call is a generic conference, where we do not know the precise state of
609 * participants in the conference (eg. on CDMA).
610 */
611 public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
612
613 /**
614 * Whether the call is made while the device is in emergency callback mode.
615 */
616 public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
617
618 /**
619 * Connection is using WIFI.
620 */
621 public static final int PROPERTY_WIFI = 0x00000008;
622
623 /**
Tyler Gunn6b6ae552018-10-11 10:42:10 -0700624 * When set, the UI should indicate to the user that a call is using high definition
625 * audio.
626 * <p>
627 * The underlying {@link ConnectionService} is responsible for reporting this
628 * property. It is important to note that this property is not intended to report the
629 * actual audio codec being used for a Call, but whether the call should be indicated
630 * to the user as high definition.
631 * <p>
632 * The Android Telephony stack reports this property for calls based on a number
633 * of factors, including which audio codec is used and whether a call is using an HD
634 * codec end-to-end. Some mobile operators choose to suppress display of an HD indication,
635 * and in these cases this property will not be set for a call even if the underlying audio
636 * codec is in fact "high definition".
Andrew Lee2378ea72015-04-29 14:38:11 -0700637 */
638 public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
639
Tony Maka68dcce2015-12-17 09:31:18 +0000640 /**
Tony Mak53b5df42016-05-19 13:40:38 +0100641 * Whether the call is associated with the work profile.
642 */
643 public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;
644
645 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700646 * When set, indicates that this {@code Call} does not actually exist locally for the
647 * {@link ConnectionService}.
648 * <p>
649 * Consider, for example, a scenario where a user has two phones with the same phone number.
650 * When a user places a call on one device, the telephony stack can represent that call on
651 * the other device by adding it to the {@link ConnectionService} with the
Tyler Gunn720c6642016-03-22 09:02:47 -0700652 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700653 * <p>
654 * An {@link InCallService} will only see calls with this property if it has the
655 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
656 * in its manifest.
657 * <p>
Tyler Gunn720c6642016-03-22 09:02:47 -0700658 * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700659 */
660 public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
661
Brad Ebinger15847072016-05-18 11:08:36 -0700662 /**
663 * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
664 */
665 public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
666
Tyler Gunn24e18332017-02-10 09:42:49 -0800667 /**
668 * Indicates that the call is from a self-managed {@link ConnectionService}.
669 * <p>
670 * See also {@link Connection#PROPERTY_SELF_MANAGED}
671 */
672 public static final int PROPERTY_SELF_MANAGED = 0x00000100;
673
Eric Erfanianec881872017-12-06 16:27:53 -0800674 /**
675 * Indicates the call used Assisted Dialing.
Tyler Gunn5567d742019-10-31 13:04:37 -0700676 *
677 * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING
Eric Erfanianec881872017-12-06 16:27:53 -0800678 */
Tyler Gunnc9503d62020-01-27 10:30:51 -0800679 public static final int PROPERTY_ASSISTED_DIALING = 0x00000200;
Eric Erfanianec881872017-12-06 16:27:53 -0800680
Hall Liue9041242018-02-09 16:40:03 -0800681 /**
682 * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
683 * {@link RttCall} object that is used to send and receive text.
684 */
685 public static final int PROPERTY_RTT = 0x00000400;
686
Tyler Gunn5bd90852018-09-21 09:37:07 -0700687 /**
688 * Indicates that the call has been identified as the network as an emergency call. This
689 * property may be set for both incoming and outgoing calls which the network identifies as
690 * emergency calls.
691 */
692 public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 0x00000800;
693
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700694 /**
695 * Indicates that the call is using VoIP audio mode.
696 * <p>
697 * When this property is set, the {@link android.media.AudioManager} audio mode for this
698 * call will be {@link android.media.AudioManager#MODE_IN_COMMUNICATION}. When this
699 * property is not set, the audio mode for this call will be
700 * {@link android.media.AudioManager#MODE_IN_CALL}.
701 * <p>
702 * This property reflects changes made using {@link Connection#setAudioModeIsVoip(boolean)}.
703 * <p>
704 * You can use this property to determine whether an un-answered incoming call or a held
705 * call will use VoIP audio mode (if the call does not currently have focus, the system
706 * audio mode may not reflect the mode the call will use).
707 */
708 public static final int PROPERTY_VOIP_AUDIO_MODE = 0x00001000;
709
Ravi Paluri80aa2142019-12-02 11:57:37 +0530710 /**
711 * Indicates that the call is an adhoc conference call. This property can be set for both
Grace Jia8587ee52020-07-10 15:42:32 -0700712 * incoming and outgoing calls. An adhoc conference call is formed using
713 * {@link #addConferenceParticipants(List)},
714 * {@link TelecomManager#addNewIncomingConference(PhoneAccountHandle, Bundle)}, or
715 * {@link TelecomManager#startConference(List, Bundle)}, rather than by merging existing
716 * call using {@link #conference(Call)}.
Ravi Paluri80aa2142019-12-02 11:57:37 +0530717 */
718 public static final int PROPERTY_IS_ADHOC_CONFERENCE = 0x00002000;
719
Sooraj Sasindran64f05b12020-11-18 12:07:10 -0800720 /**
Sooraj Sasindranfa1e57a2021-03-22 13:44:14 -0700721 * Connection is using cross sim technology.
722 * <p>
723 * Indicates that the {@link Connection} is using a cross sim technology which would
724 * register IMS over internet APN of default data subscription.
725 * <p>
Sooraj Sasindran64f05b12020-11-18 12:07:10 -0800726 */
727 public static final int PROPERTY_CROSS_SIM = 0x00004000;
728
Andrew Lee2378ea72015-04-29 14:38:11 -0700729 //******************************************************************************************
Ravi Paluri80aa2142019-12-02 11:57:37 +0530730 // Next PROPERTY value: 0x00004000
Tyler Gunnd11a3152015-03-18 13:09:14 -0700731 //******************************************************************************************
Tyler Gunn068085b2015-02-06 13:56:52 -0800732
Tyler Gunn1e406ca2021-03-18 16:47:14 -0700733 private final @CallState int mState;
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800734 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700735 private final Uri mHandle;
736 private final int mHandlePresentation;
737 private final String mCallerDisplayName;
738 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700739 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700740 private final int mCallCapabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700741 private final int mCallProperties;
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800742 private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700743 private final DisconnectCause mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700744 private final long mConnectTimeMillis;
745 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700746 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700747 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700748 private final Bundle mExtras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700749 private final Bundle mIntentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700750 private final long mCreationTimeMillis;
Hall Liuef98bf82020-01-09 15:22:44 -0800751 private final String mContactDisplayName;
Tyler Gunn94f8f112018-12-17 09:56:11 -0800752 private final @CallDirection int mCallDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700753 private final @Connection.VerificationStatus int mCallerNumberVerificationStatus;
Edgar Arriagae5bec822022-10-14 14:25:43 -0700754 private final Uri mContactPhotoUri;
Ihab Awade63fadb2014-07-09 21:52:04 -0700755
756 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800757 * Whether the supplied capabilities supports the specified capability.
758 *
759 * @param capabilities A bit field of capabilities.
760 * @param capability The capability to check capabilities for.
761 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800762 */
763 public static boolean can(int capabilities, int capability) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800764 return (capabilities & capability) == capability;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800765 }
766
767 /**
768 * Whether the capabilities of this {@code Details} supports the specified capability.
769 *
770 * @param capability The capability to check capabilities for.
771 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800772 */
773 public boolean can(int capability) {
774 return can(mCallCapabilities, capability);
775 }
776
777 /**
778 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
779 *
780 * @param capabilities A capability bit field.
781 * @return A human readable string representation.
782 */
783 public static String capabilitiesToString(int capabilities) {
784 StringBuilder builder = new StringBuilder();
785 builder.append("[Capabilities:");
786 if (can(capabilities, CAPABILITY_HOLD)) {
787 builder.append(" CAPABILITY_HOLD");
788 }
789 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
790 builder.append(" CAPABILITY_SUPPORT_HOLD");
791 }
792 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
793 builder.append(" CAPABILITY_MERGE_CONFERENCE");
794 }
795 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
796 builder.append(" CAPABILITY_SWAP_CONFERENCE");
797 }
798 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
799 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
800 }
801 if (can(capabilities, CAPABILITY_MUTE)) {
802 builder.append(" CAPABILITY_MUTE");
803 }
804 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
805 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
806 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700807 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
808 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
809 }
810 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
811 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
812 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700813 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
814 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800815 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700816 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
817 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
818 }
819 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
820 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
821 }
Tyler Gunnf97a0092016-01-19 15:59:34 -0800822 if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
823 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
824 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700825 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
826 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800827 }
Dong Zhou89f41eb2015-03-15 11:59:49 -0500828 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
Tyler Gunnd11a3152015-03-18 13:09:14 -0700829 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
Dong Zhou89f41eb2015-03-15 11:59:49 -0500830 }
Rekha Kumar07366812015-03-24 16:42:31 -0700831 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
832 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
833 }
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700834 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
835 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
836 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700837 if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
838 builder.append(" CAPABILITY_CAN_PULL_CALL");
839 }
Pooja Jaind34698d2017-12-28 14:15:31 +0530840 if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
841 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
842 }
Ravi Paluri404babb2020-01-23 19:02:44 +0530843 if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) {
844 builder.append(" CAPABILITY_ADD_PARTICIPANT");
845 }
Ravi Palurif4b38e72020-02-05 12:35:41 +0530846 if (can(capabilities, CAPABILITY_TRANSFER)) {
847 builder.append(" CAPABILITY_TRANSFER");
848 }
849 if (can(capabilities, CAPABILITY_TRANSFER_CONSULTATIVE)) {
850 builder.append(" CAPABILITY_TRANSFER_CONSULTATIVE");
851 }
Alvin Dey2f37d772018-05-18 23:16:10 +0530852 if (can(capabilities, CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT)) {
853 builder.append(" CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT");
854 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800855 builder.append("]");
856 return builder.toString();
857 }
858
859 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700860 * Whether the supplied properties includes the specified property.
861 *
862 * @param properties A bit field of properties.
863 * @param property The property to check properties for.
864 * @return Whether the specified property is supported.
865 */
866 public static boolean hasProperty(int properties, int property) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800867 return (properties & property) == property;
Andrew Lee2378ea72015-04-29 14:38:11 -0700868 }
869
870 /**
871 * Whether the properties of this {@code Details} includes the specified property.
872 *
873 * @param property The property to check properties for.
874 * @return Whether the specified property is supported.
875 */
876 public boolean hasProperty(int property) {
877 return hasProperty(mCallProperties, property);
878 }
879
880 /**
881 * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
882 *
883 * @param properties A property bit field.
884 * @return A human readable string representation.
885 */
886 public static String propertiesToString(int properties) {
887 StringBuilder builder = new StringBuilder();
888 builder.append("[Properties:");
889 if (hasProperty(properties, PROPERTY_CONFERENCE)) {
890 builder.append(" PROPERTY_CONFERENCE");
891 }
892 if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
893 builder.append(" PROPERTY_GENERIC_CONFERENCE");
894 }
895 if (hasProperty(properties, PROPERTY_WIFI)) {
896 builder.append(" PROPERTY_WIFI");
897 }
898 if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
899 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
900 }
901 if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
Yorke Leebe2a4a22015-06-12 10:10:55 -0700902 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
Andrew Lee2378ea72015-04-29 14:38:11 -0700903 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700904 if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
905 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
906 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700907 if (hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
Brad Ebinger15847072016-05-18 11:08:36 -0700908 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
909 }
Tyler Gunnc9503d62020-01-27 10:30:51 -0800910 if (hasProperty(properties, PROPERTY_ASSISTED_DIALING)) {
Eric Erfanianec881872017-12-06 16:27:53 -0800911 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
912 }
Tyler Gunn5bd90852018-09-21 09:37:07 -0700913 if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
914 builder.append(" PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL");
915 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700916 if (hasProperty(properties, PROPERTY_RTT)) {
917 builder.append(" PROPERTY_RTT");
918 }
919 if (hasProperty(properties, PROPERTY_VOIP_AUDIO_MODE)) {
920 builder.append(" PROPERTY_VOIP_AUDIO_MODE");
921 }
Ravi Paluri80aa2142019-12-02 11:57:37 +0530922 if (hasProperty(properties, PROPERTY_IS_ADHOC_CONFERENCE)) {
923 builder.append(" PROPERTY_IS_ADHOC_CONFERENCE");
924 }
Sooraj Sasindran64f05b12020-11-18 12:07:10 -0800925 if (hasProperty(properties, PROPERTY_CROSS_SIM)) {
926 builder.append(" PROPERTY_CROSS_SIM");
927 }
Andrew Lee2378ea72015-04-29 14:38:11 -0700928 builder.append("]");
929 return builder.toString();
930 }
931
Tyler Gunn1e406ca2021-03-18 16:47:14 -0700932 /**
933 * @return the state of the {@link Call} represented by this {@link Call.Details}.
934 */
935 public final @CallState int getState() {
936 return mState;
937 }
938
Grant Menke626dd262023-07-24 15:19:36 -0700939 /**
940 * @return the Telecom identifier associated with this {@link Call} . This is not a stable
941 * identifier and is not guaranteed to be unique across device reboots.
942 */
943 public @NonNull String getId() { return mTelecomCallId; }
944
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800945 /** {@hide} */
Hall Liu31de23d2019-10-11 15:38:29 -0700946 @TestApi
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800947 public String getTelecomCallId() {
948 return mTelecomCallId;
949 }
950
Andrew Lee2378ea72015-04-29 14:38:11 -0700951 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700952 * @return The handle (e.g., phone number) to which the {@code Call} is currently
953 * connected.
954 */
955 public Uri getHandle() {
956 return mHandle;
957 }
958
959 /**
960 * @return The presentation requirements for the handle. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700961 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700962 */
963 public int getHandlePresentation() {
964 return mHandlePresentation;
965 }
966
967 /**
Edgar Arriagae5bec822022-10-14 14:25:43 -0700968 * @return The contact photo URI which corresponds to
969 * {@link android.provider.ContactsContract.PhoneLookup#PHOTO_URI}, or {@code null} if the
970 * lookup is not yet complete, if there's no contacts entry for the caller,
971 * or if the {@link InCallService} does not hold the
972 * {@link android.Manifest.permission#READ_CONTACTS} permission.
973 */
974 public @Nullable Uri getContactPhotoUri() {
975 return mContactPhotoUri;
976 }
977
978 /**
Tyler Gunnd081f042018-12-04 12:56:45 -0800979 * The display name for the caller.
980 * <p>
981 * This is the name as reported by the {@link ConnectionService} associated with this call.
Tyler Gunnd081f042018-12-04 12:56:45 -0800982 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700983 * @return The display name for the caller.
984 */
985 public String getCallerDisplayName() {
986 return mCallerDisplayName;
987 }
988
989 /**
990 * @return The presentation requirements for the caller display name. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700991 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700992 */
993 public int getCallerDisplayNamePresentation() {
994 return mCallerDisplayNamePresentation;
995 }
996
997 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700998 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
999 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -07001000 */
Evan Charlton8c8a0622014-07-20 12:31:00 -07001001 public PhoneAccountHandle getAccountHandle() {
1002 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -07001003 }
1004
1005 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001006 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
1007 * {@code CAPABILITY_*} constants in this class.
Ihab Awade63fadb2014-07-09 21:52:04 -07001008 */
Ihab Awad5d0410f2014-07-30 10:07:40 -07001009 public int getCallCapabilities() {
1010 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -07001011 }
1012
1013 /**
Andrew Lee2378ea72015-04-29 14:38:11 -07001014 * @return A bitmask of the properties of the {@code Call}, as defined by the various
1015 * {@code PROPERTY_*} constants in this class.
Andrew Lee223ad142014-08-27 16:33:08 -07001016 */
1017 public int getCallProperties() {
1018 return mCallProperties;
1019 }
1020
1021 /**
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -08001022 * @return a bitmask of the audio routes available for the call.
1023 *
1024 * @hide
1025 */
1026 public int getSupportedAudioRoutes() {
1027 return mSupportedAudioRoutes;
1028 }
1029
1030 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001031 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
Nancy Chenf4cf77c2014-09-19 10:53:21 -07001032 * by {@link android.telecom.DisconnectCause}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001033 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001034 public DisconnectCause getDisconnectCause() {
1035 return mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -07001036 }
1037
1038 /**
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001039 * Returns the time the {@link Call} connected (i.e. became active). This information is
1040 * updated periodically, but user interfaces should not rely on this to display the "call
1041 * time clock". For the time when the call was first added to Telecom, see
1042 * {@link #getCreationTimeMillis()}.
1043 *
1044 * @return The time the {@link Call} connected in milliseconds since the epoch.
Ihab Awade63fadb2014-07-09 21:52:04 -07001045 */
Jay Shrauner164a0ac2015-04-14 18:16:10 -07001046 public final long getConnectTimeMillis() {
Ihab Awade63fadb2014-07-09 21:52:04 -07001047 return mConnectTimeMillis;
1048 }
1049
1050 /**
1051 * @return Information about any calling gateway the {@code Call} may be using.
1052 */
1053 public GatewayInfo getGatewayInfo() {
1054 return mGatewayInfo;
1055 }
1056
Andrew Lee7a341382014-07-15 17:05:08 -07001057 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -07001058 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -07001059 */
1060 public int getVideoState() {
1061 return mVideoState;
1062 }
1063
Ihab Awad5d0410f2014-07-30 10:07:40 -07001064 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001065 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
Ihab Awad5d0410f2014-07-30 10:07:40 -07001066 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -07001067 */
1068 public StatusHints getStatusHints() {
1069 return mStatusHints;
1070 }
1071
Nancy Chen10798dc2014-08-08 14:00:25 -07001072 /**
Santos Cordon6b7f9552015-05-27 17:21:45 -07001073 * @return The extras associated with this call.
Nancy Chen10798dc2014-08-08 14:00:25 -07001074 */
1075 public Bundle getExtras() {
1076 return mExtras;
1077 }
1078
Santos Cordon6b7f9552015-05-27 17:21:45 -07001079 /**
1080 * @return The extras used with the original intent to place this call.
1081 */
1082 public Bundle getIntentExtras() {
1083 return mIntentExtras;
1084 }
1085
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001086 /**
1087 * Returns the time when the call was first created and added to Telecom. This is the same
1088 * time that is logged as the start time in the Call Log (see
1089 * {@link android.provider.CallLog.Calls#DATE}). To determine when the call was connected
1090 * (became active), see {@link #getConnectTimeMillis()}.
1091 *
1092 * @return The creation time of the call, in millis since the epoch.
1093 */
1094 public long getCreationTimeMillis() {
1095 return mCreationTimeMillis;
1096 }
1097
Tyler Gunnd081f042018-12-04 12:56:45 -08001098 /**
Hall Liuef98bf82020-01-09 15:22:44 -08001099 * Returns the name of the caller on the remote end, as derived from a
1100 * {@link android.provider.ContactsContract} lookup of the call's handle.
1101 * @return The name of the caller, or {@code null} if the lookup is not yet complete, if
1102 * there's no contacts entry for the caller, or if the {@link InCallService} does
1103 * not hold the {@link android.Manifest.permission#READ_CONTACTS} permission.
1104 */
1105 public @Nullable String getContactDisplayName() {
1106 return mContactDisplayName;
1107 }
1108
1109 /**
Tyler Gunn94f8f112018-12-17 09:56:11 -08001110 * Indicates whether the call is an incoming or outgoing call.
1111 * @return The call's direction.
1112 */
1113 public @CallDirection int getCallDirection() {
1114 return mCallDirection;
1115 }
1116
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001117 /**
1118 * Gets the verification status for the phone number of an incoming call as identified in
1119 * ATIS-1000082.
Tyler Gunn9c642492020-10-08 13:37:03 -07001120 * <p>
1121 * For incoming calls, the number verification status indicates whether the device was
1122 * able to verify the authenticity of the calling number using the STIR process outlined
1123 * in ATIS-1000082. {@link Connection#VERIFICATION_STATUS_NOT_VERIFIED} indicates that
1124 * the network was not able to use STIR to verify the caller's number (i.e. nothing is
1125 * known regarding the authenticity of the number.
1126 * {@link Connection#VERIFICATION_STATUS_PASSED} indicates that the network was able to
1127 * use STIR to verify the caller's number. This indicates that the network has a high
1128 * degree of confidence that the incoming call actually originated from the indicated
1129 * number. {@link Connection#VERIFICATION_STATUS_FAILED} indicates that the network's
1130 * STIR verification did not pass. This indicates that the incoming call may not
1131 * actually be from the indicated number. This could occur if, for example, the caller
1132 * is using an impersonated phone number.
1133 * <p>
1134 * A {@link CallScreeningService} can use this information to help determine if an
1135 * incoming call is potentially an unwanted call. A verification status of
1136 * {@link Connection#VERIFICATION_STATUS_FAILED} indicates that an incoming call may not
1137 * actually be from the number indicated on the call (i.e. impersonated number) and that it
1138 * should potentially be blocked. Likewise,
1139 * {@link Connection#VERIFICATION_STATUS_PASSED} can be used as a positive signal to
1140 * help clarify that the incoming call is originating from the indicated number and it
1141 * is less likely to be an undesirable call.
1142 * <p>
1143 * An {@link InCallService} can use this information to provide a visual indicator to the
1144 * user regarding the verification status of a call and to help identify calls from
1145 * potentially impersonated numbers.
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001146 * @return the verification status.
1147 */
1148 public @Connection.VerificationStatus int getCallerNumberVerificationStatus() {
1149 return mCallerNumberVerificationStatus;
1150 }
1151
Ihab Awade63fadb2014-07-09 21:52:04 -07001152 @Override
1153 public boolean equals(Object o) {
1154 if (o instanceof Details) {
1155 Details d = (Details) o;
1156 return
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001157 Objects.equals(mState, d.mState) &&
Ihab Awade63fadb2014-07-09 21:52:04 -07001158 Objects.equals(mHandle, d.mHandle) &&
1159 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
1160 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
1161 Objects.equals(mCallerDisplayNamePresentation,
1162 d.mCallerDisplayNamePresentation) &&
Evan Charlton8c8a0622014-07-20 12:31:00 -07001163 Objects.equals(mAccountHandle, d.mAccountHandle) &&
Ihab Awad5d0410f2014-07-30 10:07:40 -07001164 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Andrew Lee223ad142014-08-27 16:33:08 -07001165 Objects.equals(mCallProperties, d.mCallProperties) &&
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001166 Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
Ihab Awade63fadb2014-07-09 21:52:04 -07001167 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Andrew Lee85f5d422014-07-11 17:22:03 -07001168 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Evan Charlton5b49ade2014-07-15 17:03:20 -07001169 Objects.equals(mVideoState, d.mVideoState) &&
Nancy Chen10798dc2014-08-08 14:00:25 -07001170 Objects.equals(mStatusHints, d.mStatusHints) &&
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07001171 areBundlesEqual(mExtras, d.mExtras) &&
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001172 areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
Tyler Gunnd081f042018-12-04 12:56:45 -08001173 Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis) &&
Hall Liuef98bf82020-01-09 15:22:44 -08001174 Objects.equals(mContactDisplayName, d.mContactDisplayName) &&
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001175 Objects.equals(mCallDirection, d.mCallDirection) &&
1176 Objects.equals(mCallerNumberVerificationStatus,
Edgar Arriagae5bec822022-10-14 14:25:43 -07001177 d.mCallerNumberVerificationStatus) &&
1178 Objects.equals(mContactPhotoUri, d.mContactPhotoUri);
Ihab Awade63fadb2014-07-09 21:52:04 -07001179 }
1180 return false;
1181 }
1182
1183 @Override
1184 public int hashCode() {
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001185 return Objects.hash(mState,
1186 mHandle,
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001187 mHandlePresentation,
1188 mCallerDisplayName,
1189 mCallerDisplayNamePresentation,
1190 mAccountHandle,
1191 mCallCapabilities,
1192 mCallProperties,
1193 mDisconnectCause,
1194 mConnectTimeMillis,
1195 mGatewayInfo,
1196 mVideoState,
1197 mStatusHints,
1198 mExtras,
1199 mIntentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -08001200 mCreationTimeMillis,
Hall Liuef98bf82020-01-09 15:22:44 -08001201 mContactDisplayName,
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001202 mCallDirection,
Edgar Arriagae5bec822022-10-14 14:25:43 -07001203 mCallerNumberVerificationStatus,
1204 mContactPhotoUri);
Ihab Awade63fadb2014-07-09 21:52:04 -07001205 }
1206
1207 /** {@hide} */
1208 public Details(
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001209 @CallState int state,
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001210 String telecomCallId,
Ihab Awade63fadb2014-07-09 21:52:04 -07001211 Uri handle,
1212 int handlePresentation,
1213 String callerDisplayName,
1214 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -07001215 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -07001216 int capabilities,
Andrew Lee223ad142014-08-27 16:33:08 -07001217 int properties,
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001218 DisconnectCause disconnectCause,
Ihab Awade63fadb2014-07-09 21:52:04 -07001219 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -07001220 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -07001221 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -07001222 StatusHints statusHints,
Santos Cordon6b7f9552015-05-27 17:21:45 -07001223 Bundle extras,
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001224 Bundle intentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -08001225 long creationTimeMillis,
Hall Liuef98bf82020-01-09 15:22:44 -08001226 String contactDisplayName,
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001227 int callDirection,
Edgar Arriagae5bec822022-10-14 14:25:43 -07001228 int callerNumberVerificationStatus,
1229 Uri contactPhotoUri) {
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001230 mState = state;
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001231 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001232 mHandle = handle;
1233 mHandlePresentation = handlePresentation;
1234 mCallerDisplayName = callerDisplayName;
1235 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -07001236 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -07001237 mCallCapabilities = capabilities;
Andrew Lee223ad142014-08-27 16:33:08 -07001238 mCallProperties = properties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001239 mDisconnectCause = disconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -07001240 mConnectTimeMillis = connectTimeMillis;
1241 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -07001242 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -07001243 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -07001244 mExtras = extras;
Santos Cordon6b7f9552015-05-27 17:21:45 -07001245 mIntentExtras = intentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001246 mCreationTimeMillis = creationTimeMillis;
Hall Liuef98bf82020-01-09 15:22:44 -08001247 mContactDisplayName = contactDisplayName;
Tyler Gunn94f8f112018-12-17 09:56:11 -08001248 mCallDirection = callDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001249 mCallerNumberVerificationStatus = callerNumberVerificationStatus;
Edgar Arriagae5bec822022-10-14 14:25:43 -07001250 mContactPhotoUri = contactPhotoUri;
Ihab Awade63fadb2014-07-09 21:52:04 -07001251 }
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001252
1253 /** {@hide} */
1254 public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
1255 return new Details(
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001256 parcelableCall.getState(),
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001257 parcelableCall.getId(),
1258 parcelableCall.getHandle(),
1259 parcelableCall.getHandlePresentation(),
1260 parcelableCall.getCallerDisplayName(),
1261 parcelableCall.getCallerDisplayNamePresentation(),
1262 parcelableCall.getAccountHandle(),
1263 parcelableCall.getCapabilities(),
1264 parcelableCall.getProperties(),
1265 parcelableCall.getDisconnectCause(),
1266 parcelableCall.getConnectTimeMillis(),
1267 parcelableCall.getGatewayInfo(),
1268 parcelableCall.getVideoState(),
1269 parcelableCall.getStatusHints(),
1270 parcelableCall.getExtras(),
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001271 parcelableCall.getIntentExtras(),
Tyler Gunnd081f042018-12-04 12:56:45 -08001272 parcelableCall.getCreationTimeMillis(),
Hall Liuef98bf82020-01-09 15:22:44 -08001273 parcelableCall.getContactDisplayName(),
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001274 parcelableCall.getCallDirection(),
Edgar Arriagae5bec822022-10-14 14:25:43 -07001275 parcelableCall.getCallerNumberVerificationStatus(),
1276 parcelableCall.getContactPhotoUri()
1277 );
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001278 }
Santos Cordon3c20d632016-02-25 16:12:35 -08001279
1280 @Override
1281 public String toString() {
1282 StringBuilder sb = new StringBuilder();
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001283 sb.append("[id: ");
1284 sb.append(mTelecomCallId);
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001285 sb.append(", state: ");
1286 sb.append(Call.stateToString(mState));
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001287 sb.append(", pa: ");
Santos Cordon3c20d632016-02-25 16:12:35 -08001288 sb.append(mAccountHandle);
1289 sb.append(", hdl: ");
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001290 sb.append(Log.piiHandle(mHandle));
1291 sb.append(", hdlPres: ");
1292 sb.append(mHandlePresentation);
1293 sb.append(", videoState: ");
1294 sb.append(VideoProfile.videoStateToString(mVideoState));
Santos Cordon3c20d632016-02-25 16:12:35 -08001295 sb.append(", caps: ");
1296 sb.append(capabilitiesToString(mCallCapabilities));
1297 sb.append(", props: ");
Tyler Gunn720c6642016-03-22 09:02:47 -07001298 sb.append(propertiesToString(mCallProperties));
Santos Cordon3c20d632016-02-25 16:12:35 -08001299 sb.append("]");
1300 return sb.toString();
1301 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001302 }
1303
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001304 /**
1305 * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
1306 * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
1307 * implementation.
1308 * <p>
1309 * You can handle these callbacks by extending the {@link Callback} class and overriding the
1310 * callbacks that your {@link InCallService} is interested in. The callback methods include the
1311 * {@link Call} for which the callback applies, allowing reuse of a single instance of your
1312 * {@link Callback} implementation, if desired.
1313 * <p>
1314 * Use {@link Call#registerCallback(Callback)} to register your callback(s). Ensure
1315 * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
1316 * (typically in {@link InCallService#onCallRemoved(Call)}).
1317 * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
1318 * reach your implementation of {@link Callback}, so it is important to register your callback
1319 * as soon as your {@link InCallService} is notified of a new call via
1320 * {@link InCallService#onCallAdded(Call)}.
1321 */
Andrew Leeda80c872015-04-15 14:09:50 -07001322 public static abstract class Callback {
Ihab Awade63fadb2014-07-09 21:52:04 -07001323 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001324 * @hide
1325 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001326 @IntDef(prefix = { "HANDOVER_" },
1327 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
Tyler Gunn5c60d712018-03-16 09:53:44 -07001328 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
Tyler Gunn9d127732018-03-02 15:45:51 -08001329 HANDOVER_FAILURE_UNKNOWN})
Sanket Padawea8eddd42017-11-03 11:07:35 -07001330 @Retention(RetentionPolicy.SOURCE)
1331 public @interface HandoverFailureErrors {}
1332
1333 /**
1334 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
Tyler Gunn9d127732018-03-02 15:45:51 -08001335 * to handover the call to rejects the handover request.
1336 * <p>
1337 * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
1338 * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
1339 * {@code null} {@link Connection} from
1340 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1341 * ConnectionRequest)}.
1342 * <p>
1343 * For more information on call handovers, see
1344 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001345 */
1346 public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
1347
1348 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001349 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1350 * is initiated but the source or destination app does not support handover.
1351 * <p>
1352 * Will be returned when a handover is requested via
1353 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
1354 * {@link PhoneAccountHandle} does not declare
1355 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}. May also be returned when a handover is
1356 * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
1357 * {@link Details#getAccountHandle()}) does not declare
1358 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
1359 * <p>
1360 * For more information on call handovers, see
1361 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001362 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001363 public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001364
1365 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001366 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
1367 * user rejects the handover request.
1368 * <p>
1369 * For more information on call handovers, see
1370 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001371 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001372 public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001373
Sanket Padawe85291f62017-12-01 13:59:27 -08001374 /**
1375 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
1376 * is ongoing emergency call.
Tyler Gunn9d127732018-03-02 15:45:51 -08001377 * <p>
1378 * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
1379 * called on an emergency call, or if any other call is an emergency call.
1380 * <p>
1381 * Handovers are not permitted while there are ongoing emergency calls.
1382 * <p>
1383 * For more information on call handovers, see
1384 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawe85291f62017-12-01 13:59:27 -08001385 */
Tyler Gunn5c60d712018-03-16 09:53:44 -07001386 public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
Sanket Padawe85291f62017-12-01 13:59:27 -08001387
Tyler Gunn9d127732018-03-02 15:45:51 -08001388 /**
1389 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1390 * fails for an unknown reason.
1391 * <p>
1392 * For more information on call handovers, see
1393 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
1394 */
1395 public static final int HANDOVER_FAILURE_UNKNOWN = 5;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001396
1397 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001398 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
1399 *
Ihab Awade63fadb2014-07-09 21:52:04 -07001400 * @param call The {@code Call} invoking this method.
1401 * @param state The new state of the {@code Call}.
1402 */
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001403 public void onStateChanged(Call call, @CallState int state) {}
Ihab Awade63fadb2014-07-09 21:52:04 -07001404
1405 /**
1406 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
1407 *
1408 * @param call The {@code Call} invoking this method.
1409 * @param parent The new parent of the {@code Call}.
1410 */
1411 public void onParentChanged(Call call, Call parent) {}
1412
1413 /**
1414 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
1415 *
1416 * @param call The {@code Call} invoking this method.
1417 * @param children The new children of the {@code Call}.
1418 */
1419 public void onChildrenChanged(Call call, List<Call> children) {}
1420
1421 /**
1422 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
1423 *
1424 * @param call The {@code Call} invoking this method.
1425 * @param details A {@code Details} object describing the {@code Call}.
1426 */
1427 public void onDetailsChanged(Call call, Details details) {}
1428
1429 /**
1430 * Invoked when the text messages that can be used as responses to the incoming
1431 * {@code Call} are loaded from the relevant database.
1432 * See {@link #getCannedTextResponses()}.
1433 *
1434 * @param call The {@code Call} invoking this method.
1435 * @param cannedTextResponses The text messages useable as responses.
1436 */
1437 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
1438
1439 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001440 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
1441 * character. This causes the post-dial signals to stop pending user confirmation. An
1442 * implementation should present this choice to the user and invoke
1443 * {@link #postDialContinue(boolean)} when the user makes the choice.
1444 *
1445 * @param call The {@code Call} invoking this method.
1446 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
1447 */
1448 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
1449
1450 /**
Andrew Lee50aca232014-07-22 16:41:54 -07001451 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -07001452 *
1453 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -07001454 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001455 */
Andrew Lee50aca232014-07-22 16:41:54 -07001456 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -07001457
1458 /**
1459 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
1460 * up their UI for the {@code Call} in response to state transitions. Specifically,
1461 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
1462 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
1463 * clients should wait for this method to be invoked.
1464 *
1465 * @param call The {@code Call} being destroyed.
1466 */
1467 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001468
1469 /**
1470 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
1471 * conferenced.
1472 *
1473 * @param call The {@code Call} being updated.
1474 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
1475 * conferenced.
1476 */
1477 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001478
1479 /**
Tyler Gunn5567d742019-10-31 13:04:37 -07001480 * Invoked when a {@link Call} receives an event from its associated {@link Connection} or
1481 * {@link Conference}.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001482 * <p>
1483 * Where possible, the Call should make an attempt to handle {@link Connection} events which
1484 * are part of the {@code android.telecom.*} namespace. The Call should ignore any events
1485 * it does not wish to handle. Unexpected events should be handled gracefully, as it is
1486 * possible that a {@link ConnectionService} has defined its own Connection events which a
1487 * Call is not aware of.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001488 * <p>
Tyler Gunn5567d742019-10-31 13:04:37 -07001489 * See {@link Connection#sendConnectionEvent(String, Bundle)},
1490 * {@link Conference#sendConferenceEvent(String, Bundle)}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001491 *
1492 * @param call The {@code Call} receiving the event.
1493 * @param event The event.
1494 * @param extras Extras associated with the connection event.
1495 */
1496 public void onConnectionEvent(Call call, String event, Bundle extras) {}
Hall Liu95d55872017-01-25 17:12:49 -08001497
1498 /**
1499 * Invoked when the RTT mode changes for this call.
1500 * @param call The call whose RTT mode has changed.
1501 * @param mode the new RTT mode, one of
1502 * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
1503 * or {@link RttCall#RTT_MODE_VCO}
1504 */
1505 public void onRttModeChanged(Call call, int mode) {}
1506
1507 /**
1508 * Invoked when the call's RTT status changes, either from off to on or from on to off.
1509 * @param call The call whose RTT status has changed.
1510 * @param enabled whether RTT is now enabled or disabled
1511 * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
1512 * on, null otherwise.
1513 */
1514 public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
1515
1516 /**
1517 * Invoked when the remote end of the connection has requested that an RTT communication
1518 * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
1519 * with the same ID that this method is invoked with.
1520 * @param call The call which the RTT request was placed on
1521 * @param id The ID of the request.
1522 */
1523 public void onRttRequest(Call call, int id) {}
Hall Liu57006aa2017-02-06 10:49:48 -08001524
1525 /**
1526 * Invoked when the RTT session failed to initiate for some reason, including rejection
1527 * by the remote party.
Tyler Gunnb9a04962022-02-17 08:23:54 -08001528 * <p>
1529 * This callback will ONLY be invoked to report a failure related to a user initiated
1530 * session modification request (i.e. {@link Call#sendRttRequest()}).
1531 * <p>
1532 * If a call is initiated with {@link TelecomManager#EXTRA_START_CALL_WITH_RTT} specified,
1533 * the availability of RTT can be determined by checking {@link Details#PROPERTY_RTT}
1534 * once the call enters state {@link Details#STATE_ACTIVE}.
1535 *
Hall Liu57006aa2017-02-06 10:49:48 -08001536 * @param call The call which the RTT initiation failure occurred on.
1537 * @param reason One of the status codes defined in
Tyler Gunnb9a04962022-02-17 08:23:54 -08001538 * {@link android.telecom.Connection.RttModifyStatus}, with the exception of
1539 * {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
Hall Liu57006aa2017-02-06 10:49:48 -08001540 */
Tyler Gunnb9a04962022-02-17 08:23:54 -08001541 public void onRttInitiationFailure(Call call,
1542 @android.telecom.Connection.RttModifyStatus.RttSessionModifyStatus int reason) {}
Sanket Padawea8eddd42017-11-03 11:07:35 -07001543
1544 /**
1545 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1546 * has completed successfully.
Tyler Gunn9d127732018-03-02 15:45:51 -08001547 * <p>
1548 * For a full discussion of the handover process and the APIs involved, see
1549 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1550 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001551 * @param call The call which had initiated handover.
1552 */
1553 public void onHandoverComplete(Call call) {}
1554
1555 /**
1556 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1557 * has failed.
Tyler Gunn9d127732018-03-02 15:45:51 -08001558 * <p>
1559 * For a full discussion of the handover process and the APIs involved, see
1560 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1561 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001562 * @param call The call which had initiated handover.
Tyler Gunn9d127732018-03-02 15:45:51 -08001563 * @param failureReason Error reason for failure.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001564 */
1565 public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
Hall Liu95d55872017-01-25 17:12:49 -08001566 }
1567
1568 /**
1569 * A class that holds the state that describes the state of the RTT channel to the remote
1570 * party, if it is active.
1571 */
1572 public static final class RttCall {
Hall Liu07094df2017-02-28 15:17:44 -08001573 /** @hide */
Hall Liu95d55872017-01-25 17:12:49 -08001574 @Retention(RetentionPolicy.SOURCE)
1575 @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
1576 public @interface RttAudioMode {}
1577
1578 /**
1579 * For metrics use. Default value in the proto.
1580 * @hide
1581 */
1582 public static final int RTT_MODE_INVALID = 0;
1583
1584 /**
1585 * Indicates that there should be a bidirectional audio stream between the two parties
1586 * on the call.
1587 */
1588 public static final int RTT_MODE_FULL = 1;
1589
1590 /**
1591 * Indicates that the local user should be able to hear the audio stream from the remote
1592 * user, but not vice versa. Equivalent to muting the microphone.
1593 */
1594 public static final int RTT_MODE_HCO = 2;
1595
1596 /**
1597 * Indicates that the remote user should be able to hear the audio stream from the local
1598 * user, but not vice versa. Equivalent to setting the volume to zero.
1599 */
1600 public static final int RTT_MODE_VCO = 3;
1601
1602 private static final int READ_BUFFER_SIZE = 1000;
1603
1604 private InputStreamReader mReceiveStream;
1605 private OutputStreamWriter mTransmitStream;
1606 private int mRttMode;
1607 private final InCallAdapter mInCallAdapter;
Hall Liu57006aa2017-02-06 10:49:48 -08001608 private final String mTelecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001609 private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
1610
1611 /**
1612 * @hide
1613 */
Hall Liu57006aa2017-02-06 10:49:48 -08001614 public RttCall(String telecomCallId, InputStreamReader receiveStream,
1615 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
1616 mTelecomCallId = telecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001617 mReceiveStream = receiveStream;
1618 mTransmitStream = transmitStream;
1619 mRttMode = mode;
1620 mInCallAdapter = inCallAdapter;
1621 }
1622
1623 /**
1624 * Returns the current RTT audio mode.
1625 * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
1626 * {@link #RTT_MODE_HCO}.
1627 */
1628 public int getRttAudioMode() {
1629 return mRttMode;
1630 }
1631
1632 /**
1633 * Sets the RTT audio mode. The requested mode change will be communicated through
1634 * {@link Callback#onRttModeChanged(Call, int)}.
1635 * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
1636 * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
1637 */
1638 public void setRttMode(@RttAudioMode int mode) {
Hall Liu57006aa2017-02-06 10:49:48 -08001639 mInCallAdapter.setRttMode(mTelecomCallId, mode);
Hall Liu95d55872017-01-25 17:12:49 -08001640 }
1641
1642 /**
1643 * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
Hall Liudc46c852020-10-29 16:15:33 -07001644 * RTT transmits text in real-time, this method should be called once for each user action.
1645 * For example, when the user enters text as discrete characters using the keyboard, this
1646 * method should be called once for each character. However, if the user enters text by
1647 * pasting or autocomplete, the entire contents of the pasted or autocompleted text should
1648 * be sent in one call to this method.
Hall Liu95d55872017-01-25 17:12:49 -08001649 *
1650 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1651 * lead to interleaved text.
1652 * @param input The message to send to the remote user.
1653 */
1654 public void write(String input) throws IOException {
1655 mTransmitStream.write(input);
1656 mTransmitStream.flush();
1657 }
1658
1659 /**
1660 * Reads a string from the remote user, blocking if there is no data available. Returns
1661 * {@code null} if the RTT conversation has been terminated and there is no further data
1662 * to read.
1663 *
1664 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1665 * lead to interleaved text.
1666 * @return A string containing text sent by the remote user, or {@code null} if the
1667 * conversation has been terminated or if there was an error while reading.
1668 */
Hall Liub1c8a772017-07-17 17:04:41 -07001669 public String read() {
1670 try {
1671 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1672 if (numRead < 0) {
1673 return null;
1674 }
1675 return new String(mReadBuffer, 0, numRead);
1676 } catch (IOException e) {
1677 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
Jeff Sharkey90396362017-06-12 16:26:53 -06001678 return null;
Hall Liuffa4a812017-03-02 16:11:00 -08001679 }
Hall Liuffa4a812017-03-02 16:11:00 -08001680 }
1681
1682 /**
1683 * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
1684 * be read.
1685 * @return A string containing text entered by the user, or {@code null} if the user has
1686 * not entered any new text yet.
1687 */
1688 public String readImmediately() throws IOException {
1689 if (mReceiveStream.ready()) {
Hall Liub1c8a772017-07-17 17:04:41 -07001690 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1691 if (numRead < 0) {
1692 return null;
1693 }
1694 return new String(mReadBuffer, 0, numRead);
Hall Liuffa4a812017-03-02 16:11:00 -08001695 } else {
Hall Liu95d55872017-01-25 17:12:49 -08001696 return null;
1697 }
1698 }
Hall Liue9041242018-02-09 16:40:03 -08001699
1700 /**
1701 * Closes the underlying file descriptors
1702 * @hide
1703 */
1704 public void close() {
1705 try {
1706 mReceiveStream.close();
1707 } catch (IOException e) {
1708 // ignore
1709 }
1710 try {
1711 mTransmitStream.close();
1712 } catch (IOException e) {
1713 // ignore
1714 }
1715 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001716 }
1717
Andrew Leeda80c872015-04-15 14:09:50 -07001718 /**
1719 * @deprecated Use {@code Call.Callback} instead.
1720 * @hide
1721 */
1722 @Deprecated
1723 @SystemApi
1724 public static abstract class Listener extends Callback { }
1725
Ihab Awade63fadb2014-07-09 21:52:04 -07001726 private final Phone mPhone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001727 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001728 private final InCallAdapter mInCallAdapter;
Santos Cordon823fd3c2014-08-07 18:35:18 -07001729 private final List<String> mChildrenIds = new ArrayList<>();
Ihab Awade63fadb2014-07-09 21:52:04 -07001730 private final List<Call> mChildren = new ArrayList<>();
1731 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Andrew Lee011728f2015-04-23 15:47:06 -07001732 private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001733 private final List<Call> mConferenceableCalls = new ArrayList<>();
1734 private final List<Call> mUnmodifiableConferenceableCalls =
1735 Collections.unmodifiableList(mConferenceableCalls);
1736
Santos Cordon823fd3c2014-08-07 18:35:18 -07001737 private boolean mChildrenCached;
1738 private String mParentId = null;
Hall Liuef98bf82020-01-09 15:22:44 -08001739 private String mActiveGenericConferenceChild = null;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001740 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -07001741 private List<String> mCannedTextResponses = null;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001742 private String mCallingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001743 private int mTargetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07001744 private String mRemainingPostDialSequence;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001745 private VideoCallImpl mVideoCallImpl;
Hall Liu95d55872017-01-25 17:12:49 -08001746 private RttCall mRttCall;
Ihab Awade63fadb2014-07-09 21:52:04 -07001747 private Details mDetails;
Tyler Gunndee56a82016-03-23 16:06:34 -07001748 private Bundle mExtras;
Ihab Awade63fadb2014-07-09 21:52:04 -07001749
1750 /**
1751 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
1752 *
1753 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
1754 * remaining or this {@code Call} is not in a post-dial state.
1755 */
1756 public String getRemainingPostDialSequence() {
1757 return mRemainingPostDialSequence;
1758 }
1759
1760 /**
1761 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001762 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -07001763 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001764 public void answer(@VideoProfile.VideoState int videoState) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001765 mInCallAdapter.answerCall(mTelecomCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -07001766 }
1767
1768 /**
Pooja Jaind34698d2017-12-28 14:15:31 +05301769 * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
1770 *
1771 * @param address The address to which the call will be deflected.
1772 */
1773 public void deflect(Uri address) {
1774 mInCallAdapter.deflectCall(mTelecomCallId, address);
1775 }
1776
1777 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001778 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
1779 *
1780 * @param rejectWithMessage Whether to reject with a text message.
1781 * @param textMessage An optional text message with which to respond.
1782 */
1783 public void reject(boolean rejectWithMessage, String textMessage) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001784 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
Ihab Awade63fadb2014-07-09 21:52:04 -07001785 }
1786
1787 /**
Tyler Gunnfacfdee2020-01-23 13:10:37 -08001788 * Instructs the {@link ConnectionService} providing this {@link #STATE_RINGING} call that the
1789 * user has chosen to reject the call and has indicated a reason why the call is being rejected.
1790 *
1791 * @param rejectReason the reason the call is being rejected.
1792 */
1793 public void reject(@RejectReason int rejectReason) {
1794 mInCallAdapter.rejectCall(mTelecomCallId, rejectReason);
1795 }
1796
1797 /**
Ravi Palurif4b38e72020-02-05 12:35:41 +05301798 * Instructs this {@code Call} to be transferred to another number.
1799 *
1800 * @param targetNumber The address to which the call will be transferred.
Tyler Gunn460360d2020-07-29 10:21:45 -07001801 * @param isConfirmationRequired if {@code true} it will initiate a confirmed transfer,
1802 * if {@code false}, it will initiate an unconfirmed transfer.
Ravi Palurif4b38e72020-02-05 12:35:41 +05301803 *
1804 * @hide
1805 */
1806 public void transfer(@NonNull Uri targetNumber, boolean isConfirmationRequired) {
1807 mInCallAdapter.transferCall(mTelecomCallId, targetNumber, isConfirmationRequired);
1808 }
1809
1810 /**
1811 * Instructs this {@code Call} to be transferred to another ongoing call.
1812 * This will initiate CONSULTATIVE transfer.
1813 * @param toCall The other ongoing {@code Call} to which this call will be transferred.
1814 *
1815 * @hide
1816 */
1817 public void transfer(@NonNull android.telecom.Call toCall) {
1818 mInCallAdapter.transferCall(mTelecomCallId, toCall.mTelecomCallId);
1819 }
1820
1821 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001822 * Instructs this {@code Call} to disconnect.
1823 */
1824 public void disconnect() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001825 mInCallAdapter.disconnectCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001826 }
1827
1828 /**
1829 * Instructs this {@code Call} to go on hold.
1830 */
1831 public void hold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001832 mInCallAdapter.holdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001833 }
1834
1835 /**
1836 * Instructs this {@link #STATE_HOLDING} call to release from hold.
1837 */
1838 public void unhold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001839 mInCallAdapter.unholdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001840 }
1841
1842 /**
Hall Liu6dfa2492019-10-01 17:20:39 -07001843 * Instructs Telecom to put the call into the background audio processing state.
Tyler Gunn460b7d42020-05-15 10:19:32 -07001844 * <p>
Hall Liu6dfa2492019-10-01 17:20:39 -07001845 * This method can be called either when the call is in {@link #STATE_RINGING} or
1846 * {@link #STATE_ACTIVE}. After Telecom acknowledges the request by setting the call's state to
1847 * {@link #STATE_AUDIO_PROCESSING}, your app may setup the audio paths with the audio stack in
1848 * order to capture and play audio on the call stream.
Tyler Gunn460b7d42020-05-15 10:19:32 -07001849 * <p>
Hall Liu6dfa2492019-10-01 17:20:39 -07001850 * This method can only be called by the default dialer app.
Tyler Gunn460b7d42020-05-15 10:19:32 -07001851 * <p>
1852 * Apps built with SDK version {@link android.os.Build.VERSION_CODES#R} or later which are using
1853 * the microphone as part of audio processing should specify the foreground service type using
1854 * the attribute {@link android.R.attr#foregroundServiceType} in the {@link InCallService}
1855 * service element of the app's manifest file.
1856 * The {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} attribute should be specified.
1857 * @see <a href="https://developer.android.com/preview/privacy/foreground-service-types">
1858 * the Android Developer Site</a> for more information.
Hall Liu6dfa2492019-10-01 17:20:39 -07001859 * @hide
1860 */
1861 @SystemApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001862 public void enterBackgroundAudioProcessing() {
1863 if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
1864 throw new IllegalStateException("Call must be active or ringing");
1865 }
1866 mInCallAdapter.enterBackgroundAudioProcessing(mTelecomCallId);
1867 }
1868
1869 /**
1870 * Instructs Telecom to come out of the background audio processing state requested by
1871 * {@link #enterBackgroundAudioProcessing()} or from the call screening service.
1872 *
1873 * This method can only be called when the call is in {@link #STATE_AUDIO_PROCESSING}.
1874 *
1875 * @param shouldRing If true, Telecom will put the call into the
1876 * {@link #STATE_SIMULATED_RINGING} state and notify other apps that there is
1877 * a ringing call. Otherwise, the call will go into {@link #STATE_ACTIVE}
1878 * immediately.
1879 * @hide
1880 */
1881 @SystemApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001882 public void exitBackgroundAudioProcessing(boolean shouldRing) {
1883 if (mState != STATE_AUDIO_PROCESSING) {
1884 throw new IllegalStateException("Call must in the audio processing state");
1885 }
1886 mInCallAdapter.exitBackgroundAudioProcessing(mTelecomCallId, shouldRing);
1887 }
1888
1889 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001890 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
Tyler Gunn2517d032023-02-06 16:34:54 +00001891 * <p>
1892 * Tones are both played locally for the user to hear and sent to the network to be relayed
1893 * to the remote device.
1894 * <p>
1895 * You must ensure that any call to {@link #playDtmfTone(char}) is followed by a matching
1896 * call to {@link #stopDtmfTone()} and that each tone is stopped before a new one is started.
1897 * The play and stop commands are relayed to the underlying
1898 * {@link android.telecom.ConnectionService} as executed; implementations may not correctly
1899 * handle out of order commands.
Ihab Awade63fadb2014-07-09 21:52:04 -07001900 *
1901 * @param digit A character representing the DTMF digit for which to play the tone. This
1902 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
1903 */
1904 public void playDtmfTone(char digit) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001905 mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
Ihab Awade63fadb2014-07-09 21:52:04 -07001906 }
1907
1908 /**
1909 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
1910 * currently playing.
1911 *
1912 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
1913 * currently playing, this method will do nothing.
1914 */
1915 public void stopDtmfTone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001916 mInCallAdapter.stopDtmfTone(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001917 }
1918
1919 /**
1920 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
1921 *
1922 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
1923 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -07001924 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001925 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -07001926 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
1927 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001928 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
Andrew Leeda80c872015-04-15 14:09:50 -07001929 * {@code Call} will pause playing the tones and notify callbacks via
1930 * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
Ihab Awade63fadb2014-07-09 21:52:04 -07001931 * should display to the user an indication of this state and an affordance to continue
1932 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
1933 * app should invoke the {@link #postDialContinue(boolean)} method.
1934 *
1935 * @param proceed Whether or not to continue with the post-dial sequence.
1936 */
1937 public void postDialContinue(boolean proceed) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001938 mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
Ihab Awade63fadb2014-07-09 21:52:04 -07001939 }
1940
1941 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -07001942 * Notifies this {@code Call} that an account has been selected and to proceed with placing
Nancy Chen36c62f32014-10-21 18:36:39 -07001943 * an outgoing call. Optionally sets this account as the default account.
Nancy Chen5da0fd52014-07-08 14:16:17 -07001944 */
Nancy Chen36c62f32014-10-21 18:36:39 -07001945 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
1946 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
Nancy Chen5da0fd52014-07-08 14:16:17 -07001947
1948 }
1949
1950 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001951 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001952 *
1953 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -07001954 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001955 public void conference(Call callToConferenceWith) {
1956 if (callToConferenceWith != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001957 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001958 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001959 }
1960
1961 /**
1962 * Instructs this {@code Call} to split from any conference call with which it may be
1963 * connected.
1964 */
1965 public void splitFromConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001966 mInCallAdapter.splitFromConference(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001967 }
1968
1969 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001970 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001971 */
1972 public void mergeConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001973 mInCallAdapter.mergeConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001974 }
1975
1976 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001977 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001978 */
1979 public void swapConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001980 mInCallAdapter.swapConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001981 }
1982
1983 /**
Ravi Paluri404babb2020-01-23 19:02:44 +05301984 * Pulls participants to existing call by forming a conference call.
1985 * See {@link Details#CAPABILITY_ADD_PARTICIPANT}.
1986 *
1987 * @param participants participants to be pulled to existing call.
1988 */
1989 public void addConferenceParticipants(@NonNull List<Uri> participants) {
1990 mInCallAdapter.addConferenceParticipants(mTelecomCallId, participants);
1991 }
1992
1993 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001994 * Initiates a request to the {@link ConnectionService} to pull an external call to the local
1995 * device.
1996 * <p>
1997 * Calls to this method are ignored if the call does not have the
1998 * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
1999 * <p>
2000 * An {@link InCallService} will only see calls which support this method if it has the
2001 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
2002 * in its manifest.
2003 */
2004 public void pullExternalCall() {
2005 // If this isn't an external call, ignore the request.
2006 if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
2007 return;
2008 }
2009
2010 mInCallAdapter.pullExternalCall(mTelecomCallId);
2011 }
2012
2013 /**
2014 * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
2015 * the {@link ConnectionService}.
2016 * <p>
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07002017 * Call events are used to communicate point in time information from an {@link InCallService}
2018 * to a {@link ConnectionService}. A {@link ConnectionService} implementation could define
2019 * events which enable the {@link InCallService}, for example, toggle a unique feature of the
2020 * {@link ConnectionService}.
2021 * <p>
2022 * A {@link ConnectionService} can communicate to the {@link InCallService} using
2023 * {@link Connection#sendConnectionEvent(String, Bundle)}.
2024 * <p>
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002025 * Events are exposed to {@link ConnectionService} implementations via
2026 * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
2027 * <p>
2028 * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07002029 * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
2030 * ignore some events altogether.
2031 * <p>
2032 * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
2033 * conflicts between {@link InCallService} implementations. Further, {@link InCallService}
2034 * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
2035 * they define their own event types in this namespace. When defining a custom event type,
2036 * ensure the contents of the extras {@link Bundle} is clearly defined. Extra keys for this
2037 * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
2038 * <p>
2039 * When defining events and the associated extras, it is important to keep their behavior
2040 * consistent when the associated {@link InCallService} is updated. Support for deprecated
2041 * events/extras should me maintained to ensure backwards compatibility with older
2042 * {@link ConnectionService} implementations which were built to support the older behavior.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002043 *
2044 * @param event The connection event.
2045 * @param extras Bundle containing extra information associated with the event.
2046 */
2047 public void sendCallEvent(String event, Bundle extras) {
Sanket Padawef6a9e5b2018-01-05 14:26:16 -08002048 mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002049 }
2050
2051 /**
Hall Liu95d55872017-01-25 17:12:49 -08002052 * Sends an RTT upgrade request to the remote end of the connection. Success is not
2053 * guaranteed, and notification of success will be via the
2054 * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
2055 */
2056 public void sendRttRequest() {
Hall Liu57006aa2017-02-06 10:49:48 -08002057 mInCallAdapter.sendRttRequest(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08002058 }
2059
2060 /**
2061 * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
2062 * callback.
2063 * The ID used here should be the same as the ID that was received via the callback.
2064 * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
2065 * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
2066 */
2067 public void respondToRttRequest(int id, boolean accept) {
Hall Liu57006aa2017-02-06 10:49:48 -08002068 mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
Hall Liu95d55872017-01-25 17:12:49 -08002069 }
2070
2071 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07002072 * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
2073 * by {@code toHandle}. The videoState specified indicates the desired video state after the
2074 * handover.
2075 * <p>
Tyler Gunn9d127732018-03-02 15:45:51 -08002076 * A call handover is the process where an ongoing call is transferred from one app (i.e.
2077 * {@link ConnectionService} to another app. The user could, for example, choose to continue a
2078 * mobile network call in a video calling app. The mobile network call via the Telephony stack
2079 * is referred to as the source of the handover, and the video calling app is referred to as the
2080 * destination.
2081 * <p>
2082 * When considering a handover scenario the device this method is called on is considered the
2083 * <em>initiating</em> device (since the user initiates the handover from this device), and the
2084 * other device is considered the <em>receiving</em> device.
2085 * <p>
2086 * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
2087 * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
2088 * and invoke
2089 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
2090 * ConnectionRequest)} to inform the destination app that a request has been made to handover a
2091 * call to it. The app returns an instance of {@link Connection} to represent the handover call
2092 * At this point the app should display UI to indicate to the user that a call
2093 * handover is in process.
2094 * <p>
2095 * The destination app is responsible for communicating the handover request from the
2096 * <em>initiating</em> device to the <em>receiving</em> device.
2097 * <p>
2098 * When the app on the <em>receiving</em> device receives the handover request, it calls
2099 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
2100 * process from the <em>initiating</em> device to the <em>receiving</em> device. At this point
2101 * the destination app on the <em>receiving</em> device should show UI to allow the user to
2102 * choose whether they want to continue their call in the destination app.
2103 * <p>
2104 * When the destination app on the <em>receiving</em> device calls
2105 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
2106 * {@link ConnectionService} and call
2107 * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
2108 * ConnectionRequest)} to inform it of the handover request. The app returns an instance of
2109 * {@link Connection} to represent the handover call.
2110 * <p>
2111 * If the user of the <em>receiving</em> device accepts the handover, the app calls
2112 * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
2113 * original call. If the user rejects the handover, the app calls
2114 * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
2115 * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
2116 * <p>
2117 * Telecom will only allow handovers from {@link PhoneAccount}s which declare
2118 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}. Similarly, the {@link PhoneAccount}
2119 * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
2120 * <p>
2121 * Errors in the handover process are reported to the {@link InCallService} via
2122 * {@link Callback#onHandoverFailed(Call, int)}. Errors in the handover process are reported to
2123 * the involved {@link ConnectionService}s via
2124 * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07002125 *
2126 * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
2127 * this call to.
Tyler Gunn9d127732018-03-02 15:45:51 -08002128 * @param videoState Indicates the video state desired after the handover (see the
2129 * {@code STATE_*} constants defined in {@link VideoProfile}).
Sanket Padawea8eddd42017-11-03 11:07:35 -07002130 * @param extras Bundle containing extra information to be passed to the
2131 * {@link ConnectionService}
2132 */
Tyler Gunn9d127732018-03-02 15:45:51 -08002133 public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
2134 Bundle extras) {
Sanket Padawea8eddd42017-11-03 11:07:35 -07002135 mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
2136 }
2137
2138 /**
Hall Liu95d55872017-01-25 17:12:49 -08002139 * Terminate the RTT session on this call. The resulting state change will be notified via
2140 * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
2141 */
2142 public void stopRtt() {
Hall Liu57006aa2017-02-06 10:49:48 -08002143 mInCallAdapter.stopRtt(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08002144 }
2145
2146 /**
Tyler Gunndee56a82016-03-23 16:06:34 -07002147 * Adds some extras to this {@link Call}. Existing keys are replaced and new ones are
2148 * added.
2149 * <p>
2150 * No assumptions should be made as to how an In-Call UI or service will handle these
2151 * extras. Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
Tyler Gunn6c100242023-01-09 11:23:18 -08002152 * <p>
2153 * Extras added using this method will be made available to the {@link ConnectionService}
2154 * associated with this {@link Call} and notified via
2155 * {@link Connection#onExtrasChanged(Bundle)}.
2156 * <p>
2157 * Extras added using this method will also be available to other running {@link InCallService}s
2158 * and notified via {@link Call.Callback#onDetailsChanged(Call, Details)}. The extras can be
2159 * accessed via {@link Details#getExtras()}.
Tyler Gunndee56a82016-03-23 16:06:34 -07002160 *
2161 * @param extras The extras to add.
2162 */
2163 public final void putExtras(Bundle extras) {
2164 if (extras == null) {
2165 return;
2166 }
2167
2168 if (mExtras == null) {
2169 mExtras = new Bundle();
2170 }
2171 mExtras.putAll(extras);
2172 mInCallAdapter.putExtras(mTelecomCallId, extras);
2173 }
2174
2175 /**
2176 * Adds a boolean extra to this {@link Call}.
2177 *
2178 * @param key The extra key.
2179 * @param value The value.
2180 * @hide
2181 */
2182 public final void putExtra(String key, boolean value) {
2183 if (mExtras == null) {
2184 mExtras = new Bundle();
2185 }
2186 mExtras.putBoolean(key, value);
2187 mInCallAdapter.putExtra(mTelecomCallId, key, value);
2188 }
2189
2190 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002191 * Adds an integer extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07002192 *
2193 * @param key The extra key.
2194 * @param value The value.
2195 * @hide
2196 */
2197 public final void putExtra(String key, int value) {
2198 if (mExtras == null) {
2199 mExtras = new Bundle();
2200 }
2201 mExtras.putInt(key, value);
2202 mInCallAdapter.putExtra(mTelecomCallId, key, value);
2203 }
2204
2205 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002206 * Adds a string extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07002207 *
2208 * @param key The extra key.
2209 * @param value The value.
2210 * @hide
2211 */
2212 public final void putExtra(String key, String value) {
2213 if (mExtras == null) {
2214 mExtras = new Bundle();
2215 }
2216 mExtras.putString(key, value);
2217 mInCallAdapter.putExtra(mTelecomCallId, key, value);
2218 }
2219
2220 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002221 * Removes extras from this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07002222 *
2223 * @param keys The keys of the extras to remove.
2224 */
2225 public final void removeExtras(List<String> keys) {
2226 if (mExtras != null) {
2227 for (String key : keys) {
2228 mExtras.remove(key);
2229 }
2230 if (mExtras.size() == 0) {
2231 mExtras = null;
2232 }
2233 }
2234 mInCallAdapter.removeExtras(mTelecomCallId, keys);
2235 }
2236
2237 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002238 * Removes extras from this {@link Call}.
2239 *
2240 * @param keys The keys of the extras to remove.
2241 */
2242 public final void removeExtras(String ... keys) {
2243 removeExtras(Arrays.asList(keys));
2244 }
2245
2246 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002247 * Obtains the parent of this {@code Call} in a conference, if any.
2248 *
2249 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
2250 * child of any conference {@code Call}s.
2251 */
2252 public Call getParent() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002253 if (mParentId != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002254 return mPhone.internalGetCallByTelecomId(mParentId);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002255 }
2256 return null;
Ihab Awade63fadb2014-07-09 21:52:04 -07002257 }
2258
2259 /**
2260 * Obtains the children of this conference {@code Call}, if any.
2261 *
2262 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
2263 * {@code List} otherwise.
2264 */
2265 public List<Call> getChildren() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002266 if (!mChildrenCached) {
2267 mChildrenCached = true;
2268 mChildren.clear();
2269
2270 for(String id : mChildrenIds) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002271 Call call = mPhone.internalGetCallByTelecomId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002272 if (call == null) {
2273 // At least one child was still not found, so do not save true for "cached"
2274 mChildrenCached = false;
2275 } else {
2276 mChildren.add(call);
2277 }
2278 }
2279 }
2280
Ihab Awade63fadb2014-07-09 21:52:04 -07002281 return mUnmodifiableChildren;
2282 }
2283
2284 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002285 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
2286 *
2287 * @return The list of conferenceable {@code Call}s.
2288 */
2289 public List<Call> getConferenceableCalls() {
2290 return mUnmodifiableConferenceableCalls;
2291 }
2292
2293 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002294 * Obtains the state of this {@code Call}.
2295 *
Tyler Gunn1e406ca2021-03-18 16:47:14 -07002296 * @return The call state.
2297 * @deprecated The call state is available via {@link Call.Details#getState()}.
Ihab Awade63fadb2014-07-09 21:52:04 -07002298 */
Tyler Gunn1e406ca2021-03-18 16:47:14 -07002299 @Deprecated
2300 public @CallState int getState() {
Ihab Awade63fadb2014-07-09 21:52:04 -07002301 return mState;
2302 }
2303
2304 /**
Hall Liuef98bf82020-01-09 15:22:44 -08002305 * Returns the child {@link Call} in a generic conference that is currently active.
Hall Liu135e53aa2020-02-27 18:34:11 -08002306 *
2307 * A "generic conference" is the mechanism used to support two simultaneous calls on a device
2308 * in CDMA networks. It is effectively equivalent to having one call active and one call on hold
2309 * in GSM or IMS calls. This method returns the currently active call.
2310 *
2311 * In a generic conference, the network exposes the conference to us as a single call, and we
2312 * switch between talking to the two participants using a CDMA flash command. Since the network
2313 * exposes no additional information about the call, the only way we know which caller we're
2314 * currently talking to is by keeping track of the flash commands that we've sent to the
2315 * network.
2316 *
Hall Liuef98bf82020-01-09 15:22:44 -08002317 * For calls that are not generic conferences, or when the generic conference has more than
2318 * 2 children, returns {@code null}.
2319 * @see Details#PROPERTY_GENERIC_CONFERENCE
2320 * @return The active child call.
2321 */
2322 public @Nullable Call getGenericConferenceActiveChildCall() {
2323 if (mActiveGenericConferenceChild != null) {
2324 return mPhone.internalGetCallByTelecomId(mActiveGenericConferenceChild);
2325 }
2326 return null;
2327 }
2328
2329 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002330 * Obtains a list of canned, pre-configured message responses to present to the user as
Tyler Gunn434fc2c2020-10-06 14:23:54 -07002331 * ways of rejecting an incoming {@code Call} using via a text message.
2332 * <p>
2333 * <em>Note:</em> Since canned responses may be loaded from the file system, they are not
2334 * guaranteed to be present when this {@link Call} is first added to the {@link InCallService}
2335 * via {@link InCallService#onCallAdded(Call)}. The callback
2336 * {@link Call.Callback#onCannedTextResponsesLoaded(Call, List)} will be called when/if canned
2337 * responses for the call become available.
Ihab Awade63fadb2014-07-09 21:52:04 -07002338 *
2339 * @see #reject(boolean, String)
2340 *
2341 * @return A list of canned text message responses.
2342 */
2343 public List<String> getCannedTextResponses() {
2344 return mCannedTextResponses;
2345 }
2346
2347 /**
2348 * Obtains an object that can be used to display video from this {@code Call}.
2349 *
Andrew Lee50aca232014-07-22 16:41:54 -07002350 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -07002351 */
Andrew Lee50aca232014-07-22 16:41:54 -07002352 public InCallService.VideoCall getVideoCall() {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002353 return mVideoCallImpl;
Ihab Awade63fadb2014-07-09 21:52:04 -07002354 }
2355
2356 /**
2357 * Obtains an object containing call details.
2358 *
2359 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
2360 * result may be {@code null}.
2361 */
2362 public Details getDetails() {
2363 return mDetails;
2364 }
2365
2366 /**
Hall Liu95d55872017-01-25 17:12:49 -08002367 * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
2368 * receive RTT text data, as well as to change the RTT mode.
2369 * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
2370 */
2371 public @Nullable RttCall getRttCall() {
2372 return mRttCall;
2373 }
2374
2375 /**
2376 * Returns whether this call has an active RTT connection.
2377 * @return true if there is a connection, false otherwise.
2378 */
2379 public boolean isRttActive() {
Hall Liue9041242018-02-09 16:40:03 -08002380 return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
Hall Liu95d55872017-01-25 17:12:49 -08002381 }
2382
2383 /**
Andrew Leeda80c872015-04-15 14:09:50 -07002384 * Registers a callback to this {@code Call}.
2385 *
2386 * @param callback A {@code Callback}.
2387 */
2388 public void registerCallback(Callback callback) {
Andrew Lee011728f2015-04-23 15:47:06 -07002389 registerCallback(callback, new Handler());
2390 }
2391
2392 /**
2393 * Registers a callback to this {@code Call}.
2394 *
2395 * @param callback A {@code Callback}.
2396 * @param handler A handler which command and status changes will be delivered to.
2397 */
2398 public void registerCallback(Callback callback, Handler handler) {
2399 unregisterCallback(callback);
Roshan Pius1ca62072015-07-07 17:34:51 -07002400 // Don't allow new callback registration if the call is already being destroyed.
2401 if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002402 mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
2403 }
Andrew Leeda80c872015-04-15 14:09:50 -07002404 }
2405
2406 /**
2407 * Unregisters a callback from this {@code Call}.
2408 *
2409 * @param callback A {@code Callback}.
2410 */
2411 public void unregisterCallback(Callback callback) {
Roshan Pius1ca62072015-07-07 17:34:51 -07002412 // Don't allow callback deregistration if the call is already being destroyed.
2413 if (callback != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002414 for (CallbackRecord<Callback> record : mCallbackRecords) {
2415 if (record.getCallback() == callback) {
2416 mCallbackRecords.remove(record);
2417 break;
2418 }
2419 }
Andrew Leeda80c872015-04-15 14:09:50 -07002420 }
2421 }
2422
Santos Cordon3c20d632016-02-25 16:12:35 -08002423 @Override
2424 public String toString() {
2425 return new StringBuilder().
2426 append("Call [id: ").
2427 append(mTelecomCallId).
2428 append(", state: ").
2429 append(stateToString(mState)).
2430 append(", details: ").
2431 append(mDetails).
2432 append("]").toString();
2433 }
2434
2435 /**
2436 * @param state An integer value of a {@code STATE_*} constant.
2437 * @return A string representation of the value.
2438 */
2439 private static String stateToString(int state) {
2440 switch (state) {
2441 case STATE_NEW:
2442 return "NEW";
2443 case STATE_RINGING:
2444 return "RINGING";
2445 case STATE_DIALING:
2446 return "DIALING";
2447 case STATE_ACTIVE:
2448 return "ACTIVE";
2449 case STATE_HOLDING:
2450 return "HOLDING";
2451 case STATE_DISCONNECTED:
2452 return "DISCONNECTED";
2453 case STATE_CONNECTING:
2454 return "CONNECTING";
2455 case STATE_DISCONNECTING:
2456 return "DISCONNECTING";
2457 case STATE_SELECT_PHONE_ACCOUNT:
2458 return "SELECT_PHONE_ACCOUNT";
Hall Liu4e35b642019-10-14 17:50:45 -07002459 case STATE_SIMULATED_RINGING:
2460 return "SIMULATED_RINGING";
2461 case STATE_AUDIO_PROCESSING:
2462 return "AUDIO_PROCESSING";
Santos Cordon3c20d632016-02-25 16:12:35 -08002463 default:
2464 Log.w(Call.class, "Unknown state %d", state);
2465 return "UNKNOWN";
2466 }
2467 }
2468
Andrew Leeda80c872015-04-15 14:09:50 -07002469 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002470 * Adds a listener to this {@code Call}.
2471 *
2472 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002473 * @deprecated Use {@link #registerCallback} instead.
2474 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002475 */
Andrew Leeda80c872015-04-15 14:09:50 -07002476 @Deprecated
2477 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002478 public void addListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002479 registerCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002480 }
2481
2482 /**
2483 * Removes a listener from this {@code Call}.
2484 *
2485 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002486 * @deprecated Use {@link #unregisterCallback} instead.
2487 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002488 */
Andrew Leeda80c872015-04-15 14:09:50 -07002489 @Deprecated
2490 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002491 public void removeListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002492 unregisterCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002493 }
2494
2495 /** {@hide} */
Tyler Gunn159f35c2017-03-02 09:28:37 -08002496 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
2497 int targetSdkVersion) {
Ihab Awade63fadb2014-07-09 21:52:04 -07002498 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002499 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002500 mInCallAdapter = inCallAdapter;
2501 mState = STATE_NEW;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002502 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002503 mTargetSdkVersion = targetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07002504 }
2505
2506 /** {@hide} */
Tyler Gunnb88b3112016-11-09 10:19:23 -08002507 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
Tyler Gunn159f35c2017-03-02 09:28:37 -08002508 String callingPackage, int targetSdkVersion) {
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002509 mPhone = phone;
2510 mTelecomCallId = telecomCallId;
2511 mInCallAdapter = inCallAdapter;
2512 mState = state;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002513 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002514 mTargetSdkVersion = targetSdkVersion;
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002515 }
2516
2517 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002518 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002519 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002520 }
2521
2522 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002523 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Tyler Gunnb88b3112016-11-09 10:19:23 -08002524
Ihab Awade63fadb2014-07-09 21:52:04 -07002525 // First, we update the internal state as far as possible before firing any updates.
Sailesh Nepal1bef3392016-01-24 18:21:53 -08002526 Details details = Details.createFromParcelableCall(parcelableCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07002527 boolean detailsChanged = !Objects.equals(mDetails, details);
2528 if (detailsChanged) {
2529 mDetails = details;
2530 }
2531
2532 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -07002533 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
2534 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
2535 mCannedTextResponses =
2536 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Yorke Leee886f632015-08-04 13:43:31 -07002537 cannedTextResponsesChanged = true;
Ihab Awade63fadb2014-07-09 21:52:04 -07002538 }
2539
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002540 IVideoProvider previousVideoProvider = mVideoCallImpl == null ? null :
2541 mVideoCallImpl.getVideoProvider();
2542 IVideoProvider newVideoProvider = parcelableCall.getVideoProvider();
2543
2544 // parcelableCall.isVideoCallProviderChanged is only true when we have a video provider
2545 // specified; so we should check if the actual IVideoProvider changes as well.
2546 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged()
2547 && !Objects.equals(previousVideoProvider, newVideoProvider);
Andrew Lee50aca232014-07-22 16:41:54 -07002548 if (videoCallChanged) {
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002549 if (mVideoCallImpl != null) {
2550 mVideoCallImpl.destroy();
2551 }
2552 mVideoCallImpl = parcelableCall.isVideoCallProviderChanged() ?
2553 parcelableCall.getVideoCallImpl(mCallingPackage, mTargetSdkVersion) : null;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002554 }
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002555
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002556 if (mVideoCallImpl != null) {
2557 mVideoCallImpl.setVideoState(getDetails().getVideoState());
Ihab Awade63fadb2014-07-09 21:52:04 -07002558 }
2559
Santos Cordone3c507b2015-04-23 14:44:19 -07002560 int state = parcelableCall.getState();
Hall Liu31de23d2019-10-11 15:38:29 -07002561 if (mTargetSdkVersion < Phone.SDK_VERSION_R && state == Call.STATE_SIMULATED_RINGING) {
2562 state = Call.STATE_RINGING;
2563 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002564 boolean stateChanged = mState != state;
2565 if (stateChanged) {
2566 mState = state;
2567 }
2568
Santos Cordon823fd3c2014-08-07 18:35:18 -07002569 String parentId = parcelableCall.getParentCallId();
2570 boolean parentChanged = !Objects.equals(mParentId, parentId);
2571 if (parentChanged) {
2572 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002573 }
2574
Santos Cordon823fd3c2014-08-07 18:35:18 -07002575 List<String> childCallIds = parcelableCall.getChildCallIds();
2576 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
2577 if (childrenChanged) {
2578 mChildrenIds.clear();
2579 mChildrenIds.addAll(parcelableCall.getChildCallIds());
2580 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -07002581 }
2582
Hall Liuef98bf82020-01-09 15:22:44 -08002583 String activeChildCallId = parcelableCall.getActiveChildCallId();
2584 boolean activeChildChanged = !Objects.equals(activeChildCallId,
2585 mActiveGenericConferenceChild);
2586 if (activeChildChanged) {
2587 mActiveGenericConferenceChild = activeChildCallId;
2588 }
2589
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002590 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
2591 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
2592 for (String otherId : conferenceableCallIds) {
2593 if (callIdMap.containsKey(otherId)) {
2594 conferenceableCalls.add(callIdMap.get(otherId));
2595 }
2596 }
2597
2598 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
2599 mConferenceableCalls.clear();
2600 mConferenceableCalls.addAll(conferenceableCalls);
2601 fireConferenceableCallsChanged();
2602 }
2603
Hall Liu95d55872017-01-25 17:12:49 -08002604 boolean isRttChanged = false;
2605 boolean rttModeChanged = false;
Hall Liue9041242018-02-09 16:40:03 -08002606 if (parcelableCall.getIsRttCallChanged()
2607 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
Hall Liu95d55872017-01-25 17:12:49 -08002608 ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
2609 InputStreamReader receiveStream = new InputStreamReader(
2610 new ParcelFileDescriptor.AutoCloseInputStream(
2611 parcelableRttCall.getReceiveStream()),
2612 StandardCharsets.UTF_8);
2613 OutputStreamWriter transmitStream = new OutputStreamWriter(
2614 new ParcelFileDescriptor.AutoCloseOutputStream(
2615 parcelableRttCall.getTransmitStream()),
2616 StandardCharsets.UTF_8);
Hall Liu57006aa2017-02-06 10:49:48 -08002617 RttCall newRttCall = new Call.RttCall(mTelecomCallId,
Hall Liu95d55872017-01-25 17:12:49 -08002618 receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
2619 if (mRttCall == null) {
2620 isRttChanged = true;
2621 } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
2622 rttModeChanged = true;
2623 }
2624 mRttCall = newRttCall;
2625 } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
2626 && parcelableCall.getIsRttCallChanged()) {
2627 isRttChanged = true;
Tyler Gunn4cd42482021-04-30 16:23:15 -07002628 mRttCall.close();
Hall Liu95d55872017-01-25 17:12:49 -08002629 mRttCall = null;
2630 }
2631
Ihab Awade63fadb2014-07-09 21:52:04 -07002632 // Now we fire updates, ensuring that any client who listens to any of these notifications
2633 // gets the most up-to-date state.
2634
2635 if (stateChanged) {
2636 fireStateChanged(mState);
2637 }
2638 if (detailsChanged) {
2639 fireDetailsChanged(mDetails);
2640 }
2641 if (cannedTextResponsesChanged) {
2642 fireCannedTextResponsesLoaded(mCannedTextResponses);
2643 }
Andrew Lee50aca232014-07-22 16:41:54 -07002644 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002645 fireVideoCallChanged(mVideoCallImpl);
Ihab Awade63fadb2014-07-09 21:52:04 -07002646 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002647 if (parentChanged) {
2648 fireParentChanged(getParent());
2649 }
Hall Liuef98bf82020-01-09 15:22:44 -08002650 if (childrenChanged || activeChildChanged) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002651 fireChildrenChanged(getChildren());
2652 }
Hall Liu95d55872017-01-25 17:12:49 -08002653 if (isRttChanged) {
2654 fireOnIsRttChanged(mRttCall != null, mRttCall);
2655 }
2656 if (rttModeChanged) {
2657 fireOnRttModeChanged(mRttCall.getRttAudioMode());
2658 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002659
2660 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
2661 // remove ourselves from the Phone. Note that we do this after completing all state updates
2662 // so a client can cleanly transition all their UI to the state appropriate for a
2663 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
qing278fdb12021-10-26 19:05:51 +00002664 // Check if the original state is already disconnected, otherwise onCallRemoved will be
2665 // triggered before onCallAdded.
2666 if (mState == STATE_DISCONNECTED && stateChanged) {
Ihab Awade63fadb2014-07-09 21:52:04 -07002667 fireCallDestroyed();
Ihab Awade63fadb2014-07-09 21:52:04 -07002668 }
2669 }
2670
2671 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002672 final void internalSetPostDialWait(String remaining) {
2673 mRemainingPostDialSequence = remaining;
2674 firePostDialWait(mRemainingPostDialSequence);
2675 }
2676
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07002677 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -07002678 final void internalSetDisconnected() {
2679 if (mState != Call.STATE_DISCONNECTED) {
2680 mState = Call.STATE_DISCONNECTED;
Tyler Gunn1e406ca2021-03-18 16:47:14 -07002681 if (mDetails != null) {
2682 mDetails = new Details(mState,
2683 mDetails.getTelecomCallId(),
2684 mDetails.getHandle(),
2685 mDetails.getHandlePresentation(),
2686 mDetails.getCallerDisplayName(),
2687 mDetails.getCallerDisplayNamePresentation(),
2688 mDetails.getAccountHandle(),
2689 mDetails.getCallCapabilities(),
2690 mDetails.getCallProperties(),
2691 mDetails.getDisconnectCause(),
2692 mDetails.getConnectTimeMillis(),
2693 mDetails.getGatewayInfo(),
2694 mDetails.getVideoState(),
2695 mDetails.getStatusHints(),
2696 mDetails.getExtras(),
2697 mDetails.getIntentExtras(),
2698 mDetails.getCreationTimeMillis(),
2699 mDetails.getContactDisplayName(),
2700 mDetails.getCallDirection(),
Edgar Arriagae5bec822022-10-14 14:25:43 -07002701 mDetails.getCallerNumberVerificationStatus(),
2702 mDetails.getContactPhotoUri()
Tyler Gunn1e406ca2021-03-18 16:47:14 -07002703 );
2704 fireDetailsChanged(mDetails);
2705 }
Santos Cordonf30d7e92014-08-26 09:54:33 -07002706 fireStateChanged(mState);
2707 fireCallDestroyed();
Santos Cordonf30d7e92014-08-26 09:54:33 -07002708 }
2709 }
2710
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002711 /** {@hide} */
2712 final void internalOnConnectionEvent(String event, Bundle extras) {
2713 fireOnConnectionEvent(event, extras);
2714 }
2715
Hall Liu95d55872017-01-25 17:12:49 -08002716 /** {@hide} */
2717 final void internalOnRttUpgradeRequest(final int requestId) {
2718 for (CallbackRecord<Callback> record : mCallbackRecords) {
2719 final Call call = this;
2720 final Callback callback = record.getCallback();
2721 record.getHandler().post(() -> callback.onRttRequest(call, requestId));
2722 }
2723 }
2724
Hall Liu57006aa2017-02-06 10:49:48 -08002725 /** @hide */
2726 final void internalOnRttInitiationFailure(int reason) {
2727 for (CallbackRecord<Callback> record : mCallbackRecords) {
2728 final Call call = this;
2729 final Callback callback = record.getCallback();
2730 record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
2731 }
2732 }
2733
Sanket Padawe85291f62017-12-01 13:59:27 -08002734 /** {@hide} */
2735 final void internalOnHandoverFailed(int error) {
2736 for (CallbackRecord<Callback> record : mCallbackRecords) {
2737 final Call call = this;
2738 final Callback callback = record.getCallback();
2739 record.getHandler().post(() -> callback.onHandoverFailed(call, error));
2740 }
2741 }
2742
Tyler Gunn858bfaf2018-01-22 15:17:54 -08002743 /** {@hide} */
2744 final void internalOnHandoverComplete() {
2745 for (CallbackRecord<Callback> record : mCallbackRecords) {
2746 final Call call = this;
2747 final Callback callback = record.getCallback();
2748 record.getHandler().post(() -> callback.onHandoverComplete(call));
2749 }
2750 }
2751
Andrew Lee011728f2015-04-23 15:47:06 -07002752 private void fireStateChanged(final int newState) {
2753 for (CallbackRecord<Callback> record : mCallbackRecords) {
2754 final Call call = this;
2755 final Callback callback = record.getCallback();
2756 record.getHandler().post(new Runnable() {
2757 @Override
2758 public void run() {
2759 callback.onStateChanged(call, newState);
2760 }
2761 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002762 }
2763 }
2764
Andrew Lee011728f2015-04-23 15:47:06 -07002765 private void fireParentChanged(final Call newParent) {
2766 for (CallbackRecord<Callback> record : mCallbackRecords) {
2767 final Call call = this;
2768 final Callback callback = record.getCallback();
2769 record.getHandler().post(new Runnable() {
2770 @Override
2771 public void run() {
2772 callback.onParentChanged(call, newParent);
2773 }
2774 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002775 }
2776 }
2777
Andrew Lee011728f2015-04-23 15:47:06 -07002778 private void fireChildrenChanged(final List<Call> children) {
2779 for (CallbackRecord<Callback> record : mCallbackRecords) {
2780 final Call call = this;
2781 final Callback callback = record.getCallback();
2782 record.getHandler().post(new Runnable() {
2783 @Override
2784 public void run() {
2785 callback.onChildrenChanged(call, children);
2786 }
2787 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002788 }
2789 }
2790
Andrew Lee011728f2015-04-23 15:47:06 -07002791 private void fireDetailsChanged(final Details details) {
2792 for (CallbackRecord<Callback> record : mCallbackRecords) {
2793 final Call call = this;
2794 final Callback callback = record.getCallback();
2795 record.getHandler().post(new Runnable() {
2796 @Override
2797 public void run() {
2798 callback.onDetailsChanged(call, details);
2799 }
2800 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002801 }
2802 }
2803
Andrew Lee011728f2015-04-23 15:47:06 -07002804 private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
2805 for (CallbackRecord<Callback> record : mCallbackRecords) {
2806 final Call call = this;
2807 final Callback callback = record.getCallback();
2808 record.getHandler().post(new Runnable() {
2809 @Override
2810 public void run() {
2811 callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
2812 }
2813 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002814 }
2815 }
2816
Andrew Lee011728f2015-04-23 15:47:06 -07002817 private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
2818 for (CallbackRecord<Callback> record : mCallbackRecords) {
2819 final Call call = this;
2820 final Callback callback = record.getCallback();
2821 record.getHandler().post(new Runnable() {
2822 @Override
2823 public void run() {
2824 callback.onVideoCallChanged(call, videoCall);
2825 }
2826 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002827 }
2828 }
2829
Andrew Lee011728f2015-04-23 15:47:06 -07002830 private void firePostDialWait(final String remainingPostDialSequence) {
2831 for (CallbackRecord<Callback> record : mCallbackRecords) {
2832 final Call call = this;
2833 final Callback callback = record.getCallback();
2834 record.getHandler().post(new Runnable() {
2835 @Override
2836 public void run() {
2837 callback.onPostDialWait(call, remainingPostDialSequence);
2838 }
2839 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002840 }
2841 }
2842
2843 private void fireCallDestroyed() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002844 /**
2845 * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
2846 * onCallRemoved callback, we remove this call from the Phone's record
2847 * only once all of the registered onCallDestroyed callbacks are executed.
2848 * All the callbacks get removed from our records as a part of this operation
2849 * since onCallDestroyed is the final callback.
2850 */
2851 final Call call = this;
2852 if (mCallbackRecords.isEmpty()) {
2853 // No callbacks registered, remove the call from Phone's record.
2854 mPhone.internalRemoveCall(call);
2855 }
2856 for (final CallbackRecord<Callback> record : mCallbackRecords) {
Andrew Lee011728f2015-04-23 15:47:06 -07002857 final Callback callback = record.getCallback();
2858 record.getHandler().post(new Runnable() {
2859 @Override
2860 public void run() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002861 boolean isFinalRemoval = false;
2862 RuntimeException toThrow = null;
2863 try {
2864 callback.onCallDestroyed(call);
2865 } catch (RuntimeException e) {
2866 toThrow = e;
2867 }
2868 synchronized(Call.this) {
2869 mCallbackRecords.remove(record);
2870 if (mCallbackRecords.isEmpty()) {
2871 isFinalRemoval = true;
2872 }
2873 }
2874 if (isFinalRemoval) {
2875 mPhone.internalRemoveCall(call);
2876 }
2877 if (toThrow != null) {
2878 throw toThrow;
2879 }
Andrew Lee011728f2015-04-23 15:47:06 -07002880 }
2881 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002882 }
2883 }
2884
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002885 private void fireConferenceableCallsChanged() {
Andrew Lee011728f2015-04-23 15:47:06 -07002886 for (CallbackRecord<Callback> record : mCallbackRecords) {
2887 final Call call = this;
2888 final Callback callback = record.getCallback();
2889 record.getHandler().post(new Runnable() {
2890 @Override
2891 public void run() {
2892 callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
2893 }
2894 });
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002895 }
2896 }
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002897
2898 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002899 * Notifies listeners of an incoming connection event.
2900 * <p>
2901 * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
2902 *
2903 * @param event
2904 * @param extras
2905 */
2906 private void fireOnConnectionEvent(final String event, final Bundle extras) {
2907 for (CallbackRecord<Callback> record : mCallbackRecords) {
2908 final Call call = this;
2909 final Callback callback = record.getCallback();
2910 record.getHandler().post(new Runnable() {
2911 @Override
2912 public void run() {
2913 callback.onConnectionEvent(call, event, extras);
2914 }
2915 });
2916 }
2917 }
2918
2919 /**
Hall Liu95d55872017-01-25 17:12:49 -08002920 * Notifies listeners of an RTT on/off change
2921 *
2922 * @param enabled True if RTT is now enabled, false otherwise
2923 */
2924 private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
2925 for (CallbackRecord<Callback> record : mCallbackRecords) {
2926 final Call call = this;
2927 final Callback callback = record.getCallback();
2928 record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
2929 }
2930 }
2931
2932 /**
2933 * Notifies listeners of a RTT mode change
2934 *
2935 * @param mode The new RTT mode
2936 */
2937 private void fireOnRttModeChanged(final int mode) {
2938 for (CallbackRecord<Callback> record : mCallbackRecords) {
2939 final Call call = this;
2940 final Callback callback = record.getCallback();
2941 record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
2942 }
2943 }
2944
2945 /**
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002946 * Determines if two bundles are equal.
2947 *
2948 * @param bundle The original bundle.
2949 * @param newBundle The bundle to compare with.
2950 * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
2951 */
2952 private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
2953 if (bundle == null || newBundle == null) {
2954 return bundle == newBundle;
2955 }
2956
2957 if (bundle.size() != newBundle.size()) {
2958 return false;
2959 }
2960
2961 for(String key : bundle.keySet()) {
2962 if (key != null) {
Grace Jia17005bd2022-05-12 12:49:02 -07002963 if (!newBundle.containsKey(key)) {
2964 return false;
2965 }
qing723dac62022-10-28 03:40:43 +00002966 // In case new call extra contains non-framework class objects, return false to
2967 // force update the call extra
2968 try {
2969 final Object value = bundle.get(key);
2970 final Object newValue = newBundle.get(key);
2971 if (value instanceof Bundle && newValue instanceof Bundle) {
2972 if (!areBundlesEqual((Bundle) value, (Bundle) newValue)) {
2973 return false;
2974 }
2975 }
2976 if (value instanceof byte[] && newValue instanceof byte[]) {
2977 if (!Arrays.equals((byte[]) value, (byte[]) newValue)) {
2978 return false;
2979 }
2980 } else if (!Objects.equals(value, newValue)) {
Grace Jia17005bd2022-05-12 12:49:02 -07002981 return false;
2982 }
qing723dac62022-10-28 03:40:43 +00002983 } catch (BadParcelableException e) {
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002984 return false;
2985 }
2986 }
2987 }
2988 return true;
2989 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002990}