blob: eb0a1e1a40bc16cda4610d282042914ca2a03be6 [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 /**
364 * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
365 * call because they have declined to answer it. This typically means that they are unable
366 * to answer the call at this time and would prefer it be sent to voicemail.
367 */
368 public static final int REJECT_REASON_DECLINED = 1;
369
370 /**
371 * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
372 * call because it is an unwanted call. This allows the user to indicate that they are
373 * rejecting a call because it is likely a nuisance call.
374 */
375 public static final int REJECT_REASON_UNWANTED = 2;
376
377 /**
378 * @hide
379 */
380 @IntDef(prefix = { "REJECT_REASON_" },
381 value = {REJECT_REASON_DECLINED, REJECT_REASON_UNWANTED})
382 @Retention(RetentionPolicy.SOURCE)
383 public @interface RejectReason {};
384
Ihab Awade63fadb2014-07-09 21:52:04 -0700385 public static class Details {
Tyler Gunn94f8f112018-12-17 09:56:11 -0800386 /** @hide */
387 @Retention(RetentionPolicy.SOURCE)
388 @IntDef(
389 prefix = { "DIRECTION_" },
390 value = {DIRECTION_UNKNOWN, DIRECTION_INCOMING, DIRECTION_OUTGOING})
391 public @interface CallDirection {}
392
393 /**
394 * Indicates that the call is neither and incoming nor an outgoing call. This can be the
395 * case for calls reported directly by a {@link ConnectionService} in special cases such as
396 * call handovers.
397 */
398 public static final int DIRECTION_UNKNOWN = -1;
399
400 /**
401 * Indicates that the call is an incoming call.
402 */
403 public static final int DIRECTION_INCOMING = 0;
404
405 /**
406 * Indicates that the call is an outgoing call.
407 */
408 public static final int DIRECTION_OUTGOING = 1;
409
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800410 /** Call can currently be put on hold or unheld. */
411 public static final int CAPABILITY_HOLD = 0x00000001;
412
413 /** Call supports the hold feature. */
414 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
415
416 /**
417 * Calls within a conference can be merged. A {@link ConnectionService} has the option to
418 * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
419 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
420 * capability allows a merge button to be shown while the conference call is in the foreground
421 * of the in-call UI.
422 * <p>
423 * This is only intended for use by a {@link Conference}.
424 */
425 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
426
427 /**
428 * Calls within a conference can be swapped between foreground and background.
429 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
430 * <p>
431 * This is only intended for use by a {@link Conference}.
432 */
433 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
434
435 /**
436 * @hide
437 */
Andrew Lee2378ea72015-04-29 14:38:11 -0700438 public static final int CAPABILITY_UNUSED_1 = 0x00000010;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800439
440 /** Call supports responding via text option. */
441 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
442
443 /** Call can be muted. */
444 public static final int CAPABILITY_MUTE = 0x00000040;
445
446 /**
447 * Call supports conference call management. This capability only applies to {@link Conference}
448 * calls which can have {@link Connection}s as children.
449 */
450 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
451
452 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700453 * Local device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800454 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700455 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800456
457 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700458 * Local device supports transmitting video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800459 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700460 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800461
462 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700463 * Local device supports bidirectional video calling.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800464 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700465 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700466 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800467
468 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700469 * Remote device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800470 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700471 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
472
473 /**
474 * Remote device supports transmitting video.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700475 */
476 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
477
478 /**
479 * Remote device supports bidirectional video calling.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700480 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700481 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700482 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800483
484 /**
485 * Call is able to be separated from its parent {@code Conference}, if any.
486 */
487 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
488
489 /**
490 * Call is able to be individually disconnected when in a {@code Conference}.
491 */
492 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
493
494 /**
Dong Zhou89f41eb2015-03-15 11:59:49 -0500495 * Speed up audio setup for MT call.
496 * @hide
497 */
Tyler Gunn96d6c402015-03-18 12:39:23 -0700498 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
499
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700500 /**
501 * Call can be upgraded to a video call.
Rekha Kumar07366812015-03-24 16:42:31 -0700502 * @hide
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800503 * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
504 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call
505 * whether or not video calling is supported.
Rekha Kumar07366812015-03-24 16:42:31 -0700506 */
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800507 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
Rekha Kumar07366812015-03-24 16:42:31 -0700508 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
509
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700510 /**
511 * For video calls, indicates whether the outgoing video for the call can be paused using
Yorke Lee32f24732015-05-12 16:18:03 -0700512 * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700513 */
514 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
515
Bryce Lee81901682015-08-28 16:38:02 -0700516 /**
517 * Call sends responses through connection.
518 * @hide
519 */
Tyler Gunnf97a0092016-01-19 15:59:34 -0800520 public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;
521
522 /**
523 * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
524 * <p>
525 * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
526 * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
527 * downgraded from a video call back to a VideoState of
528 * {@link VideoProfile#STATE_AUDIO_ONLY}.
529 * <p>
530 * Intuitively, a call which can be downgraded to audio should also have local and remote
531 * video
532 * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
533 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
534 */
535 public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
Bryce Lee81901682015-08-28 16:38:02 -0700536
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700537 /**
538 * When set for an external call, indicates that this {@code Call} can be pulled from a
539 * remote device to the current device.
540 * <p>
541 * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
542 * <p>
543 * An {@link InCallService} will only see calls with this capability if it has the
544 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
545 * in its manifest.
546 * <p>
547 * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
Tyler Gunn720c6642016-03-22 09:02:47 -0700548 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700549 */
550 public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
551
Pooja Jaind34698d2017-12-28 14:15:31 +0530552 /** Call supports the deflect feature. */
553 public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
554
Tyler Gunn0c62ef02020-02-11 14:39:43 -0800555 /**
556 * Call supports adding participants to the call via
Grace Jia8587ee52020-07-10 15:42:32 -0700557 * {@link #addConferenceParticipants(List)}. Once participants are added, the call becomes
558 * an adhoc conference call ({@link #PROPERTY_IS_ADHOC_CONFERENCE}).
Tyler Gunn0c62ef02020-02-11 14:39:43 -0800559 */
Ravi Paluri404babb2020-01-23 19:02:44 +0530560 public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
Ravi Palurif4b38e72020-02-05 12:35:41 +0530561
562 /**
563 * When set for a call, indicates that this {@code Call} can be transferred to another
564 * number.
Tyler Gunn460360d2020-07-29 10:21:45 -0700565 * Call supports the confirmed and unconfirmed call transfer feature.
Ravi Palurif4b38e72020-02-05 12:35:41 +0530566 *
567 * @hide
568 */
569 public static final int CAPABILITY_TRANSFER = 0x04000000;
570
571 /**
572 * When set for a call, indicates that this {@code Call} can be transferred to another
573 * ongoing call.
574 * Call supports the consultative call transfer feature.
575 *
576 * @hide
577 */
578 public static final int CAPABILITY_TRANSFER_CONSULTATIVE = 0x08000000;
579
Alvin Dey2f37d772018-05-18 23:16:10 +0530580 /**
581 * Indicates whether the remote party supports RTT or not to the UI.
582 */
583
584 public static final int CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT = 0x10000000;
585
Tyler Gunnd11a3152015-03-18 13:09:14 -0700586 //******************************************************************************************
Alvin Dey2f37d772018-05-18 23:16:10 +0530587 // Next CAPABILITY value: 0x20000000
Andrew Lee2378ea72015-04-29 14:38:11 -0700588 //******************************************************************************************
589
590 /**
591 * Whether the call is currently a conference.
592 */
593 public static final int PROPERTY_CONFERENCE = 0x00000001;
594
595 /**
596 * Whether the call is a generic conference, where we do not know the precise state of
597 * participants in the conference (eg. on CDMA).
598 */
599 public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
600
601 /**
602 * Whether the call is made while the device is in emergency callback mode.
603 */
604 public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
605
606 /**
607 * Connection is using WIFI.
608 */
609 public static final int PROPERTY_WIFI = 0x00000008;
610
611 /**
Tyler Gunn6b6ae552018-10-11 10:42:10 -0700612 * When set, the UI should indicate to the user that a call is using high definition
613 * audio.
614 * <p>
615 * The underlying {@link ConnectionService} is responsible for reporting this
616 * property. It is important to note that this property is not intended to report the
617 * actual audio codec being used for a Call, but whether the call should be indicated
618 * to the user as high definition.
619 * <p>
620 * The Android Telephony stack reports this property for calls based on a number
621 * of factors, including which audio codec is used and whether a call is using an HD
622 * codec end-to-end. Some mobile operators choose to suppress display of an HD indication,
623 * and in these cases this property will not be set for a call even if the underlying audio
624 * codec is in fact "high definition".
Andrew Lee2378ea72015-04-29 14:38:11 -0700625 */
626 public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
627
Tony Maka68dcce2015-12-17 09:31:18 +0000628 /**
Tony Mak53b5df42016-05-19 13:40:38 +0100629 * Whether the call is associated with the work profile.
630 */
631 public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;
632
633 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700634 * When set, indicates that this {@code Call} does not actually exist locally for the
635 * {@link ConnectionService}.
636 * <p>
637 * Consider, for example, a scenario where a user has two phones with the same phone number.
638 * When a user places a call on one device, the telephony stack can represent that call on
639 * the other device by adding it to the {@link ConnectionService} with the
Tyler Gunn720c6642016-03-22 09:02:47 -0700640 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700641 * <p>
642 * An {@link InCallService} will only see calls with this property if it has the
643 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
644 * in its manifest.
645 * <p>
Tyler Gunn720c6642016-03-22 09:02:47 -0700646 * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700647 */
648 public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
649
Brad Ebinger15847072016-05-18 11:08:36 -0700650 /**
651 * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
652 */
653 public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
654
Tyler Gunn24e18332017-02-10 09:42:49 -0800655 /**
656 * Indicates that the call is from a self-managed {@link ConnectionService}.
657 * <p>
658 * See also {@link Connection#PROPERTY_SELF_MANAGED}
659 */
660 public static final int PROPERTY_SELF_MANAGED = 0x00000100;
661
Eric Erfanianec881872017-12-06 16:27:53 -0800662 /**
663 * Indicates the call used Assisted Dialing.
Tyler Gunn5567d742019-10-31 13:04:37 -0700664 *
665 * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING
Eric Erfanianec881872017-12-06 16:27:53 -0800666 */
Tyler Gunnc9503d62020-01-27 10:30:51 -0800667 public static final int PROPERTY_ASSISTED_DIALING = 0x00000200;
Eric Erfanianec881872017-12-06 16:27:53 -0800668
Hall Liue9041242018-02-09 16:40:03 -0800669 /**
670 * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
671 * {@link RttCall} object that is used to send and receive text.
672 */
673 public static final int PROPERTY_RTT = 0x00000400;
674
Tyler Gunn5bd90852018-09-21 09:37:07 -0700675 /**
676 * Indicates that the call has been identified as the network as an emergency call. This
677 * property may be set for both incoming and outgoing calls which the network identifies as
678 * emergency calls.
679 */
680 public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 0x00000800;
681
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700682 /**
683 * Indicates that the call is using VoIP audio mode.
684 * <p>
685 * When this property is set, the {@link android.media.AudioManager} audio mode for this
686 * call will be {@link android.media.AudioManager#MODE_IN_COMMUNICATION}. When this
687 * property is not set, the audio mode for this call will be
688 * {@link android.media.AudioManager#MODE_IN_CALL}.
689 * <p>
690 * This property reflects changes made using {@link Connection#setAudioModeIsVoip(boolean)}.
691 * <p>
692 * You can use this property to determine whether an un-answered incoming call or a held
693 * call will use VoIP audio mode (if the call does not currently have focus, the system
694 * audio mode may not reflect the mode the call will use).
695 */
696 public static final int PROPERTY_VOIP_AUDIO_MODE = 0x00001000;
697
Ravi Paluri80aa2142019-12-02 11:57:37 +0530698 /**
699 * Indicates that the call is an adhoc conference call. This property can be set for both
Grace Jia8587ee52020-07-10 15:42:32 -0700700 * incoming and outgoing calls. An adhoc conference call is formed using
701 * {@link #addConferenceParticipants(List)},
702 * {@link TelecomManager#addNewIncomingConference(PhoneAccountHandle, Bundle)}, or
703 * {@link TelecomManager#startConference(List, Bundle)}, rather than by merging existing
704 * call using {@link #conference(Call)}.
Ravi Paluri80aa2142019-12-02 11:57:37 +0530705 */
706 public static final int PROPERTY_IS_ADHOC_CONFERENCE = 0x00002000;
707
Sooraj Sasindran64f05b12020-11-18 12:07:10 -0800708 /**
Sooraj Sasindranfa1e57a2021-03-22 13:44:14 -0700709 * Connection is using cross sim technology.
710 * <p>
711 * Indicates that the {@link Connection} is using a cross sim technology which would
712 * register IMS over internet APN of default data subscription.
713 * <p>
Sooraj Sasindran64f05b12020-11-18 12:07:10 -0800714 */
715 public static final int PROPERTY_CROSS_SIM = 0x00004000;
716
Andrew Lee2378ea72015-04-29 14:38:11 -0700717 //******************************************************************************************
Ravi Paluri80aa2142019-12-02 11:57:37 +0530718 // Next PROPERTY value: 0x00004000
Tyler Gunnd11a3152015-03-18 13:09:14 -0700719 //******************************************************************************************
Tyler Gunn068085b2015-02-06 13:56:52 -0800720
Tyler Gunn1e406ca2021-03-18 16:47:14 -0700721 private final @CallState int mState;
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800722 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700723 private final Uri mHandle;
724 private final int mHandlePresentation;
725 private final String mCallerDisplayName;
726 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700727 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700728 private final int mCallCapabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700729 private final int mCallProperties;
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800730 private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700731 private final DisconnectCause mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700732 private final long mConnectTimeMillis;
733 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700734 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700735 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700736 private final Bundle mExtras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700737 private final Bundle mIntentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700738 private final long mCreationTimeMillis;
Hall Liuef98bf82020-01-09 15:22:44 -0800739 private final String mContactDisplayName;
Tyler Gunn94f8f112018-12-17 09:56:11 -0800740 private final @CallDirection int mCallDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700741 private final @Connection.VerificationStatus int mCallerNumberVerificationStatus;
Edgar Arriagae5bec822022-10-14 14:25:43 -0700742 private final Uri mContactPhotoUri;
Ihab Awade63fadb2014-07-09 21:52:04 -0700743
744 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800745 * Whether the supplied capabilities supports the specified capability.
746 *
747 * @param capabilities A bit field of capabilities.
748 * @param capability The capability to check capabilities for.
749 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800750 */
751 public static boolean can(int capabilities, int capability) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800752 return (capabilities & capability) == capability;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800753 }
754
755 /**
756 * Whether the capabilities of this {@code Details} supports the specified capability.
757 *
758 * @param capability The capability to check capabilities for.
759 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800760 */
761 public boolean can(int capability) {
762 return can(mCallCapabilities, capability);
763 }
764
765 /**
766 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
767 *
768 * @param capabilities A capability bit field.
769 * @return A human readable string representation.
770 */
771 public static String capabilitiesToString(int capabilities) {
772 StringBuilder builder = new StringBuilder();
773 builder.append("[Capabilities:");
774 if (can(capabilities, CAPABILITY_HOLD)) {
775 builder.append(" CAPABILITY_HOLD");
776 }
777 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
778 builder.append(" CAPABILITY_SUPPORT_HOLD");
779 }
780 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
781 builder.append(" CAPABILITY_MERGE_CONFERENCE");
782 }
783 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
784 builder.append(" CAPABILITY_SWAP_CONFERENCE");
785 }
786 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
787 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
788 }
789 if (can(capabilities, CAPABILITY_MUTE)) {
790 builder.append(" CAPABILITY_MUTE");
791 }
792 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
793 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
794 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700795 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
796 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
797 }
798 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
799 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
800 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700801 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
802 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800803 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700804 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
805 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
806 }
807 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
808 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
809 }
Tyler Gunnf97a0092016-01-19 15:59:34 -0800810 if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
811 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
812 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700813 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
814 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800815 }
Dong Zhou89f41eb2015-03-15 11:59:49 -0500816 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
Tyler Gunnd11a3152015-03-18 13:09:14 -0700817 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
Dong Zhou89f41eb2015-03-15 11:59:49 -0500818 }
Rekha Kumar07366812015-03-24 16:42:31 -0700819 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
820 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
821 }
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700822 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
823 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
824 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700825 if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
826 builder.append(" CAPABILITY_CAN_PULL_CALL");
827 }
Pooja Jaind34698d2017-12-28 14:15:31 +0530828 if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
829 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
830 }
Ravi Paluri404babb2020-01-23 19:02:44 +0530831 if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) {
832 builder.append(" CAPABILITY_ADD_PARTICIPANT");
833 }
Ravi Palurif4b38e72020-02-05 12:35:41 +0530834 if (can(capabilities, CAPABILITY_TRANSFER)) {
835 builder.append(" CAPABILITY_TRANSFER");
836 }
837 if (can(capabilities, CAPABILITY_TRANSFER_CONSULTATIVE)) {
838 builder.append(" CAPABILITY_TRANSFER_CONSULTATIVE");
839 }
Alvin Dey2f37d772018-05-18 23:16:10 +0530840 if (can(capabilities, CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT)) {
841 builder.append(" CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT");
842 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800843 builder.append("]");
844 return builder.toString();
845 }
846
847 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700848 * Whether the supplied properties includes the specified property.
849 *
850 * @param properties A bit field of properties.
851 * @param property The property to check properties for.
852 * @return Whether the specified property is supported.
853 */
854 public static boolean hasProperty(int properties, int property) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800855 return (properties & property) == property;
Andrew Lee2378ea72015-04-29 14:38:11 -0700856 }
857
858 /**
859 * Whether the properties of this {@code Details} includes the specified property.
860 *
861 * @param property The property to check properties for.
862 * @return Whether the specified property is supported.
863 */
864 public boolean hasProperty(int property) {
865 return hasProperty(mCallProperties, property);
866 }
867
868 /**
869 * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
870 *
871 * @param properties A property bit field.
872 * @return A human readable string representation.
873 */
874 public static String propertiesToString(int properties) {
875 StringBuilder builder = new StringBuilder();
876 builder.append("[Properties:");
877 if (hasProperty(properties, PROPERTY_CONFERENCE)) {
878 builder.append(" PROPERTY_CONFERENCE");
879 }
880 if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
881 builder.append(" PROPERTY_GENERIC_CONFERENCE");
882 }
883 if (hasProperty(properties, PROPERTY_WIFI)) {
884 builder.append(" PROPERTY_WIFI");
885 }
886 if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
887 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
888 }
889 if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
Yorke Leebe2a4a22015-06-12 10:10:55 -0700890 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
Andrew Lee2378ea72015-04-29 14:38:11 -0700891 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700892 if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
893 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
894 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700895 if (hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
Brad Ebinger15847072016-05-18 11:08:36 -0700896 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
897 }
Tyler Gunnc9503d62020-01-27 10:30:51 -0800898 if (hasProperty(properties, PROPERTY_ASSISTED_DIALING)) {
Eric Erfanianec881872017-12-06 16:27:53 -0800899 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
900 }
Tyler Gunn5bd90852018-09-21 09:37:07 -0700901 if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
902 builder.append(" PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL");
903 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700904 if (hasProperty(properties, PROPERTY_RTT)) {
905 builder.append(" PROPERTY_RTT");
906 }
907 if (hasProperty(properties, PROPERTY_VOIP_AUDIO_MODE)) {
908 builder.append(" PROPERTY_VOIP_AUDIO_MODE");
909 }
Ravi Paluri80aa2142019-12-02 11:57:37 +0530910 if (hasProperty(properties, PROPERTY_IS_ADHOC_CONFERENCE)) {
911 builder.append(" PROPERTY_IS_ADHOC_CONFERENCE");
912 }
Sooraj Sasindran64f05b12020-11-18 12:07:10 -0800913 if (hasProperty(properties, PROPERTY_CROSS_SIM)) {
914 builder.append(" PROPERTY_CROSS_SIM");
915 }
Andrew Lee2378ea72015-04-29 14:38:11 -0700916 builder.append("]");
917 return builder.toString();
918 }
919
Tyler Gunn1e406ca2021-03-18 16:47:14 -0700920 /**
921 * @return the state of the {@link Call} represented by this {@link Call.Details}.
922 */
923 public final @CallState int getState() {
924 return mState;
925 }
926
Grant Menke626dd262023-07-24 15:19:36 -0700927 /**
928 * @return the Telecom identifier associated with this {@link Call} . This is not a stable
929 * identifier and is not guaranteed to be unique across device reboots.
930 */
931 public @NonNull String getId() { return mTelecomCallId; }
932
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800933 /** {@hide} */
Hall Liu31de23d2019-10-11 15:38:29 -0700934 @TestApi
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800935 public String getTelecomCallId() {
936 return mTelecomCallId;
937 }
938
Andrew Lee2378ea72015-04-29 14:38:11 -0700939 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700940 * @return The handle (e.g., phone number) to which the {@code Call} is currently
941 * connected.
942 */
943 public Uri getHandle() {
944 return mHandle;
945 }
946
947 /**
948 * @return The presentation requirements for the handle. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700949 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700950 */
951 public int getHandlePresentation() {
952 return mHandlePresentation;
953 }
954
955 /**
Edgar Arriagae5bec822022-10-14 14:25:43 -0700956 * @return The contact photo URI which corresponds to
957 * {@link android.provider.ContactsContract.PhoneLookup#PHOTO_URI}, or {@code null} if the
958 * lookup is not yet complete, if there's no contacts entry for the caller,
959 * or if the {@link InCallService} does not hold the
960 * {@link android.Manifest.permission#READ_CONTACTS} permission.
961 */
962 public @Nullable Uri getContactPhotoUri() {
963 return mContactPhotoUri;
964 }
965
966 /**
Tyler Gunnd081f042018-12-04 12:56:45 -0800967 * The display name for the caller.
968 * <p>
969 * This is the name as reported by the {@link ConnectionService} associated with this call.
Tyler Gunnd081f042018-12-04 12:56:45 -0800970 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700971 * @return The display name for the caller.
972 */
973 public String getCallerDisplayName() {
974 return mCallerDisplayName;
975 }
976
977 /**
978 * @return The presentation requirements for the caller display name. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700979 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700980 */
981 public int getCallerDisplayNamePresentation() {
982 return mCallerDisplayNamePresentation;
983 }
984
985 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700986 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
987 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700988 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700989 public PhoneAccountHandle getAccountHandle() {
990 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -0700991 }
992
993 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800994 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
995 * {@code CAPABILITY_*} constants in this class.
Ihab Awade63fadb2014-07-09 21:52:04 -0700996 */
Ihab Awad5d0410f2014-07-30 10:07:40 -0700997 public int getCallCapabilities() {
998 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700999 }
1000
1001 /**
Andrew Lee2378ea72015-04-29 14:38:11 -07001002 * @return A bitmask of the properties of the {@code Call}, as defined by the various
1003 * {@code PROPERTY_*} constants in this class.
Andrew Lee223ad142014-08-27 16:33:08 -07001004 */
1005 public int getCallProperties() {
1006 return mCallProperties;
1007 }
1008
1009 /**
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -08001010 * @return a bitmask of the audio routes available for the call.
1011 *
1012 * @hide
1013 */
1014 public int getSupportedAudioRoutes() {
1015 return mSupportedAudioRoutes;
1016 }
1017
1018 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001019 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
Nancy Chenf4cf77c2014-09-19 10:53:21 -07001020 * by {@link android.telecom.DisconnectCause}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001021 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001022 public DisconnectCause getDisconnectCause() {
1023 return mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -07001024 }
1025
1026 /**
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001027 * Returns the time the {@link Call} connected (i.e. became active). This information is
1028 * updated periodically, but user interfaces should not rely on this to display the "call
1029 * time clock". For the time when the call was first added to Telecom, see
1030 * {@link #getCreationTimeMillis()}.
1031 *
1032 * @return The time the {@link Call} connected in milliseconds since the epoch.
Ihab Awade63fadb2014-07-09 21:52:04 -07001033 */
Jay Shrauner164a0ac2015-04-14 18:16:10 -07001034 public final long getConnectTimeMillis() {
Ihab Awade63fadb2014-07-09 21:52:04 -07001035 return mConnectTimeMillis;
1036 }
1037
1038 /**
1039 * @return Information about any calling gateway the {@code Call} may be using.
1040 */
1041 public GatewayInfo getGatewayInfo() {
1042 return mGatewayInfo;
1043 }
1044
Andrew Lee7a341382014-07-15 17:05:08 -07001045 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -07001046 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -07001047 */
1048 public int getVideoState() {
1049 return mVideoState;
1050 }
1051
Ihab Awad5d0410f2014-07-30 10:07:40 -07001052 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001053 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
Ihab Awad5d0410f2014-07-30 10:07:40 -07001054 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -07001055 */
1056 public StatusHints getStatusHints() {
1057 return mStatusHints;
1058 }
1059
Nancy Chen10798dc2014-08-08 14:00:25 -07001060 /**
Santos Cordon6b7f9552015-05-27 17:21:45 -07001061 * @return The extras associated with this call.
Nancy Chen10798dc2014-08-08 14:00:25 -07001062 */
1063 public Bundle getExtras() {
1064 return mExtras;
1065 }
1066
Santos Cordon6b7f9552015-05-27 17:21:45 -07001067 /**
1068 * @return The extras used with the original intent to place this call.
1069 */
1070 public Bundle getIntentExtras() {
1071 return mIntentExtras;
1072 }
1073
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001074 /**
1075 * Returns the time when the call was first created and added to Telecom. This is the same
1076 * time that is logged as the start time in the Call Log (see
1077 * {@link android.provider.CallLog.Calls#DATE}). To determine when the call was connected
1078 * (became active), see {@link #getConnectTimeMillis()}.
1079 *
1080 * @return The creation time of the call, in millis since the epoch.
1081 */
1082 public long getCreationTimeMillis() {
1083 return mCreationTimeMillis;
1084 }
1085
Tyler Gunnd081f042018-12-04 12:56:45 -08001086 /**
Hall Liuef98bf82020-01-09 15:22:44 -08001087 * Returns the name of the caller on the remote end, as derived from a
1088 * {@link android.provider.ContactsContract} lookup of the call's handle.
1089 * @return The name of the caller, or {@code null} if the lookup is not yet complete, if
1090 * there's no contacts entry for the caller, or if the {@link InCallService} does
1091 * not hold the {@link android.Manifest.permission#READ_CONTACTS} permission.
1092 */
1093 public @Nullable String getContactDisplayName() {
1094 return mContactDisplayName;
1095 }
1096
1097 /**
Tyler Gunn94f8f112018-12-17 09:56:11 -08001098 * Indicates whether the call is an incoming or outgoing call.
1099 * @return The call's direction.
1100 */
1101 public @CallDirection int getCallDirection() {
1102 return mCallDirection;
1103 }
1104
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001105 /**
1106 * Gets the verification status for the phone number of an incoming call as identified in
1107 * ATIS-1000082.
Tyler Gunn9c642492020-10-08 13:37:03 -07001108 * <p>
1109 * For incoming calls, the number verification status indicates whether the device was
1110 * able to verify the authenticity of the calling number using the STIR process outlined
1111 * in ATIS-1000082. {@link Connection#VERIFICATION_STATUS_NOT_VERIFIED} indicates that
1112 * the network was not able to use STIR to verify the caller's number (i.e. nothing is
1113 * known regarding the authenticity of the number.
1114 * {@link Connection#VERIFICATION_STATUS_PASSED} indicates that the network was able to
1115 * use STIR to verify the caller's number. This indicates that the network has a high
1116 * degree of confidence that the incoming call actually originated from the indicated
1117 * number. {@link Connection#VERIFICATION_STATUS_FAILED} indicates that the network's
1118 * STIR verification did not pass. This indicates that the incoming call may not
1119 * actually be from the indicated number. This could occur if, for example, the caller
1120 * is using an impersonated phone number.
1121 * <p>
1122 * A {@link CallScreeningService} can use this information to help determine if an
1123 * incoming call is potentially an unwanted call. A verification status of
1124 * {@link Connection#VERIFICATION_STATUS_FAILED} indicates that an incoming call may not
1125 * actually be from the number indicated on the call (i.e. impersonated number) and that it
1126 * should potentially be blocked. Likewise,
1127 * {@link Connection#VERIFICATION_STATUS_PASSED} can be used as a positive signal to
1128 * help clarify that the incoming call is originating from the indicated number and it
1129 * is less likely to be an undesirable call.
1130 * <p>
1131 * An {@link InCallService} can use this information to provide a visual indicator to the
1132 * user regarding the verification status of a call and to help identify calls from
1133 * potentially impersonated numbers.
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001134 * @return the verification status.
1135 */
1136 public @Connection.VerificationStatus int getCallerNumberVerificationStatus() {
1137 return mCallerNumberVerificationStatus;
1138 }
1139
Ihab Awade63fadb2014-07-09 21:52:04 -07001140 @Override
1141 public boolean equals(Object o) {
1142 if (o instanceof Details) {
1143 Details d = (Details) o;
1144 return
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001145 Objects.equals(mState, d.mState) &&
Ihab Awade63fadb2014-07-09 21:52:04 -07001146 Objects.equals(mHandle, d.mHandle) &&
1147 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
1148 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
1149 Objects.equals(mCallerDisplayNamePresentation,
1150 d.mCallerDisplayNamePresentation) &&
Evan Charlton8c8a0622014-07-20 12:31:00 -07001151 Objects.equals(mAccountHandle, d.mAccountHandle) &&
Ihab Awad5d0410f2014-07-30 10:07:40 -07001152 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Andrew Lee223ad142014-08-27 16:33:08 -07001153 Objects.equals(mCallProperties, d.mCallProperties) &&
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001154 Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
Ihab Awade63fadb2014-07-09 21:52:04 -07001155 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Andrew Lee85f5d422014-07-11 17:22:03 -07001156 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Evan Charlton5b49ade2014-07-15 17:03:20 -07001157 Objects.equals(mVideoState, d.mVideoState) &&
Nancy Chen10798dc2014-08-08 14:00:25 -07001158 Objects.equals(mStatusHints, d.mStatusHints) &&
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07001159 areBundlesEqual(mExtras, d.mExtras) &&
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001160 areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
Tyler Gunnd081f042018-12-04 12:56:45 -08001161 Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis) &&
Hall Liuef98bf82020-01-09 15:22:44 -08001162 Objects.equals(mContactDisplayName, d.mContactDisplayName) &&
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001163 Objects.equals(mCallDirection, d.mCallDirection) &&
1164 Objects.equals(mCallerNumberVerificationStatus,
Edgar Arriagae5bec822022-10-14 14:25:43 -07001165 d.mCallerNumberVerificationStatus) &&
1166 Objects.equals(mContactPhotoUri, d.mContactPhotoUri);
Ihab Awade63fadb2014-07-09 21:52:04 -07001167 }
1168 return false;
1169 }
1170
1171 @Override
1172 public int hashCode() {
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001173 return Objects.hash(mState,
1174 mHandle,
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001175 mHandlePresentation,
1176 mCallerDisplayName,
1177 mCallerDisplayNamePresentation,
1178 mAccountHandle,
1179 mCallCapabilities,
1180 mCallProperties,
1181 mDisconnectCause,
1182 mConnectTimeMillis,
1183 mGatewayInfo,
1184 mVideoState,
1185 mStatusHints,
1186 mExtras,
1187 mIntentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -08001188 mCreationTimeMillis,
Hall Liuef98bf82020-01-09 15:22:44 -08001189 mContactDisplayName,
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001190 mCallDirection,
Edgar Arriagae5bec822022-10-14 14:25:43 -07001191 mCallerNumberVerificationStatus,
1192 mContactPhotoUri);
Ihab Awade63fadb2014-07-09 21:52:04 -07001193 }
1194
1195 /** {@hide} */
1196 public Details(
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001197 @CallState int state,
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001198 String telecomCallId,
Ihab Awade63fadb2014-07-09 21:52:04 -07001199 Uri handle,
1200 int handlePresentation,
1201 String callerDisplayName,
1202 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -07001203 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -07001204 int capabilities,
Andrew Lee223ad142014-08-27 16:33:08 -07001205 int properties,
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001206 DisconnectCause disconnectCause,
Ihab Awade63fadb2014-07-09 21:52:04 -07001207 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -07001208 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -07001209 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -07001210 StatusHints statusHints,
Santos Cordon6b7f9552015-05-27 17:21:45 -07001211 Bundle extras,
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001212 Bundle intentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -08001213 long creationTimeMillis,
Hall Liuef98bf82020-01-09 15:22:44 -08001214 String contactDisplayName,
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001215 int callDirection,
Edgar Arriagae5bec822022-10-14 14:25:43 -07001216 int callerNumberVerificationStatus,
1217 Uri contactPhotoUri) {
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001218 mState = state;
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001219 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001220 mHandle = handle;
1221 mHandlePresentation = handlePresentation;
1222 mCallerDisplayName = callerDisplayName;
1223 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -07001224 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -07001225 mCallCapabilities = capabilities;
Andrew Lee223ad142014-08-27 16:33:08 -07001226 mCallProperties = properties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001227 mDisconnectCause = disconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -07001228 mConnectTimeMillis = connectTimeMillis;
1229 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -07001230 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -07001231 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -07001232 mExtras = extras;
Santos Cordon6b7f9552015-05-27 17:21:45 -07001233 mIntentExtras = intentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001234 mCreationTimeMillis = creationTimeMillis;
Hall Liuef98bf82020-01-09 15:22:44 -08001235 mContactDisplayName = contactDisplayName;
Tyler Gunn94f8f112018-12-17 09:56:11 -08001236 mCallDirection = callDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001237 mCallerNumberVerificationStatus = callerNumberVerificationStatus;
Edgar Arriagae5bec822022-10-14 14:25:43 -07001238 mContactPhotoUri = contactPhotoUri;
Ihab Awade63fadb2014-07-09 21:52:04 -07001239 }
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001240
1241 /** {@hide} */
1242 public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
1243 return new Details(
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001244 parcelableCall.getState(),
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001245 parcelableCall.getId(),
1246 parcelableCall.getHandle(),
1247 parcelableCall.getHandlePresentation(),
1248 parcelableCall.getCallerDisplayName(),
1249 parcelableCall.getCallerDisplayNamePresentation(),
1250 parcelableCall.getAccountHandle(),
1251 parcelableCall.getCapabilities(),
1252 parcelableCall.getProperties(),
1253 parcelableCall.getDisconnectCause(),
1254 parcelableCall.getConnectTimeMillis(),
1255 parcelableCall.getGatewayInfo(),
1256 parcelableCall.getVideoState(),
1257 parcelableCall.getStatusHints(),
1258 parcelableCall.getExtras(),
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001259 parcelableCall.getIntentExtras(),
Tyler Gunnd081f042018-12-04 12:56:45 -08001260 parcelableCall.getCreationTimeMillis(),
Hall Liuef98bf82020-01-09 15:22:44 -08001261 parcelableCall.getContactDisplayName(),
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001262 parcelableCall.getCallDirection(),
Edgar Arriagae5bec822022-10-14 14:25:43 -07001263 parcelableCall.getCallerNumberVerificationStatus(),
1264 parcelableCall.getContactPhotoUri()
1265 );
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001266 }
Santos Cordon3c20d632016-02-25 16:12:35 -08001267
1268 @Override
1269 public String toString() {
1270 StringBuilder sb = new StringBuilder();
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001271 sb.append("[id: ");
1272 sb.append(mTelecomCallId);
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001273 sb.append(", state: ");
1274 sb.append(Call.stateToString(mState));
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001275 sb.append(", pa: ");
Santos Cordon3c20d632016-02-25 16:12:35 -08001276 sb.append(mAccountHandle);
1277 sb.append(", hdl: ");
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001278 sb.append(Log.piiHandle(mHandle));
1279 sb.append(", hdlPres: ");
1280 sb.append(mHandlePresentation);
1281 sb.append(", videoState: ");
1282 sb.append(VideoProfile.videoStateToString(mVideoState));
Santos Cordon3c20d632016-02-25 16:12:35 -08001283 sb.append(", caps: ");
1284 sb.append(capabilitiesToString(mCallCapabilities));
1285 sb.append(", props: ");
Tyler Gunn720c6642016-03-22 09:02:47 -07001286 sb.append(propertiesToString(mCallProperties));
Santos Cordon3c20d632016-02-25 16:12:35 -08001287 sb.append("]");
1288 return sb.toString();
1289 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001290 }
1291
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001292 /**
1293 * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
1294 * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
1295 * implementation.
1296 * <p>
1297 * You can handle these callbacks by extending the {@link Callback} class and overriding the
1298 * callbacks that your {@link InCallService} is interested in. The callback methods include the
1299 * {@link Call} for which the callback applies, allowing reuse of a single instance of your
1300 * {@link Callback} implementation, if desired.
1301 * <p>
1302 * Use {@link Call#registerCallback(Callback)} to register your callback(s). Ensure
1303 * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
1304 * (typically in {@link InCallService#onCallRemoved(Call)}).
1305 * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
1306 * reach your implementation of {@link Callback}, so it is important to register your callback
1307 * as soon as your {@link InCallService} is notified of a new call via
1308 * {@link InCallService#onCallAdded(Call)}.
1309 */
Andrew Leeda80c872015-04-15 14:09:50 -07001310 public static abstract class Callback {
Ihab Awade63fadb2014-07-09 21:52:04 -07001311 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001312 * @hide
1313 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001314 @IntDef(prefix = { "HANDOVER_" },
1315 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
Tyler Gunn5c60d712018-03-16 09:53:44 -07001316 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
Tyler Gunn9d127732018-03-02 15:45:51 -08001317 HANDOVER_FAILURE_UNKNOWN})
Sanket Padawea8eddd42017-11-03 11:07:35 -07001318 @Retention(RetentionPolicy.SOURCE)
1319 public @interface HandoverFailureErrors {}
1320
1321 /**
1322 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
Tyler Gunn9d127732018-03-02 15:45:51 -08001323 * to handover the call to rejects the handover request.
1324 * <p>
1325 * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
1326 * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
1327 * {@code null} {@link Connection} from
1328 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1329 * ConnectionRequest)}.
1330 * <p>
1331 * For more information on call handovers, see
1332 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001333 */
1334 public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
1335
1336 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001337 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1338 * is initiated but the source or destination app does not support handover.
1339 * <p>
1340 * Will be returned when a handover is requested via
1341 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
1342 * {@link PhoneAccountHandle} does not declare
1343 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}. May also be returned when a handover is
1344 * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
1345 * {@link Details#getAccountHandle()}) does not declare
1346 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
1347 * <p>
1348 * For more information on call handovers, see
1349 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001350 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001351 public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001352
1353 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001354 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
1355 * user rejects the handover request.
1356 * <p>
1357 * For more information on call handovers, see
1358 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001359 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001360 public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001361
Sanket Padawe85291f62017-12-01 13:59:27 -08001362 /**
1363 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
1364 * is ongoing emergency call.
Tyler Gunn9d127732018-03-02 15:45:51 -08001365 * <p>
1366 * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
1367 * called on an emergency call, or if any other call is an emergency call.
1368 * <p>
1369 * Handovers are not permitted while there are ongoing emergency calls.
1370 * <p>
1371 * For more information on call handovers, see
1372 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawe85291f62017-12-01 13:59:27 -08001373 */
Tyler Gunn5c60d712018-03-16 09:53:44 -07001374 public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
Sanket Padawe85291f62017-12-01 13:59:27 -08001375
Tyler Gunn9d127732018-03-02 15:45:51 -08001376 /**
1377 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1378 * fails for an unknown reason.
1379 * <p>
1380 * For more information on call handovers, see
1381 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
1382 */
1383 public static final int HANDOVER_FAILURE_UNKNOWN = 5;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001384
1385 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001386 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
1387 *
Ihab Awade63fadb2014-07-09 21:52:04 -07001388 * @param call The {@code Call} invoking this method.
1389 * @param state The new state of the {@code Call}.
1390 */
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001391 public void onStateChanged(Call call, @CallState int state) {}
Ihab Awade63fadb2014-07-09 21:52:04 -07001392
1393 /**
1394 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
1395 *
1396 * @param call The {@code Call} invoking this method.
1397 * @param parent The new parent of the {@code Call}.
1398 */
1399 public void onParentChanged(Call call, Call parent) {}
1400
1401 /**
1402 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
1403 *
1404 * @param call The {@code Call} invoking this method.
1405 * @param children The new children of the {@code Call}.
1406 */
1407 public void onChildrenChanged(Call call, List<Call> children) {}
1408
1409 /**
1410 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
1411 *
1412 * @param call The {@code Call} invoking this method.
1413 * @param details A {@code Details} object describing the {@code Call}.
1414 */
1415 public void onDetailsChanged(Call call, Details details) {}
1416
1417 /**
1418 * Invoked when the text messages that can be used as responses to the incoming
1419 * {@code Call} are loaded from the relevant database.
1420 * See {@link #getCannedTextResponses()}.
1421 *
1422 * @param call The {@code Call} invoking this method.
1423 * @param cannedTextResponses The text messages useable as responses.
1424 */
1425 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
1426
1427 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001428 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
1429 * character. This causes the post-dial signals to stop pending user confirmation. An
1430 * implementation should present this choice to the user and invoke
1431 * {@link #postDialContinue(boolean)} when the user makes the choice.
1432 *
1433 * @param call The {@code Call} invoking this method.
1434 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
1435 */
1436 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
1437
1438 /**
Andrew Lee50aca232014-07-22 16:41:54 -07001439 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -07001440 *
1441 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -07001442 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001443 */
Andrew Lee50aca232014-07-22 16:41:54 -07001444 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -07001445
1446 /**
1447 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
1448 * up their UI for the {@code Call} in response to state transitions. Specifically,
1449 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
1450 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
1451 * clients should wait for this method to be invoked.
1452 *
1453 * @param call The {@code Call} being destroyed.
1454 */
1455 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001456
1457 /**
1458 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
1459 * conferenced.
1460 *
1461 * @param call The {@code Call} being updated.
1462 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
1463 * conferenced.
1464 */
1465 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001466
1467 /**
Tyler Gunn5567d742019-10-31 13:04:37 -07001468 * Invoked when a {@link Call} receives an event from its associated {@link Connection} or
1469 * {@link Conference}.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001470 * <p>
1471 * Where possible, the Call should make an attempt to handle {@link Connection} events which
1472 * are part of the {@code android.telecom.*} namespace. The Call should ignore any events
1473 * it does not wish to handle. Unexpected events should be handled gracefully, as it is
1474 * possible that a {@link ConnectionService} has defined its own Connection events which a
1475 * Call is not aware of.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001476 * <p>
Tyler Gunn5567d742019-10-31 13:04:37 -07001477 * See {@link Connection#sendConnectionEvent(String, Bundle)},
1478 * {@link Conference#sendConferenceEvent(String, Bundle)}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001479 *
1480 * @param call The {@code Call} receiving the event.
1481 * @param event The event.
1482 * @param extras Extras associated with the connection event.
1483 */
1484 public void onConnectionEvent(Call call, String event, Bundle extras) {}
Hall Liu95d55872017-01-25 17:12:49 -08001485
1486 /**
1487 * Invoked when the RTT mode changes for this call.
1488 * @param call The call whose RTT mode has changed.
1489 * @param mode the new RTT mode, one of
1490 * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
1491 * or {@link RttCall#RTT_MODE_VCO}
1492 */
1493 public void onRttModeChanged(Call call, int mode) {}
1494
1495 /**
1496 * Invoked when the call's RTT status changes, either from off to on or from on to off.
1497 * @param call The call whose RTT status has changed.
1498 * @param enabled whether RTT is now enabled or disabled
1499 * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
1500 * on, null otherwise.
1501 */
1502 public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
1503
1504 /**
1505 * Invoked when the remote end of the connection has requested that an RTT communication
1506 * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
1507 * with the same ID that this method is invoked with.
1508 * @param call The call which the RTT request was placed on
1509 * @param id The ID of the request.
1510 */
1511 public void onRttRequest(Call call, int id) {}
Hall Liu57006aa2017-02-06 10:49:48 -08001512
1513 /**
1514 * Invoked when the RTT session failed to initiate for some reason, including rejection
1515 * by the remote party.
Tyler Gunnb9a04962022-02-17 08:23:54 -08001516 * <p>
1517 * This callback will ONLY be invoked to report a failure related to a user initiated
1518 * session modification request (i.e. {@link Call#sendRttRequest()}).
1519 * <p>
1520 * If a call is initiated with {@link TelecomManager#EXTRA_START_CALL_WITH_RTT} specified,
1521 * the availability of RTT can be determined by checking {@link Details#PROPERTY_RTT}
1522 * once the call enters state {@link Details#STATE_ACTIVE}.
1523 *
Hall Liu57006aa2017-02-06 10:49:48 -08001524 * @param call The call which the RTT initiation failure occurred on.
1525 * @param reason One of the status codes defined in
Tyler Gunnb9a04962022-02-17 08:23:54 -08001526 * {@link android.telecom.Connection.RttModifyStatus}, with the exception of
1527 * {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
Hall Liu57006aa2017-02-06 10:49:48 -08001528 */
Tyler Gunnb9a04962022-02-17 08:23:54 -08001529 public void onRttInitiationFailure(Call call,
1530 @android.telecom.Connection.RttModifyStatus.RttSessionModifyStatus int reason) {}
Sanket Padawea8eddd42017-11-03 11:07:35 -07001531
1532 /**
1533 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1534 * has completed successfully.
Tyler Gunn9d127732018-03-02 15:45:51 -08001535 * <p>
1536 * For a full discussion of the handover process and the APIs involved, see
1537 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1538 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001539 * @param call The call which had initiated handover.
1540 */
1541 public void onHandoverComplete(Call call) {}
1542
1543 /**
1544 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1545 * has failed.
Tyler Gunn9d127732018-03-02 15:45:51 -08001546 * <p>
1547 * For a full discussion of the handover process and the APIs involved, see
1548 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1549 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001550 * @param call The call which had initiated handover.
Tyler Gunn9d127732018-03-02 15:45:51 -08001551 * @param failureReason Error reason for failure.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001552 */
1553 public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
Hall Liu95d55872017-01-25 17:12:49 -08001554 }
1555
1556 /**
1557 * A class that holds the state that describes the state of the RTT channel to the remote
1558 * party, if it is active.
1559 */
1560 public static final class RttCall {
Hall Liu07094df2017-02-28 15:17:44 -08001561 /** @hide */
Hall Liu95d55872017-01-25 17:12:49 -08001562 @Retention(RetentionPolicy.SOURCE)
1563 @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
1564 public @interface RttAudioMode {}
1565
1566 /**
1567 * For metrics use. Default value in the proto.
1568 * @hide
1569 */
1570 public static final int RTT_MODE_INVALID = 0;
1571
1572 /**
1573 * Indicates that there should be a bidirectional audio stream between the two parties
1574 * on the call.
1575 */
1576 public static final int RTT_MODE_FULL = 1;
1577
1578 /**
1579 * Indicates that the local user should be able to hear the audio stream from the remote
1580 * user, but not vice versa. Equivalent to muting the microphone.
1581 */
1582 public static final int RTT_MODE_HCO = 2;
1583
1584 /**
1585 * Indicates that the remote user should be able to hear the audio stream from the local
1586 * user, but not vice versa. Equivalent to setting the volume to zero.
1587 */
1588 public static final int RTT_MODE_VCO = 3;
1589
1590 private static final int READ_BUFFER_SIZE = 1000;
1591
1592 private InputStreamReader mReceiveStream;
1593 private OutputStreamWriter mTransmitStream;
1594 private int mRttMode;
1595 private final InCallAdapter mInCallAdapter;
Hall Liu57006aa2017-02-06 10:49:48 -08001596 private final String mTelecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001597 private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
1598
1599 /**
1600 * @hide
1601 */
Hall Liu57006aa2017-02-06 10:49:48 -08001602 public RttCall(String telecomCallId, InputStreamReader receiveStream,
1603 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
1604 mTelecomCallId = telecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001605 mReceiveStream = receiveStream;
1606 mTransmitStream = transmitStream;
1607 mRttMode = mode;
1608 mInCallAdapter = inCallAdapter;
1609 }
1610
1611 /**
1612 * Returns the current RTT audio mode.
1613 * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
1614 * {@link #RTT_MODE_HCO}.
1615 */
1616 public int getRttAudioMode() {
1617 return mRttMode;
1618 }
1619
1620 /**
1621 * Sets the RTT audio mode. The requested mode change will be communicated through
1622 * {@link Callback#onRttModeChanged(Call, int)}.
1623 * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
1624 * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
1625 */
1626 public void setRttMode(@RttAudioMode int mode) {
Hall Liu57006aa2017-02-06 10:49:48 -08001627 mInCallAdapter.setRttMode(mTelecomCallId, mode);
Hall Liu95d55872017-01-25 17:12:49 -08001628 }
1629
1630 /**
1631 * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
Hall Liudc46c852020-10-29 16:15:33 -07001632 * RTT transmits text in real-time, this method should be called once for each user action.
1633 * For example, when the user enters text as discrete characters using the keyboard, this
1634 * method should be called once for each character. However, if the user enters text by
1635 * pasting or autocomplete, the entire contents of the pasted or autocompleted text should
1636 * be sent in one call to this method.
Hall Liu95d55872017-01-25 17:12:49 -08001637 *
1638 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1639 * lead to interleaved text.
1640 * @param input The message to send to the remote user.
1641 */
1642 public void write(String input) throws IOException {
1643 mTransmitStream.write(input);
1644 mTransmitStream.flush();
1645 }
1646
1647 /**
1648 * Reads a string from the remote user, blocking if there is no data available. Returns
1649 * {@code null} if the RTT conversation has been terminated and there is no further data
1650 * to read.
1651 *
1652 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1653 * lead to interleaved text.
1654 * @return A string containing text sent by the remote user, or {@code null} if the
1655 * conversation has been terminated or if there was an error while reading.
1656 */
Hall Liub1c8a772017-07-17 17:04:41 -07001657 public String read() {
1658 try {
1659 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1660 if (numRead < 0) {
1661 return null;
1662 }
1663 return new String(mReadBuffer, 0, numRead);
1664 } catch (IOException e) {
1665 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
Jeff Sharkey90396362017-06-12 16:26:53 -06001666 return null;
Hall Liuffa4a812017-03-02 16:11:00 -08001667 }
Hall Liuffa4a812017-03-02 16:11:00 -08001668 }
1669
1670 /**
1671 * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
1672 * be read.
1673 * @return A string containing text entered by the user, or {@code null} if the user has
1674 * not entered any new text yet.
1675 */
1676 public String readImmediately() throws IOException {
1677 if (mReceiveStream.ready()) {
Hall Liub1c8a772017-07-17 17:04:41 -07001678 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1679 if (numRead < 0) {
1680 return null;
1681 }
1682 return new String(mReadBuffer, 0, numRead);
Hall Liuffa4a812017-03-02 16:11:00 -08001683 } else {
Hall Liu95d55872017-01-25 17:12:49 -08001684 return null;
1685 }
1686 }
Hall Liue9041242018-02-09 16:40:03 -08001687
1688 /**
1689 * Closes the underlying file descriptors
1690 * @hide
1691 */
1692 public void close() {
1693 try {
1694 mReceiveStream.close();
1695 } catch (IOException e) {
1696 // ignore
1697 }
1698 try {
1699 mTransmitStream.close();
1700 } catch (IOException e) {
1701 // ignore
1702 }
1703 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001704 }
1705
Andrew Leeda80c872015-04-15 14:09:50 -07001706 /**
1707 * @deprecated Use {@code Call.Callback} instead.
1708 * @hide
1709 */
1710 @Deprecated
1711 @SystemApi
1712 public static abstract class Listener extends Callback { }
1713
Ihab Awade63fadb2014-07-09 21:52:04 -07001714 private final Phone mPhone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001715 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001716 private final InCallAdapter mInCallAdapter;
Santos Cordon823fd3c2014-08-07 18:35:18 -07001717 private final List<String> mChildrenIds = new ArrayList<>();
Ihab Awade63fadb2014-07-09 21:52:04 -07001718 private final List<Call> mChildren = new ArrayList<>();
1719 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Andrew Lee011728f2015-04-23 15:47:06 -07001720 private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001721 private final List<Call> mConferenceableCalls = new ArrayList<>();
1722 private final List<Call> mUnmodifiableConferenceableCalls =
1723 Collections.unmodifiableList(mConferenceableCalls);
1724
Santos Cordon823fd3c2014-08-07 18:35:18 -07001725 private boolean mChildrenCached;
1726 private String mParentId = null;
Hall Liuef98bf82020-01-09 15:22:44 -08001727 private String mActiveGenericConferenceChild = null;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001728 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -07001729 private List<String> mCannedTextResponses = null;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001730 private String mCallingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001731 private int mTargetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07001732 private String mRemainingPostDialSequence;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001733 private VideoCallImpl mVideoCallImpl;
Hall Liu95d55872017-01-25 17:12:49 -08001734 private RttCall mRttCall;
Ihab Awade63fadb2014-07-09 21:52:04 -07001735 private Details mDetails;
Tyler Gunndee56a82016-03-23 16:06:34 -07001736 private Bundle mExtras;
Ihab Awade63fadb2014-07-09 21:52:04 -07001737
1738 /**
1739 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
1740 *
1741 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
1742 * remaining or this {@code Call} is not in a post-dial state.
1743 */
1744 public String getRemainingPostDialSequence() {
1745 return mRemainingPostDialSequence;
1746 }
1747
1748 /**
1749 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001750 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -07001751 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001752 public void answer(@VideoProfile.VideoState int videoState) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001753 mInCallAdapter.answerCall(mTelecomCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -07001754 }
1755
1756 /**
Pooja Jaind34698d2017-12-28 14:15:31 +05301757 * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
1758 *
1759 * @param address The address to which the call will be deflected.
1760 */
1761 public void deflect(Uri address) {
1762 mInCallAdapter.deflectCall(mTelecomCallId, address);
1763 }
1764
1765 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001766 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
1767 *
1768 * @param rejectWithMessage Whether to reject with a text message.
1769 * @param textMessage An optional text message with which to respond.
1770 */
1771 public void reject(boolean rejectWithMessage, String textMessage) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001772 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
Ihab Awade63fadb2014-07-09 21:52:04 -07001773 }
1774
1775 /**
Tyler Gunnfacfdee2020-01-23 13:10:37 -08001776 * Instructs the {@link ConnectionService} providing this {@link #STATE_RINGING} call that the
1777 * user has chosen to reject the call and has indicated a reason why the call is being rejected.
1778 *
1779 * @param rejectReason the reason the call is being rejected.
1780 */
1781 public void reject(@RejectReason int rejectReason) {
1782 mInCallAdapter.rejectCall(mTelecomCallId, rejectReason);
1783 }
1784
1785 /**
Ravi Palurif4b38e72020-02-05 12:35:41 +05301786 * Instructs this {@code Call} to be transferred to another number.
1787 *
1788 * @param targetNumber The address to which the call will be transferred.
Tyler Gunn460360d2020-07-29 10:21:45 -07001789 * @param isConfirmationRequired if {@code true} it will initiate a confirmed transfer,
1790 * if {@code false}, it will initiate an unconfirmed transfer.
Ravi Palurif4b38e72020-02-05 12:35:41 +05301791 *
1792 * @hide
1793 */
1794 public void transfer(@NonNull Uri targetNumber, boolean isConfirmationRequired) {
1795 mInCallAdapter.transferCall(mTelecomCallId, targetNumber, isConfirmationRequired);
1796 }
1797
1798 /**
1799 * Instructs this {@code Call} to be transferred to another ongoing call.
1800 * This will initiate CONSULTATIVE transfer.
1801 * @param toCall The other ongoing {@code Call} to which this call will be transferred.
1802 *
1803 * @hide
1804 */
1805 public void transfer(@NonNull android.telecom.Call toCall) {
1806 mInCallAdapter.transferCall(mTelecomCallId, toCall.mTelecomCallId);
1807 }
1808
1809 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001810 * Instructs this {@code Call} to disconnect.
1811 */
1812 public void disconnect() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001813 mInCallAdapter.disconnectCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001814 }
1815
1816 /**
1817 * Instructs this {@code Call} to go on hold.
1818 */
1819 public void hold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001820 mInCallAdapter.holdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001821 }
1822
1823 /**
1824 * Instructs this {@link #STATE_HOLDING} call to release from hold.
1825 */
1826 public void unhold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001827 mInCallAdapter.unholdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001828 }
1829
1830 /**
Hall Liu6dfa2492019-10-01 17:20:39 -07001831 * Instructs Telecom to put the call into the background audio processing state.
Tyler Gunn460b7d42020-05-15 10:19:32 -07001832 * <p>
Hall Liu6dfa2492019-10-01 17:20:39 -07001833 * This method can be called either when the call is in {@link #STATE_RINGING} or
1834 * {@link #STATE_ACTIVE}. After Telecom acknowledges the request by setting the call's state to
1835 * {@link #STATE_AUDIO_PROCESSING}, your app may setup the audio paths with the audio stack in
1836 * order to capture and play audio on the call stream.
Tyler Gunn460b7d42020-05-15 10:19:32 -07001837 * <p>
Hall Liu6dfa2492019-10-01 17:20:39 -07001838 * This method can only be called by the default dialer app.
Tyler Gunn460b7d42020-05-15 10:19:32 -07001839 * <p>
1840 * Apps built with SDK version {@link android.os.Build.VERSION_CODES#R} or later which are using
1841 * the microphone as part of audio processing should specify the foreground service type using
1842 * the attribute {@link android.R.attr#foregroundServiceType} in the {@link InCallService}
1843 * service element of the app's manifest file.
1844 * The {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} attribute should be specified.
1845 * @see <a href="https://developer.android.com/preview/privacy/foreground-service-types">
1846 * the Android Developer Site</a> for more information.
Hall Liu6dfa2492019-10-01 17:20:39 -07001847 * @hide
1848 */
1849 @SystemApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001850 public void enterBackgroundAudioProcessing() {
1851 if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
1852 throw new IllegalStateException("Call must be active or ringing");
1853 }
1854 mInCallAdapter.enterBackgroundAudioProcessing(mTelecomCallId);
1855 }
1856
1857 /**
1858 * Instructs Telecom to come out of the background audio processing state requested by
1859 * {@link #enterBackgroundAudioProcessing()} or from the call screening service.
1860 *
1861 * This method can only be called when the call is in {@link #STATE_AUDIO_PROCESSING}.
1862 *
1863 * @param shouldRing If true, Telecom will put the call into the
1864 * {@link #STATE_SIMULATED_RINGING} state and notify other apps that there is
1865 * a ringing call. Otherwise, the call will go into {@link #STATE_ACTIVE}
1866 * immediately.
1867 * @hide
1868 */
1869 @SystemApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001870 public void exitBackgroundAudioProcessing(boolean shouldRing) {
1871 if (mState != STATE_AUDIO_PROCESSING) {
1872 throw new IllegalStateException("Call must in the audio processing state");
1873 }
1874 mInCallAdapter.exitBackgroundAudioProcessing(mTelecomCallId, shouldRing);
1875 }
1876
1877 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001878 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
Tyler Gunn2517d032023-02-06 16:34:54 +00001879 * <p>
1880 * Tones are both played locally for the user to hear and sent to the network to be relayed
1881 * to the remote device.
1882 * <p>
1883 * You must ensure that any call to {@link #playDtmfTone(char}) is followed by a matching
1884 * call to {@link #stopDtmfTone()} and that each tone is stopped before a new one is started.
1885 * The play and stop commands are relayed to the underlying
1886 * {@link android.telecom.ConnectionService} as executed; implementations may not correctly
1887 * handle out of order commands.
Ihab Awade63fadb2014-07-09 21:52:04 -07001888 *
1889 * @param digit A character representing the DTMF digit for which to play the tone. This
1890 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
1891 */
1892 public void playDtmfTone(char digit) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001893 mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
Ihab Awade63fadb2014-07-09 21:52:04 -07001894 }
1895
1896 /**
1897 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
1898 * currently playing.
1899 *
1900 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
1901 * currently playing, this method will do nothing.
1902 */
1903 public void stopDtmfTone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001904 mInCallAdapter.stopDtmfTone(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001905 }
1906
1907 /**
1908 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
1909 *
1910 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
1911 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -07001912 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001913 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -07001914 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
1915 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001916 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
Andrew Leeda80c872015-04-15 14:09:50 -07001917 * {@code Call} will pause playing the tones and notify callbacks via
1918 * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
Ihab Awade63fadb2014-07-09 21:52:04 -07001919 * should display to the user an indication of this state and an affordance to continue
1920 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
1921 * app should invoke the {@link #postDialContinue(boolean)} method.
1922 *
1923 * @param proceed Whether or not to continue with the post-dial sequence.
1924 */
1925 public void postDialContinue(boolean proceed) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001926 mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
Ihab Awade63fadb2014-07-09 21:52:04 -07001927 }
1928
1929 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -07001930 * Notifies this {@code Call} that an account has been selected and to proceed with placing
Nancy Chen36c62f32014-10-21 18:36:39 -07001931 * an outgoing call. Optionally sets this account as the default account.
Nancy Chen5da0fd52014-07-08 14:16:17 -07001932 */
Nancy Chen36c62f32014-10-21 18:36:39 -07001933 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
1934 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
Nancy Chen5da0fd52014-07-08 14:16:17 -07001935
1936 }
1937
1938 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001939 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001940 *
1941 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -07001942 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001943 public void conference(Call callToConferenceWith) {
1944 if (callToConferenceWith != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001945 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001946 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001947 }
1948
1949 /**
1950 * Instructs this {@code Call} to split from any conference call with which it may be
1951 * connected.
1952 */
1953 public void splitFromConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001954 mInCallAdapter.splitFromConference(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001955 }
1956
1957 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001958 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001959 */
1960 public void mergeConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001961 mInCallAdapter.mergeConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001962 }
1963
1964 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001965 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001966 */
1967 public void swapConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001968 mInCallAdapter.swapConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001969 }
1970
1971 /**
Ravi Paluri404babb2020-01-23 19:02:44 +05301972 * Pulls participants to existing call by forming a conference call.
1973 * See {@link Details#CAPABILITY_ADD_PARTICIPANT}.
1974 *
1975 * @param participants participants to be pulled to existing call.
1976 */
1977 public void addConferenceParticipants(@NonNull List<Uri> participants) {
1978 mInCallAdapter.addConferenceParticipants(mTelecomCallId, participants);
1979 }
1980
1981 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001982 * Initiates a request to the {@link ConnectionService} to pull an external call to the local
1983 * device.
1984 * <p>
1985 * Calls to this method are ignored if the call does not have the
1986 * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
1987 * <p>
1988 * An {@link InCallService} will only see calls which support this method if it has the
1989 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
1990 * in its manifest.
1991 */
1992 public void pullExternalCall() {
1993 // If this isn't an external call, ignore the request.
1994 if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
1995 return;
1996 }
1997
1998 mInCallAdapter.pullExternalCall(mTelecomCallId);
1999 }
2000
2001 /**
2002 * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
2003 * the {@link ConnectionService}.
2004 * <p>
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07002005 * Call events are used to communicate point in time information from an {@link InCallService}
2006 * to a {@link ConnectionService}. A {@link ConnectionService} implementation could define
2007 * events which enable the {@link InCallService}, for example, toggle a unique feature of the
2008 * {@link ConnectionService}.
2009 * <p>
2010 * A {@link ConnectionService} can communicate to the {@link InCallService} using
2011 * {@link Connection#sendConnectionEvent(String, Bundle)}.
2012 * <p>
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002013 * Events are exposed to {@link ConnectionService} implementations via
2014 * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
2015 * <p>
2016 * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07002017 * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
2018 * ignore some events altogether.
2019 * <p>
2020 * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
2021 * conflicts between {@link InCallService} implementations. Further, {@link InCallService}
2022 * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
2023 * they define their own event types in this namespace. When defining a custom event type,
2024 * ensure the contents of the extras {@link Bundle} is clearly defined. Extra keys for this
2025 * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
2026 * <p>
2027 * When defining events and the associated extras, it is important to keep their behavior
2028 * consistent when the associated {@link InCallService} is updated. Support for deprecated
2029 * events/extras should me maintained to ensure backwards compatibility with older
2030 * {@link ConnectionService} implementations which were built to support the older behavior.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002031 *
2032 * @param event The connection event.
2033 * @param extras Bundle containing extra information associated with the event.
2034 */
2035 public void sendCallEvent(String event, Bundle extras) {
Sanket Padawef6a9e5b2018-01-05 14:26:16 -08002036 mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002037 }
2038
2039 /**
Hall Liu95d55872017-01-25 17:12:49 -08002040 * Sends an RTT upgrade request to the remote end of the connection. Success is not
2041 * guaranteed, and notification of success will be via the
2042 * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
2043 */
2044 public void sendRttRequest() {
Hall Liu57006aa2017-02-06 10:49:48 -08002045 mInCallAdapter.sendRttRequest(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08002046 }
2047
2048 /**
2049 * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
2050 * callback.
2051 * The ID used here should be the same as the ID that was received via the callback.
2052 * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
2053 * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
2054 */
2055 public void respondToRttRequest(int id, boolean accept) {
Hall Liu57006aa2017-02-06 10:49:48 -08002056 mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
Hall Liu95d55872017-01-25 17:12:49 -08002057 }
2058
2059 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07002060 * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
2061 * by {@code toHandle}. The videoState specified indicates the desired video state after the
2062 * handover.
2063 * <p>
Tyler Gunn9d127732018-03-02 15:45:51 -08002064 * A call handover is the process where an ongoing call is transferred from one app (i.e.
2065 * {@link ConnectionService} to another app. The user could, for example, choose to continue a
2066 * mobile network call in a video calling app. The mobile network call via the Telephony stack
2067 * is referred to as the source of the handover, and the video calling app is referred to as the
2068 * destination.
2069 * <p>
2070 * When considering a handover scenario the device this method is called on is considered the
2071 * <em>initiating</em> device (since the user initiates the handover from this device), and the
2072 * other device is considered the <em>receiving</em> device.
2073 * <p>
2074 * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
2075 * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
2076 * and invoke
2077 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
2078 * ConnectionRequest)} to inform the destination app that a request has been made to handover a
2079 * call to it. The app returns an instance of {@link Connection} to represent the handover call
2080 * At this point the app should display UI to indicate to the user that a call
2081 * handover is in process.
2082 * <p>
2083 * The destination app is responsible for communicating the handover request from the
2084 * <em>initiating</em> device to the <em>receiving</em> device.
2085 * <p>
2086 * When the app on the <em>receiving</em> device receives the handover request, it calls
2087 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
2088 * process from the <em>initiating</em> device to the <em>receiving</em> device. At this point
2089 * the destination app on the <em>receiving</em> device should show UI to allow the user to
2090 * choose whether they want to continue their call in the destination app.
2091 * <p>
2092 * When the destination app on the <em>receiving</em> device calls
2093 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
2094 * {@link ConnectionService} and call
2095 * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
2096 * ConnectionRequest)} to inform it of the handover request. The app returns an instance of
2097 * {@link Connection} to represent the handover call.
2098 * <p>
2099 * If the user of the <em>receiving</em> device accepts the handover, the app calls
2100 * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
2101 * original call. If the user rejects the handover, the app calls
2102 * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
2103 * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
2104 * <p>
2105 * Telecom will only allow handovers from {@link PhoneAccount}s which declare
2106 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}. Similarly, the {@link PhoneAccount}
2107 * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
2108 * <p>
2109 * Errors in the handover process are reported to the {@link InCallService} via
2110 * {@link Callback#onHandoverFailed(Call, int)}. Errors in the handover process are reported to
2111 * the involved {@link ConnectionService}s via
2112 * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07002113 *
2114 * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
2115 * this call to.
Tyler Gunn9d127732018-03-02 15:45:51 -08002116 * @param videoState Indicates the video state desired after the handover (see the
2117 * {@code STATE_*} constants defined in {@link VideoProfile}).
Sanket Padawea8eddd42017-11-03 11:07:35 -07002118 * @param extras Bundle containing extra information to be passed to the
2119 * {@link ConnectionService}
2120 */
Tyler Gunn9d127732018-03-02 15:45:51 -08002121 public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
2122 Bundle extras) {
Sanket Padawea8eddd42017-11-03 11:07:35 -07002123 mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
2124 }
2125
2126 /**
Hall Liu95d55872017-01-25 17:12:49 -08002127 * Terminate the RTT session on this call. The resulting state change will be notified via
2128 * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
2129 */
2130 public void stopRtt() {
Hall Liu57006aa2017-02-06 10:49:48 -08002131 mInCallAdapter.stopRtt(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08002132 }
2133
2134 /**
Tyler Gunndee56a82016-03-23 16:06:34 -07002135 * Adds some extras to this {@link Call}. Existing keys are replaced and new ones are
2136 * added.
2137 * <p>
2138 * No assumptions should be made as to how an In-Call UI or service will handle these
2139 * extras. Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
Tyler Gunn6c100242023-01-09 11:23:18 -08002140 * <p>
2141 * Extras added using this method will be made available to the {@link ConnectionService}
2142 * associated with this {@link Call} and notified via
2143 * {@link Connection#onExtrasChanged(Bundle)}.
2144 * <p>
2145 * Extras added using this method will also be available to other running {@link InCallService}s
2146 * and notified via {@link Call.Callback#onDetailsChanged(Call, Details)}. The extras can be
2147 * accessed via {@link Details#getExtras()}.
Tyler Gunndee56a82016-03-23 16:06:34 -07002148 *
2149 * @param extras The extras to add.
2150 */
2151 public final void putExtras(Bundle extras) {
2152 if (extras == null) {
2153 return;
2154 }
2155
2156 if (mExtras == null) {
2157 mExtras = new Bundle();
2158 }
2159 mExtras.putAll(extras);
2160 mInCallAdapter.putExtras(mTelecomCallId, extras);
2161 }
2162
2163 /**
2164 * Adds a boolean extra to this {@link Call}.
2165 *
2166 * @param key The extra key.
2167 * @param value The value.
2168 * @hide
2169 */
2170 public final void putExtra(String key, boolean value) {
2171 if (mExtras == null) {
2172 mExtras = new Bundle();
2173 }
2174 mExtras.putBoolean(key, value);
2175 mInCallAdapter.putExtra(mTelecomCallId, key, value);
2176 }
2177
2178 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002179 * Adds an integer extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07002180 *
2181 * @param key The extra key.
2182 * @param value The value.
2183 * @hide
2184 */
2185 public final void putExtra(String key, int value) {
2186 if (mExtras == null) {
2187 mExtras = new Bundle();
2188 }
2189 mExtras.putInt(key, value);
2190 mInCallAdapter.putExtra(mTelecomCallId, key, value);
2191 }
2192
2193 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002194 * Adds a string extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07002195 *
2196 * @param key The extra key.
2197 * @param value The value.
2198 * @hide
2199 */
2200 public final void putExtra(String key, String value) {
2201 if (mExtras == null) {
2202 mExtras = new Bundle();
2203 }
2204 mExtras.putString(key, value);
2205 mInCallAdapter.putExtra(mTelecomCallId, key, value);
2206 }
2207
2208 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002209 * Removes extras from this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07002210 *
2211 * @param keys The keys of the extras to remove.
2212 */
2213 public final void removeExtras(List<String> keys) {
2214 if (mExtras != null) {
2215 for (String key : keys) {
2216 mExtras.remove(key);
2217 }
2218 if (mExtras.size() == 0) {
2219 mExtras = null;
2220 }
2221 }
2222 mInCallAdapter.removeExtras(mTelecomCallId, keys);
2223 }
2224
2225 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002226 * Removes extras from this {@link Call}.
2227 *
2228 * @param keys The keys of the extras to remove.
2229 */
2230 public final void removeExtras(String ... keys) {
2231 removeExtras(Arrays.asList(keys));
2232 }
2233
2234 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002235 * Obtains the parent of this {@code Call} in a conference, if any.
2236 *
2237 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
2238 * child of any conference {@code Call}s.
2239 */
2240 public Call getParent() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002241 if (mParentId != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002242 return mPhone.internalGetCallByTelecomId(mParentId);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002243 }
2244 return null;
Ihab Awade63fadb2014-07-09 21:52:04 -07002245 }
2246
2247 /**
2248 * Obtains the children of this conference {@code Call}, if any.
2249 *
2250 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
2251 * {@code List} otherwise.
2252 */
2253 public List<Call> getChildren() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002254 if (!mChildrenCached) {
2255 mChildrenCached = true;
2256 mChildren.clear();
2257
2258 for(String id : mChildrenIds) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002259 Call call = mPhone.internalGetCallByTelecomId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002260 if (call == null) {
2261 // At least one child was still not found, so do not save true for "cached"
2262 mChildrenCached = false;
2263 } else {
2264 mChildren.add(call);
2265 }
2266 }
2267 }
2268
Ihab Awade63fadb2014-07-09 21:52:04 -07002269 return mUnmodifiableChildren;
2270 }
2271
2272 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002273 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
2274 *
2275 * @return The list of conferenceable {@code Call}s.
2276 */
2277 public List<Call> getConferenceableCalls() {
2278 return mUnmodifiableConferenceableCalls;
2279 }
2280
2281 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002282 * Obtains the state of this {@code Call}.
2283 *
Tyler Gunn1e406ca2021-03-18 16:47:14 -07002284 * @return The call state.
2285 * @deprecated The call state is available via {@link Call.Details#getState()}.
Ihab Awade63fadb2014-07-09 21:52:04 -07002286 */
Tyler Gunn1e406ca2021-03-18 16:47:14 -07002287 @Deprecated
2288 public @CallState int getState() {
Ihab Awade63fadb2014-07-09 21:52:04 -07002289 return mState;
2290 }
2291
2292 /**
Hall Liuef98bf82020-01-09 15:22:44 -08002293 * Returns the child {@link Call} in a generic conference that is currently active.
Hall Liu135e53aa2020-02-27 18:34:11 -08002294 *
2295 * A "generic conference" is the mechanism used to support two simultaneous calls on a device
2296 * in CDMA networks. It is effectively equivalent to having one call active and one call on hold
2297 * in GSM or IMS calls. This method returns the currently active call.
2298 *
2299 * In a generic conference, the network exposes the conference to us as a single call, and we
2300 * switch between talking to the two participants using a CDMA flash command. Since the network
2301 * exposes no additional information about the call, the only way we know which caller we're
2302 * currently talking to is by keeping track of the flash commands that we've sent to the
2303 * network.
2304 *
Hall Liuef98bf82020-01-09 15:22:44 -08002305 * For calls that are not generic conferences, or when the generic conference has more than
2306 * 2 children, returns {@code null}.
2307 * @see Details#PROPERTY_GENERIC_CONFERENCE
2308 * @return The active child call.
2309 */
2310 public @Nullable Call getGenericConferenceActiveChildCall() {
2311 if (mActiveGenericConferenceChild != null) {
2312 return mPhone.internalGetCallByTelecomId(mActiveGenericConferenceChild);
2313 }
2314 return null;
2315 }
2316
2317 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002318 * Obtains a list of canned, pre-configured message responses to present to the user as
Tyler Gunn434fc2c2020-10-06 14:23:54 -07002319 * ways of rejecting an incoming {@code Call} using via a text message.
2320 * <p>
2321 * <em>Note:</em> Since canned responses may be loaded from the file system, they are not
2322 * guaranteed to be present when this {@link Call} is first added to the {@link InCallService}
2323 * via {@link InCallService#onCallAdded(Call)}. The callback
2324 * {@link Call.Callback#onCannedTextResponsesLoaded(Call, List)} will be called when/if canned
2325 * responses for the call become available.
Ihab Awade63fadb2014-07-09 21:52:04 -07002326 *
2327 * @see #reject(boolean, String)
2328 *
2329 * @return A list of canned text message responses.
2330 */
2331 public List<String> getCannedTextResponses() {
2332 return mCannedTextResponses;
2333 }
2334
2335 /**
2336 * Obtains an object that can be used to display video from this {@code Call}.
2337 *
Andrew Lee50aca232014-07-22 16:41:54 -07002338 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -07002339 */
Andrew Lee50aca232014-07-22 16:41:54 -07002340 public InCallService.VideoCall getVideoCall() {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002341 return mVideoCallImpl;
Ihab Awade63fadb2014-07-09 21:52:04 -07002342 }
2343
2344 /**
2345 * Obtains an object containing call details.
2346 *
2347 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
2348 * result may be {@code null}.
2349 */
2350 public Details getDetails() {
2351 return mDetails;
2352 }
2353
2354 /**
Hall Liu95d55872017-01-25 17:12:49 -08002355 * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
2356 * receive RTT text data, as well as to change the RTT mode.
2357 * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
2358 */
2359 public @Nullable RttCall getRttCall() {
2360 return mRttCall;
2361 }
2362
2363 /**
2364 * Returns whether this call has an active RTT connection.
2365 * @return true if there is a connection, false otherwise.
2366 */
2367 public boolean isRttActive() {
Hall Liue9041242018-02-09 16:40:03 -08002368 return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
Hall Liu95d55872017-01-25 17:12:49 -08002369 }
2370
2371 /**
Andrew Leeda80c872015-04-15 14:09:50 -07002372 * Registers a callback to this {@code Call}.
2373 *
2374 * @param callback A {@code Callback}.
2375 */
2376 public void registerCallback(Callback callback) {
Andrew Lee011728f2015-04-23 15:47:06 -07002377 registerCallback(callback, new Handler());
2378 }
2379
2380 /**
2381 * Registers a callback to this {@code Call}.
2382 *
2383 * @param callback A {@code Callback}.
2384 * @param handler A handler which command and status changes will be delivered to.
2385 */
2386 public void registerCallback(Callback callback, Handler handler) {
2387 unregisterCallback(callback);
Roshan Pius1ca62072015-07-07 17:34:51 -07002388 // Don't allow new callback registration if the call is already being destroyed.
2389 if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002390 mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
2391 }
Andrew Leeda80c872015-04-15 14:09:50 -07002392 }
2393
2394 /**
2395 * Unregisters a callback from this {@code Call}.
2396 *
2397 * @param callback A {@code Callback}.
2398 */
2399 public void unregisterCallback(Callback callback) {
Roshan Pius1ca62072015-07-07 17:34:51 -07002400 // Don't allow callback deregistration if the call is already being destroyed.
2401 if (callback != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002402 for (CallbackRecord<Callback> record : mCallbackRecords) {
2403 if (record.getCallback() == callback) {
2404 mCallbackRecords.remove(record);
2405 break;
2406 }
2407 }
Andrew Leeda80c872015-04-15 14:09:50 -07002408 }
2409 }
2410
Santos Cordon3c20d632016-02-25 16:12:35 -08002411 @Override
2412 public String toString() {
2413 return new StringBuilder().
2414 append("Call [id: ").
2415 append(mTelecomCallId).
2416 append(", state: ").
2417 append(stateToString(mState)).
2418 append(", details: ").
2419 append(mDetails).
2420 append("]").toString();
2421 }
2422
2423 /**
2424 * @param state An integer value of a {@code STATE_*} constant.
2425 * @return A string representation of the value.
2426 */
2427 private static String stateToString(int state) {
2428 switch (state) {
2429 case STATE_NEW:
2430 return "NEW";
2431 case STATE_RINGING:
2432 return "RINGING";
2433 case STATE_DIALING:
2434 return "DIALING";
2435 case STATE_ACTIVE:
2436 return "ACTIVE";
2437 case STATE_HOLDING:
2438 return "HOLDING";
2439 case STATE_DISCONNECTED:
2440 return "DISCONNECTED";
2441 case STATE_CONNECTING:
2442 return "CONNECTING";
2443 case STATE_DISCONNECTING:
2444 return "DISCONNECTING";
2445 case STATE_SELECT_PHONE_ACCOUNT:
2446 return "SELECT_PHONE_ACCOUNT";
Hall Liu4e35b642019-10-14 17:50:45 -07002447 case STATE_SIMULATED_RINGING:
2448 return "SIMULATED_RINGING";
2449 case STATE_AUDIO_PROCESSING:
2450 return "AUDIO_PROCESSING";
Santos Cordon3c20d632016-02-25 16:12:35 -08002451 default:
2452 Log.w(Call.class, "Unknown state %d", state);
2453 return "UNKNOWN";
2454 }
2455 }
2456
Andrew Leeda80c872015-04-15 14:09:50 -07002457 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002458 * Adds a listener to this {@code Call}.
2459 *
2460 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002461 * @deprecated Use {@link #registerCallback} instead.
2462 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002463 */
Andrew Leeda80c872015-04-15 14:09:50 -07002464 @Deprecated
2465 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002466 public void addListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002467 registerCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002468 }
2469
2470 /**
2471 * Removes a listener from this {@code Call}.
2472 *
2473 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002474 * @deprecated Use {@link #unregisterCallback} instead.
2475 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002476 */
Andrew Leeda80c872015-04-15 14:09:50 -07002477 @Deprecated
2478 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002479 public void removeListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002480 unregisterCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002481 }
2482
2483 /** {@hide} */
Tyler Gunn159f35c2017-03-02 09:28:37 -08002484 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
2485 int targetSdkVersion) {
Ihab Awade63fadb2014-07-09 21:52:04 -07002486 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002487 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002488 mInCallAdapter = inCallAdapter;
2489 mState = STATE_NEW;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002490 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002491 mTargetSdkVersion = targetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07002492 }
2493
2494 /** {@hide} */
Tyler Gunnb88b3112016-11-09 10:19:23 -08002495 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
Tyler Gunn159f35c2017-03-02 09:28:37 -08002496 String callingPackage, int targetSdkVersion) {
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002497 mPhone = phone;
2498 mTelecomCallId = telecomCallId;
2499 mInCallAdapter = inCallAdapter;
2500 mState = state;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002501 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002502 mTargetSdkVersion = targetSdkVersion;
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002503 }
2504
2505 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002506 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002507 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002508 }
2509
2510 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002511 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Tyler Gunnb88b3112016-11-09 10:19:23 -08002512
Ihab Awade63fadb2014-07-09 21:52:04 -07002513 // First, we update the internal state as far as possible before firing any updates.
Sailesh Nepal1bef3392016-01-24 18:21:53 -08002514 Details details = Details.createFromParcelableCall(parcelableCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07002515 boolean detailsChanged = !Objects.equals(mDetails, details);
2516 if (detailsChanged) {
2517 mDetails = details;
2518 }
2519
2520 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -07002521 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
2522 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
2523 mCannedTextResponses =
2524 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Yorke Leee886f632015-08-04 13:43:31 -07002525 cannedTextResponsesChanged = true;
Ihab Awade63fadb2014-07-09 21:52:04 -07002526 }
2527
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002528 IVideoProvider previousVideoProvider = mVideoCallImpl == null ? null :
2529 mVideoCallImpl.getVideoProvider();
2530 IVideoProvider newVideoProvider = parcelableCall.getVideoProvider();
2531
2532 // parcelableCall.isVideoCallProviderChanged is only true when we have a video provider
2533 // specified; so we should check if the actual IVideoProvider changes as well.
2534 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged()
2535 && !Objects.equals(previousVideoProvider, newVideoProvider);
Andrew Lee50aca232014-07-22 16:41:54 -07002536 if (videoCallChanged) {
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002537 if (mVideoCallImpl != null) {
2538 mVideoCallImpl.destroy();
2539 }
2540 mVideoCallImpl = parcelableCall.isVideoCallProviderChanged() ?
2541 parcelableCall.getVideoCallImpl(mCallingPackage, mTargetSdkVersion) : null;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002542 }
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002543
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002544 if (mVideoCallImpl != null) {
2545 mVideoCallImpl.setVideoState(getDetails().getVideoState());
Ihab Awade63fadb2014-07-09 21:52:04 -07002546 }
2547
Santos Cordone3c507b2015-04-23 14:44:19 -07002548 int state = parcelableCall.getState();
Hall Liu31de23d2019-10-11 15:38:29 -07002549 if (mTargetSdkVersion < Phone.SDK_VERSION_R && state == Call.STATE_SIMULATED_RINGING) {
2550 state = Call.STATE_RINGING;
2551 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002552 boolean stateChanged = mState != state;
2553 if (stateChanged) {
2554 mState = state;
2555 }
2556
Santos Cordon823fd3c2014-08-07 18:35:18 -07002557 String parentId = parcelableCall.getParentCallId();
2558 boolean parentChanged = !Objects.equals(mParentId, parentId);
2559 if (parentChanged) {
2560 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002561 }
2562
Santos Cordon823fd3c2014-08-07 18:35:18 -07002563 List<String> childCallIds = parcelableCall.getChildCallIds();
2564 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
2565 if (childrenChanged) {
2566 mChildrenIds.clear();
2567 mChildrenIds.addAll(parcelableCall.getChildCallIds());
2568 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -07002569 }
2570
Hall Liuef98bf82020-01-09 15:22:44 -08002571 String activeChildCallId = parcelableCall.getActiveChildCallId();
2572 boolean activeChildChanged = !Objects.equals(activeChildCallId,
2573 mActiveGenericConferenceChild);
2574 if (activeChildChanged) {
2575 mActiveGenericConferenceChild = activeChildCallId;
2576 }
2577
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002578 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
2579 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
2580 for (String otherId : conferenceableCallIds) {
2581 if (callIdMap.containsKey(otherId)) {
2582 conferenceableCalls.add(callIdMap.get(otherId));
2583 }
2584 }
2585
2586 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
2587 mConferenceableCalls.clear();
2588 mConferenceableCalls.addAll(conferenceableCalls);
2589 fireConferenceableCallsChanged();
2590 }
2591
Hall Liu95d55872017-01-25 17:12:49 -08002592 boolean isRttChanged = false;
2593 boolean rttModeChanged = false;
Hall Liue9041242018-02-09 16:40:03 -08002594 if (parcelableCall.getIsRttCallChanged()
2595 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
Hall Liu95d55872017-01-25 17:12:49 -08002596 ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
2597 InputStreamReader receiveStream = new InputStreamReader(
2598 new ParcelFileDescriptor.AutoCloseInputStream(
2599 parcelableRttCall.getReceiveStream()),
2600 StandardCharsets.UTF_8);
2601 OutputStreamWriter transmitStream = new OutputStreamWriter(
2602 new ParcelFileDescriptor.AutoCloseOutputStream(
2603 parcelableRttCall.getTransmitStream()),
2604 StandardCharsets.UTF_8);
Hall Liu57006aa2017-02-06 10:49:48 -08002605 RttCall newRttCall = new Call.RttCall(mTelecomCallId,
Hall Liu95d55872017-01-25 17:12:49 -08002606 receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
2607 if (mRttCall == null) {
2608 isRttChanged = true;
2609 } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
2610 rttModeChanged = true;
2611 }
2612 mRttCall = newRttCall;
2613 } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
2614 && parcelableCall.getIsRttCallChanged()) {
2615 isRttChanged = true;
Tyler Gunn4cd42482021-04-30 16:23:15 -07002616 mRttCall.close();
Hall Liu95d55872017-01-25 17:12:49 -08002617 mRttCall = null;
2618 }
2619
Ihab Awade63fadb2014-07-09 21:52:04 -07002620 // Now we fire updates, ensuring that any client who listens to any of these notifications
2621 // gets the most up-to-date state.
2622
2623 if (stateChanged) {
2624 fireStateChanged(mState);
2625 }
2626 if (detailsChanged) {
2627 fireDetailsChanged(mDetails);
2628 }
2629 if (cannedTextResponsesChanged) {
2630 fireCannedTextResponsesLoaded(mCannedTextResponses);
2631 }
Andrew Lee50aca232014-07-22 16:41:54 -07002632 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002633 fireVideoCallChanged(mVideoCallImpl);
Ihab Awade63fadb2014-07-09 21:52:04 -07002634 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002635 if (parentChanged) {
2636 fireParentChanged(getParent());
2637 }
Hall Liuef98bf82020-01-09 15:22:44 -08002638 if (childrenChanged || activeChildChanged) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002639 fireChildrenChanged(getChildren());
2640 }
Hall Liu95d55872017-01-25 17:12:49 -08002641 if (isRttChanged) {
2642 fireOnIsRttChanged(mRttCall != null, mRttCall);
2643 }
2644 if (rttModeChanged) {
2645 fireOnRttModeChanged(mRttCall.getRttAudioMode());
2646 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002647
2648 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
2649 // remove ourselves from the Phone. Note that we do this after completing all state updates
2650 // so a client can cleanly transition all their UI to the state appropriate for a
2651 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
qing278fdb12021-10-26 19:05:51 +00002652 // Check if the original state is already disconnected, otherwise onCallRemoved will be
2653 // triggered before onCallAdded.
2654 if (mState == STATE_DISCONNECTED && stateChanged) {
Ihab Awade63fadb2014-07-09 21:52:04 -07002655 fireCallDestroyed();
Ihab Awade63fadb2014-07-09 21:52:04 -07002656 }
2657 }
2658
2659 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002660 final void internalSetPostDialWait(String remaining) {
2661 mRemainingPostDialSequence = remaining;
2662 firePostDialWait(mRemainingPostDialSequence);
2663 }
2664
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07002665 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -07002666 final void internalSetDisconnected() {
2667 if (mState != Call.STATE_DISCONNECTED) {
2668 mState = Call.STATE_DISCONNECTED;
Tyler Gunn1e406ca2021-03-18 16:47:14 -07002669 if (mDetails != null) {
2670 mDetails = new Details(mState,
2671 mDetails.getTelecomCallId(),
2672 mDetails.getHandle(),
2673 mDetails.getHandlePresentation(),
2674 mDetails.getCallerDisplayName(),
2675 mDetails.getCallerDisplayNamePresentation(),
2676 mDetails.getAccountHandle(),
2677 mDetails.getCallCapabilities(),
2678 mDetails.getCallProperties(),
2679 mDetails.getDisconnectCause(),
2680 mDetails.getConnectTimeMillis(),
2681 mDetails.getGatewayInfo(),
2682 mDetails.getVideoState(),
2683 mDetails.getStatusHints(),
2684 mDetails.getExtras(),
2685 mDetails.getIntentExtras(),
2686 mDetails.getCreationTimeMillis(),
2687 mDetails.getContactDisplayName(),
2688 mDetails.getCallDirection(),
Edgar Arriagae5bec822022-10-14 14:25:43 -07002689 mDetails.getCallerNumberVerificationStatus(),
2690 mDetails.getContactPhotoUri()
Tyler Gunn1e406ca2021-03-18 16:47:14 -07002691 );
2692 fireDetailsChanged(mDetails);
2693 }
Santos Cordonf30d7e92014-08-26 09:54:33 -07002694 fireStateChanged(mState);
2695 fireCallDestroyed();
Santos Cordonf30d7e92014-08-26 09:54:33 -07002696 }
2697 }
2698
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002699 /** {@hide} */
2700 final void internalOnConnectionEvent(String event, Bundle extras) {
2701 fireOnConnectionEvent(event, extras);
2702 }
2703
Hall Liu95d55872017-01-25 17:12:49 -08002704 /** {@hide} */
2705 final void internalOnRttUpgradeRequest(final int requestId) {
2706 for (CallbackRecord<Callback> record : mCallbackRecords) {
2707 final Call call = this;
2708 final Callback callback = record.getCallback();
2709 record.getHandler().post(() -> callback.onRttRequest(call, requestId));
2710 }
2711 }
2712
Hall Liu57006aa2017-02-06 10:49:48 -08002713 /** @hide */
2714 final void internalOnRttInitiationFailure(int reason) {
2715 for (CallbackRecord<Callback> record : mCallbackRecords) {
2716 final Call call = this;
2717 final Callback callback = record.getCallback();
2718 record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
2719 }
2720 }
2721
Sanket Padawe85291f62017-12-01 13:59:27 -08002722 /** {@hide} */
2723 final void internalOnHandoverFailed(int error) {
2724 for (CallbackRecord<Callback> record : mCallbackRecords) {
2725 final Call call = this;
2726 final Callback callback = record.getCallback();
2727 record.getHandler().post(() -> callback.onHandoverFailed(call, error));
2728 }
2729 }
2730
Tyler Gunn858bfaf2018-01-22 15:17:54 -08002731 /** {@hide} */
2732 final void internalOnHandoverComplete() {
2733 for (CallbackRecord<Callback> record : mCallbackRecords) {
2734 final Call call = this;
2735 final Callback callback = record.getCallback();
2736 record.getHandler().post(() -> callback.onHandoverComplete(call));
2737 }
2738 }
2739
Andrew Lee011728f2015-04-23 15:47:06 -07002740 private void fireStateChanged(final int newState) {
2741 for (CallbackRecord<Callback> record : mCallbackRecords) {
2742 final Call call = this;
2743 final Callback callback = record.getCallback();
2744 record.getHandler().post(new Runnable() {
2745 @Override
2746 public void run() {
2747 callback.onStateChanged(call, newState);
2748 }
2749 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002750 }
2751 }
2752
Andrew Lee011728f2015-04-23 15:47:06 -07002753 private void fireParentChanged(final Call newParent) {
2754 for (CallbackRecord<Callback> record : mCallbackRecords) {
2755 final Call call = this;
2756 final Callback callback = record.getCallback();
2757 record.getHandler().post(new Runnable() {
2758 @Override
2759 public void run() {
2760 callback.onParentChanged(call, newParent);
2761 }
2762 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002763 }
2764 }
2765
Andrew Lee011728f2015-04-23 15:47:06 -07002766 private void fireChildrenChanged(final List<Call> children) {
2767 for (CallbackRecord<Callback> record : mCallbackRecords) {
2768 final Call call = this;
2769 final Callback callback = record.getCallback();
2770 record.getHandler().post(new Runnable() {
2771 @Override
2772 public void run() {
2773 callback.onChildrenChanged(call, children);
2774 }
2775 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002776 }
2777 }
2778
Andrew Lee011728f2015-04-23 15:47:06 -07002779 private void fireDetailsChanged(final Details details) {
2780 for (CallbackRecord<Callback> record : mCallbackRecords) {
2781 final Call call = this;
2782 final Callback callback = record.getCallback();
2783 record.getHandler().post(new Runnable() {
2784 @Override
2785 public void run() {
2786 callback.onDetailsChanged(call, details);
2787 }
2788 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002789 }
2790 }
2791
Andrew Lee011728f2015-04-23 15:47:06 -07002792 private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
2793 for (CallbackRecord<Callback> record : mCallbackRecords) {
2794 final Call call = this;
2795 final Callback callback = record.getCallback();
2796 record.getHandler().post(new Runnable() {
2797 @Override
2798 public void run() {
2799 callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
2800 }
2801 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002802 }
2803 }
2804
Andrew Lee011728f2015-04-23 15:47:06 -07002805 private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
2806 for (CallbackRecord<Callback> record : mCallbackRecords) {
2807 final Call call = this;
2808 final Callback callback = record.getCallback();
2809 record.getHandler().post(new Runnable() {
2810 @Override
2811 public void run() {
2812 callback.onVideoCallChanged(call, videoCall);
2813 }
2814 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002815 }
2816 }
2817
Andrew Lee011728f2015-04-23 15:47:06 -07002818 private void firePostDialWait(final String remainingPostDialSequence) {
2819 for (CallbackRecord<Callback> record : mCallbackRecords) {
2820 final Call call = this;
2821 final Callback callback = record.getCallback();
2822 record.getHandler().post(new Runnable() {
2823 @Override
2824 public void run() {
2825 callback.onPostDialWait(call, remainingPostDialSequence);
2826 }
2827 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002828 }
2829 }
2830
2831 private void fireCallDestroyed() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002832 /**
2833 * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
2834 * onCallRemoved callback, we remove this call from the Phone's record
2835 * only once all of the registered onCallDestroyed callbacks are executed.
2836 * All the callbacks get removed from our records as a part of this operation
2837 * since onCallDestroyed is the final callback.
2838 */
2839 final Call call = this;
2840 if (mCallbackRecords.isEmpty()) {
2841 // No callbacks registered, remove the call from Phone's record.
2842 mPhone.internalRemoveCall(call);
2843 }
2844 for (final CallbackRecord<Callback> record : mCallbackRecords) {
Andrew Lee011728f2015-04-23 15:47:06 -07002845 final Callback callback = record.getCallback();
2846 record.getHandler().post(new Runnable() {
2847 @Override
2848 public void run() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002849 boolean isFinalRemoval = false;
2850 RuntimeException toThrow = null;
2851 try {
2852 callback.onCallDestroyed(call);
2853 } catch (RuntimeException e) {
2854 toThrow = e;
2855 }
2856 synchronized(Call.this) {
2857 mCallbackRecords.remove(record);
2858 if (mCallbackRecords.isEmpty()) {
2859 isFinalRemoval = true;
2860 }
2861 }
2862 if (isFinalRemoval) {
2863 mPhone.internalRemoveCall(call);
2864 }
2865 if (toThrow != null) {
2866 throw toThrow;
2867 }
Andrew Lee011728f2015-04-23 15:47:06 -07002868 }
2869 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002870 }
2871 }
2872
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002873 private void fireConferenceableCallsChanged() {
Andrew Lee011728f2015-04-23 15:47:06 -07002874 for (CallbackRecord<Callback> record : mCallbackRecords) {
2875 final Call call = this;
2876 final Callback callback = record.getCallback();
2877 record.getHandler().post(new Runnable() {
2878 @Override
2879 public void run() {
2880 callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
2881 }
2882 });
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002883 }
2884 }
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002885
2886 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002887 * Notifies listeners of an incoming connection event.
2888 * <p>
2889 * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
2890 *
2891 * @param event
2892 * @param extras
2893 */
2894 private void fireOnConnectionEvent(final String event, final Bundle extras) {
2895 for (CallbackRecord<Callback> record : mCallbackRecords) {
2896 final Call call = this;
2897 final Callback callback = record.getCallback();
2898 record.getHandler().post(new Runnable() {
2899 @Override
2900 public void run() {
2901 callback.onConnectionEvent(call, event, extras);
2902 }
2903 });
2904 }
2905 }
2906
2907 /**
Hall Liu95d55872017-01-25 17:12:49 -08002908 * Notifies listeners of an RTT on/off change
2909 *
2910 * @param enabled True if RTT is now enabled, false otherwise
2911 */
2912 private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
2913 for (CallbackRecord<Callback> record : mCallbackRecords) {
2914 final Call call = this;
2915 final Callback callback = record.getCallback();
2916 record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
2917 }
2918 }
2919
2920 /**
2921 * Notifies listeners of a RTT mode change
2922 *
2923 * @param mode The new RTT mode
2924 */
2925 private void fireOnRttModeChanged(final int mode) {
2926 for (CallbackRecord<Callback> record : mCallbackRecords) {
2927 final Call call = this;
2928 final Callback callback = record.getCallback();
2929 record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
2930 }
2931 }
2932
2933 /**
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002934 * Determines if two bundles are equal.
2935 *
2936 * @param bundle The original bundle.
2937 * @param newBundle The bundle to compare with.
2938 * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
2939 */
2940 private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
2941 if (bundle == null || newBundle == null) {
2942 return bundle == newBundle;
2943 }
2944
2945 if (bundle.size() != newBundle.size()) {
2946 return false;
2947 }
2948
2949 for(String key : bundle.keySet()) {
2950 if (key != null) {
Grace Jia17005bd2022-05-12 12:49:02 -07002951 if (!newBundle.containsKey(key)) {
2952 return false;
2953 }
qing723dac62022-10-28 03:40:43 +00002954 // In case new call extra contains non-framework class objects, return false to
2955 // force update the call extra
2956 try {
2957 final Object value = bundle.get(key);
2958 final Object newValue = newBundle.get(key);
2959 if (value instanceof Bundle && newValue instanceof Bundle) {
2960 if (!areBundlesEqual((Bundle) value, (Bundle) newValue)) {
2961 return false;
2962 }
2963 }
2964 if (value instanceof byte[] && newValue instanceof byte[]) {
2965 if (!Arrays.equals((byte[]) value, (byte[]) newValue)) {
2966 return false;
2967 }
2968 } else if (!Objects.equals(value, newValue)) {
Grace Jia17005bd2022-05-12 12:49:02 -07002969 return false;
2970 }
qing723dac62022-10-28 03:40:43 +00002971 } catch (BadParcelableException e) {
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002972 return false;
2973 }
2974 }
2975 }
2976 return true;
2977 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002978}