blob: ce9530c196efd2e4c38238dc702581c0173adf33 [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;
Tyler Gunn6e3ecc42018-11-12 11:30:56 -080027import android.os.Build;
Nancy Chen10798dc2014-08-08 14:00:25 -070028import android.os.Bundle;
Andrew Lee011728f2015-04-23 15:47:06 -070029import android.os.Handler;
Hall Liu95d55872017-01-25 17:12:49 -080030import android.os.ParcelFileDescriptor;
Ihab Awade63fadb2014-07-09 21:52:04 -070031
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -080032import com.android.internal.telecom.IVideoProvider;
33
Hall Liu95d55872017-01-25 17:12:49 -080034import java.io.IOException;
35import java.io.InputStreamReader;
36import java.io.OutputStreamWriter;
Hall Liu95d55872017-01-25 17:12:49 -080037import java.lang.annotation.Retention;
38import java.lang.annotation.RetentionPolicy;
39import java.nio.charset.StandardCharsets;
Ihab Awade63fadb2014-07-09 21:52:04 -070040import java.util.ArrayList;
Tyler Gunn071be6f2016-05-10 14:52:33 -070041import java.util.Arrays;
Ihab Awade63fadb2014-07-09 21:52:04 -070042import java.util.Collections;
43import java.util.List;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070044import java.util.Map;
Ihab Awade63fadb2014-07-09 21:52:04 -070045import java.util.Objects;
Jay Shrauner229e3822014-08-15 09:23:07 -070046import java.util.concurrent.CopyOnWriteArrayList;
Ihab Awade63fadb2014-07-09 21:52:04 -070047
48/**
49 * Represents an ongoing phone call that the in-call app should present to the user.
50 */
51public final class Call {
52 /**
53 * The state of a {@code Call} when newly created.
54 */
55 public static final int STATE_NEW = 0;
56
57 /**
58 * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
59 */
60 public static final int STATE_DIALING = 1;
61
62 /**
63 * The state of an incoming {@code Call} when ringing locally, but not yet connected.
64 */
65 public static final int STATE_RINGING = 2;
66
67 /**
68 * The state of a {@code Call} when in a holding state.
69 */
70 public static final int STATE_HOLDING = 3;
71
72 /**
73 * The state of a {@code Call} when actively supporting conversation.
74 */
75 public static final int STATE_ACTIVE = 4;
76
77 /**
78 * The state of a {@code Call} when no further voice or other communication is being
79 * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
80 * is no longer active, and the local data transport has or inevitably will release resources
81 * associated with this {@code Call}.
82 */
83 public static final int STATE_DISCONNECTED = 7;
84
Nancy Chen5da0fd52014-07-08 14:16:17 -070085 /**
Santos Cordone3c507b2015-04-23 14:44:19 -070086 * The state of an outgoing {@code Call} when waiting on user to select a
87 * {@link PhoneAccount} through which to place the call.
Nancy Chen5da0fd52014-07-08 14:16:17 -070088 */
Santos Cordone3c507b2015-04-23 14:44:19 -070089 public static final int STATE_SELECT_PHONE_ACCOUNT = 8;
90
91 /**
92 * @hide
93 * @deprecated use STATE_SELECT_PHONE_ACCOUNT.
94 */
95 @Deprecated
96 @SystemApi
97 public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT;
Nancy Chen5da0fd52014-07-08 14:16:17 -070098
Nancy Chene20930f2014-08-07 16:17:21 -070099 /**
Nancy Chene9b7a8e2014-08-08 14:26:27 -0700100 * The initial state of an outgoing {@code Call}.
101 * Common transitions are to {@link #STATE_DIALING} state for a successful call or
102 * {@link #STATE_DISCONNECTED} if it failed.
Nancy Chene20930f2014-08-07 16:17:21 -0700103 */
104 public static final int STATE_CONNECTING = 9;
105
Nancy Chen513c8922014-09-17 14:47:20 -0700106 /**
Tyler Gunn4afc6af2014-10-07 10:14:55 -0700107 * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
108 * call has not yet been disconnected by the underlying {@code ConnectionService}. The next
109 * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
110 */
111 public static final int STATE_DISCONNECTING = 10;
112
113 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700114 * The state of an external call which is in the process of being pulled from a remote device to
115 * the local device.
116 * <p>
117 * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
118 * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
119 * <p>
120 * An {@link InCallService} will only see this state if it has the
121 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
122 * manifest.
123 */
124 public static final int STATE_PULLING_CALL = 11;
125
126 /**
Hall Liu6dfa2492019-10-01 17:20:39 -0700127 * The state of a call that is active with the network, but the audio from the call is
128 * being intercepted by an app on the local device. Telecom does not hold audio focus in this
129 * state, and the call will be invisible to the user except for a persistent notification.
130 */
131 public static final int STATE_AUDIO_PROCESSING = 12;
132
133 /**
134 * The state of a call that is being presented to the user after being in
135 * {@link #STATE_AUDIO_PROCESSING}. The call is still active with the network in this case, and
136 * Telecom will hold audio focus and play a ringtone if appropriate.
137 */
138 public static final int STATE_SIMULATED_RINGING = 13;
139
140 /**
Tyler Gunn1e406ca2021-03-18 16:47:14 -0700141 * @hide
142 */
143 @IntDef(prefix = { "STATE_" },
144 value = {
145 STATE_NEW,
146 STATE_DIALING,
147 STATE_RINGING,
148 STATE_HOLDING,
149 STATE_ACTIVE,
150 STATE_DISCONNECTED,
151 STATE_SELECT_PHONE_ACCOUNT,
152 STATE_CONNECTING,
153 STATE_DISCONNECTING,
154 STATE_PULLING_CALL,
155 STATE_AUDIO_PROCESSING,
156 STATE_SIMULATED_RINGING
157 })
158 @Retention(RetentionPolicy.SOURCE)
159 public @interface CallState {};
160
161 /**
Nancy Chen513c8922014-09-17 14:47:20 -0700162 * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
163 * extras. Used to pass the phone accounts to display on the front end to the user in order to
164 * select phone accounts to (for example) place a call.
Hall Liu34d9e242018-11-21 17:05:58 -0800165 * @deprecated Use the list from {@link #EXTRA_SUGGESTED_PHONE_ACCOUNTS} instead.
Nancy Chen513c8922014-09-17 14:47:20 -0700166 */
Hall Liu34d9e242018-11-21 17:05:58 -0800167 @Deprecated
Nancy Chen513c8922014-09-17 14:47:20 -0700168 public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
169
mike dooley4af561f2016-12-20 08:55:17 -0800170 /**
Hall Liu34d9e242018-11-21 17:05:58 -0800171 * Key for extra used to pass along a list of {@link PhoneAccountSuggestion}s to the in-call
172 * UI when a call enters the {@link #STATE_SELECT_PHONE_ACCOUNT} state. The list included here
173 * will have the same length and be in the same order as the list passed with
174 * {@link #AVAILABLE_PHONE_ACCOUNTS}.
175 */
176 public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS =
177 "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS";
178
179 /**
mike dooley91217422017-03-09 12:58:42 -0800180 * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC)
181 * when the last outgoing emergency call was made. This is used to identify potential emergency
182 * callbacks.
mike dooley4af561f2016-12-20 08:55:17 -0800183 */
184 public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
185 "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
186
Usman Abdullahb0dc29a2019-03-06 15:54:56 -0800187
188 /**
189 * Extra key used to indicate whether a {@link CallScreeningService} has requested to silence
190 * the ringtone for a call. If the {@link InCallService} declares
191 * {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} in its manifest, it should not
192 * play a ringtone for an incoming call with this extra key set.
193 */
194 public static final String EXTRA_SILENT_RINGING_REQUESTED =
195 "android.telecom.extra.SILENT_RINGING_REQUESTED";
196
Tyler Gunn8bf76572017-04-06 15:30:08 -0700197 /**
198 * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
199 * Telecom that the user has requested that the current {@link Call} should be handed over
200 * to another {@link ConnectionService}.
201 * <p>
202 * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
203 * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
204 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700205 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
206 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700207 */
208 public static final String EVENT_REQUEST_HANDOVER =
209 "android.telecom.event.REQUEST_HANDOVER";
210
211 /**
212 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
213 * {@link PhoneAccountHandle} to which a call should be handed over to.
214 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700215 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
216 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700217 */
218 public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
219 "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
220
221 /**
222 * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
223 * video state of the call when it is handed over to the new {@link PhoneAccount}.
224 * <p>
225 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
226 * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
227 * {@link VideoProfile#STATE_TX_ENABLED}.
228 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700229 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
230 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700231 */
232 public static final String EXTRA_HANDOVER_VIDEO_STATE =
233 "android.telecom.extra.HANDOVER_VIDEO_STATE";
234
235 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700236 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Used by the
237 * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra
238 * information to the handover {@link ConnectionService} specified by
239 * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}.
240 * <p>
241 * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the
242 * {@link ConnectionService} via the request extras when
243 * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
244 * is called to initate the handover.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700245 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700246 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
247 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700248 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700249 public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700250
251 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700252 * Call event sent from Telecom to the handover {@link ConnectionService} via
253 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
254 * to the {@link ConnectionService} has completed successfully.
255 * <p>
256 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700257 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700258 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
259 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700260 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700261 public static final String EVENT_HANDOVER_COMPLETE =
262 "android.telecom.event.HANDOVER_COMPLETE";
Tyler Gunn34a2b312017-06-23 08:32:00 -0700263
264 /**
265 * Call event sent from Telecom to the handover destination {@link ConnectionService} via
266 * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the
267 * source connection has disconnected. The {@link Bundle} parameter for the call event will be
268 * {@code null}.
269 * <p>
270 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
271 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700272 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
273 * APIs instead.
Tyler Gunn34a2b312017-06-23 08:32:00 -0700274 */
275 public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
276 "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
277
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700278 /**
279 * Call event sent from Telecom to the handover {@link ConnectionService} via
280 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
281 * to the {@link ConnectionService} has failed.
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 Gunn9f6f0472017-04-17 18:25:22 -0700287 */
288 public static final String EVENT_HANDOVER_FAILED =
289 "android.telecom.event.HANDOVER_FAILED";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700290
Tyler Gunnd5821842021-02-05 11:12:57 -0800291 /**
292 * Event reported from the Telecom stack to report an in-call diagnostic message which the
293 * dialer app may opt to display to the user. A diagnostic message is used to communicate
294 * scenarios the device has detected which may impact the quality of the ongoing call.
295 * <p>
296 * For example a problem with a bluetooth headset may generate a recommendation for the user to
297 * try using the speakerphone instead, or if the device detects it has entered a poor service
298 * area, the user might be warned so that they can finish their call prior to it dropping.
299 * <p>
300 * A diagnostic message is considered persistent in nature. When the user enters a poor service
301 * area, for example, the accompanying diagnostic message persists until they leave the area
302 * of poor service. Each message is accompanied with a {@link #EXTRA_DIAGNOSTIC_MESSAGE_ID}
303 * which uniquely identifies the diagnostic condition being reported. The framework raises a
304 * call event of type {@link #EVENT_CLEAR_DIAGNOSTIC_MESSAGE} when the condition reported has
305 * been cleared. The dialer app should display the diagnostic message until it is cleared.
306 * If multiple diagnostic messages are sent with different IDs (which have not yet been cleared)
307 * the dialer app should prioritize the most recently received message, but still provide the
308 * user with a means to review past messages.
309 * <p>
310 * The text of the message is found in {@link #EXTRA_DIAGNOSTIC_MESSAGE} in the form of a human
311 * readable {@link CharSequence} which is intended for display in the call UX.
312 * <p>
313 * The telecom framework audibly notifies the user of the presence of a diagnostic message, so
314 * the dialer app needs only to concern itself with visually displaying the message.
315 * <p>
316 * The dialer app receives this event via
317 * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)}.
318 */
319 public static final String EVENT_DISPLAY_DIAGNOSTIC_MESSAGE =
320 "android.telecom.event.DISPLAY_DIAGNOSTIC_MESSAGE";
321
322 /**
323 * Event reported from the telecom framework when a diagnostic message previously raised with
324 * {@link #EVENT_DISPLAY_DIAGNOSTIC_MESSAGE} has cleared and is no longer pertinent.
325 * <p>
326 * The {@link #EXTRA_DIAGNOSTIC_MESSAGE_ID} indicates the diagnostic message which has been
327 * cleared.
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_CLEAR_DIAGNOSTIC_MESSAGE =
333 "android.telecom.event.CLEAR_DIAGNOSTIC_MESSAGE";
334
335 /**
336 * Integer extra representing a message ID for a message posted via
337 * {@link #EVENT_DISPLAY_DIAGNOSTIC_MESSAGE}. Used to ensure that the dialer app knows when
338 * the message in question has cleared via {@link #EVENT_CLEAR_DIAGNOSTIC_MESSAGE}.
339 */
340 public static final String EXTRA_DIAGNOSTIC_MESSAGE_ID =
341 "android.telecom.extra.DIAGNOSTIC_MESSAGE_ID";
342
343 /**
344 * {@link CharSequence} extra used with {@link #EVENT_DISPLAY_DIAGNOSTIC_MESSAGE}. This is the
345 * diagnostic message the dialer app should display.
346 */
347 public static final String EXTRA_DIAGNOSTIC_MESSAGE =
348 "android.telecom.extra.DIAGNOSTIC_MESSAGE";
Tyler Gunnfacfdee2020-01-23 13:10:37 -0800349
350 /**
351 * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
352 * call because they have declined to answer it. This typically means that they are unable
353 * to answer the call at this time and would prefer it be sent to voicemail.
354 */
355 public static final int REJECT_REASON_DECLINED = 1;
356
357 /**
358 * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
359 * call because it is an unwanted call. This allows the user to indicate that they are
360 * rejecting a call because it is likely a nuisance call.
361 */
362 public static final int REJECT_REASON_UNWANTED = 2;
363
364 /**
365 * @hide
366 */
367 @IntDef(prefix = { "REJECT_REASON_" },
368 value = {REJECT_REASON_DECLINED, REJECT_REASON_UNWANTED})
369 @Retention(RetentionPolicy.SOURCE)
370 public @interface RejectReason {};
371
Ihab Awade63fadb2014-07-09 21:52:04 -0700372 public static class Details {
Tyler Gunn94f8f112018-12-17 09:56:11 -0800373 /** @hide */
374 @Retention(RetentionPolicy.SOURCE)
375 @IntDef(
376 prefix = { "DIRECTION_" },
377 value = {DIRECTION_UNKNOWN, DIRECTION_INCOMING, DIRECTION_OUTGOING})
378 public @interface CallDirection {}
379
380 /**
381 * Indicates that the call is neither and incoming nor an outgoing call. This can be the
382 * case for calls reported directly by a {@link ConnectionService} in special cases such as
383 * call handovers.
384 */
385 public static final int DIRECTION_UNKNOWN = -1;
386
387 /**
388 * Indicates that the call is an incoming call.
389 */
390 public static final int DIRECTION_INCOMING = 0;
391
392 /**
393 * Indicates that the call is an outgoing call.
394 */
395 public static final int DIRECTION_OUTGOING = 1;
396
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800397 /** Call can currently be put on hold or unheld. */
398 public static final int CAPABILITY_HOLD = 0x00000001;
399
400 /** Call supports the hold feature. */
401 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
402
403 /**
404 * Calls within a conference can be merged. A {@link ConnectionService} has the option to
405 * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
406 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
407 * capability allows a merge button to be shown while the conference call is in the foreground
408 * of the in-call UI.
409 * <p>
410 * This is only intended for use by a {@link Conference}.
411 */
412 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
413
414 /**
415 * Calls within a conference can be swapped between foreground and background.
416 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
417 * <p>
418 * This is only intended for use by a {@link Conference}.
419 */
420 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
421
422 /**
423 * @hide
424 */
Andrew Lee2378ea72015-04-29 14:38:11 -0700425 public static final int CAPABILITY_UNUSED_1 = 0x00000010;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800426
427 /** Call supports responding via text option. */
428 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
429
430 /** Call can be muted. */
431 public static final int CAPABILITY_MUTE = 0x00000040;
432
433 /**
434 * Call supports conference call management. This capability only applies to {@link Conference}
435 * calls which can have {@link Connection}s as children.
436 */
437 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
438
439 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700440 * Local device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800441 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700442 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800443
444 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700445 * Local device supports transmitting video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800446 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700447 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800448
449 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700450 * Local device supports bidirectional video calling.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800451 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700452 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700453 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800454
455 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700456 * Remote device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800457 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700458 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
459
460 /**
461 * Remote device supports transmitting video.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700462 */
463 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
464
465 /**
466 * Remote device supports bidirectional video calling.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700467 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700468 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700469 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800470
471 /**
472 * Call is able to be separated from its parent {@code Conference}, if any.
473 */
474 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
475
476 /**
477 * Call is able to be individually disconnected when in a {@code Conference}.
478 */
479 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
480
481 /**
Dong Zhou89f41eb2015-03-15 11:59:49 -0500482 * Speed up audio setup for MT call.
483 * @hide
484 */
Tyler Gunn96d6c402015-03-18 12:39:23 -0700485 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
486
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700487 /**
488 * Call can be upgraded to a video call.
Rekha Kumar07366812015-03-24 16:42:31 -0700489 * @hide
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800490 * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
491 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call
492 * whether or not video calling is supported.
Rekha Kumar07366812015-03-24 16:42:31 -0700493 */
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800494 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
Rekha Kumar07366812015-03-24 16:42:31 -0700495 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
496
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700497 /**
498 * For video calls, indicates whether the outgoing video for the call can be paused using
Yorke Lee32f24732015-05-12 16:18:03 -0700499 * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700500 */
501 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
502
Bryce Lee81901682015-08-28 16:38:02 -0700503 /**
504 * Call sends responses through connection.
505 * @hide
506 */
Tyler Gunnf97a0092016-01-19 15:59:34 -0800507 public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;
508
509 /**
510 * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
511 * <p>
512 * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
513 * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
514 * downgraded from a video call back to a VideoState of
515 * {@link VideoProfile#STATE_AUDIO_ONLY}.
516 * <p>
517 * Intuitively, a call which can be downgraded to audio should also have local and remote
518 * video
519 * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
520 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
521 */
522 public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
Bryce Lee81901682015-08-28 16:38:02 -0700523
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700524 /**
525 * When set for an external call, indicates that this {@code Call} can be pulled from a
526 * remote device to the current device.
527 * <p>
528 * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
529 * <p>
530 * An {@link InCallService} will only see calls with this capability if it has the
531 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
532 * in its manifest.
533 * <p>
534 * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
Tyler Gunn720c6642016-03-22 09:02:47 -0700535 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700536 */
537 public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
538
Pooja Jaind34698d2017-12-28 14:15:31 +0530539 /** Call supports the deflect feature. */
540 public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
541
Tyler Gunn0c62ef02020-02-11 14:39:43 -0800542 /**
543 * Call supports adding participants to the call via
Grace Jia8587ee52020-07-10 15:42:32 -0700544 * {@link #addConferenceParticipants(List)}. Once participants are added, the call becomes
545 * an adhoc conference call ({@link #PROPERTY_IS_ADHOC_CONFERENCE}).
Tyler Gunn0c62ef02020-02-11 14:39:43 -0800546 */
Ravi Paluri404babb2020-01-23 19:02:44 +0530547 public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
Ravi Palurif4b38e72020-02-05 12:35:41 +0530548
549 /**
550 * When set for a call, indicates that this {@code Call} can be transferred to another
551 * number.
Tyler Gunn460360d2020-07-29 10:21:45 -0700552 * Call supports the confirmed and unconfirmed call transfer feature.
Ravi Palurif4b38e72020-02-05 12:35:41 +0530553 *
554 * @hide
555 */
556 public static final int CAPABILITY_TRANSFER = 0x04000000;
557
558 /**
559 * When set for a call, indicates that this {@code Call} can be transferred to another
560 * ongoing call.
561 * Call supports the consultative call transfer feature.
562 *
563 * @hide
564 */
565 public static final int CAPABILITY_TRANSFER_CONSULTATIVE = 0x08000000;
566
Alvin Dey2f37d772018-05-18 23:16:10 +0530567 /**
568 * Indicates whether the remote party supports RTT or not to the UI.
569 */
570
571 public static final int CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT = 0x10000000;
572
Tyler Gunnd11a3152015-03-18 13:09:14 -0700573 //******************************************************************************************
Grace Jiae04723f2022-01-26 16:24:48 +0000574 // Next CAPABILITY value: 0x20000000
Andrew Lee2378ea72015-04-29 14:38:11 -0700575 //******************************************************************************************
576
577 /**
578 * Whether the call is currently a conference.
579 */
580 public static final int PROPERTY_CONFERENCE = 0x00000001;
581
582 /**
583 * Whether the call is a generic conference, where we do not know the precise state of
584 * participants in the conference (eg. on CDMA).
585 */
586 public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
587
588 /**
589 * Whether the call is made while the device is in emergency callback mode.
590 */
591 public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
592
593 /**
594 * Connection is using WIFI.
595 */
596 public static final int PROPERTY_WIFI = 0x00000008;
597
598 /**
Tyler Gunn6b6ae552018-10-11 10:42:10 -0700599 * When set, the UI should indicate to the user that a call is using high definition
600 * audio.
601 * <p>
602 * The underlying {@link ConnectionService} is responsible for reporting this
603 * property. It is important to note that this property is not intended to report the
604 * actual audio codec being used for a Call, but whether the call should be indicated
605 * to the user as high definition.
606 * <p>
607 * The Android Telephony stack reports this property for calls based on a number
608 * of factors, including which audio codec is used and whether a call is using an HD
609 * codec end-to-end. Some mobile operators choose to suppress display of an HD indication,
610 * and in these cases this property will not be set for a call even if the underlying audio
611 * codec is in fact "high definition".
Andrew Lee2378ea72015-04-29 14:38:11 -0700612 */
613 public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
614
Tony Maka68dcce2015-12-17 09:31:18 +0000615 /**
Tony Mak53b5df42016-05-19 13:40:38 +0100616 * Whether the call is associated with the work profile.
617 */
618 public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;
619
620 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700621 * When set, indicates that this {@code Call} does not actually exist locally for the
622 * {@link ConnectionService}.
623 * <p>
624 * Consider, for example, a scenario where a user has two phones with the same phone number.
625 * When a user places a call on one device, the telephony stack can represent that call on
626 * the other device by adding it to the {@link ConnectionService} with the
Tyler Gunn720c6642016-03-22 09:02:47 -0700627 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700628 * <p>
629 * An {@link InCallService} will only see calls with this property if it has the
630 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
631 * in its manifest.
632 * <p>
Tyler Gunn720c6642016-03-22 09:02:47 -0700633 * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700634 */
635 public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
636
Brad Ebinger15847072016-05-18 11:08:36 -0700637 /**
638 * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
639 */
640 public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
641
Tyler Gunn24e18332017-02-10 09:42:49 -0800642 /**
643 * Indicates that the call is from a self-managed {@link ConnectionService}.
644 * <p>
645 * See also {@link Connection#PROPERTY_SELF_MANAGED}
646 */
647 public static final int PROPERTY_SELF_MANAGED = 0x00000100;
648
Eric Erfanianec881872017-12-06 16:27:53 -0800649 /**
650 * Indicates the call used Assisted Dialing.
Tyler Gunn5567d742019-10-31 13:04:37 -0700651 *
652 * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING
Eric Erfanianec881872017-12-06 16:27:53 -0800653 */
Tyler Gunnc9503d62020-01-27 10:30:51 -0800654 public static final int PROPERTY_ASSISTED_DIALING = 0x00000200;
Eric Erfanianec881872017-12-06 16:27:53 -0800655
Hall Liue9041242018-02-09 16:40:03 -0800656 /**
657 * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
658 * {@link RttCall} object that is used to send and receive text.
659 */
660 public static final int PROPERTY_RTT = 0x00000400;
661
Tyler Gunn5bd90852018-09-21 09:37:07 -0700662 /**
663 * Indicates that the call has been identified as the network as an emergency call. This
664 * property may be set for both incoming and outgoing calls which the network identifies as
665 * emergency calls.
666 */
667 public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 0x00000800;
668
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700669 /**
670 * Indicates that the call is using VoIP audio mode.
671 * <p>
672 * When this property is set, the {@link android.media.AudioManager} audio mode for this
673 * call will be {@link android.media.AudioManager#MODE_IN_COMMUNICATION}. When this
674 * property is not set, the audio mode for this call will be
675 * {@link android.media.AudioManager#MODE_IN_CALL}.
676 * <p>
677 * This property reflects changes made using {@link Connection#setAudioModeIsVoip(boolean)}.
678 * <p>
679 * You can use this property to determine whether an un-answered incoming call or a held
680 * call will use VoIP audio mode (if the call does not currently have focus, the system
681 * audio mode may not reflect the mode the call will use).
682 */
683 public static final int PROPERTY_VOIP_AUDIO_MODE = 0x00001000;
684
Ravi Paluri80aa2142019-12-02 11:57:37 +0530685 /**
686 * Indicates that the call is an adhoc conference call. This property can be set for both
Grace Jia8587ee52020-07-10 15:42:32 -0700687 * incoming and outgoing calls. An adhoc conference call is formed using
688 * {@link #addConferenceParticipants(List)},
689 * {@link TelecomManager#addNewIncomingConference(PhoneAccountHandle, Bundle)}, or
690 * {@link TelecomManager#startConference(List, Bundle)}, rather than by merging existing
691 * call using {@link #conference(Call)}.
Ravi Paluri80aa2142019-12-02 11:57:37 +0530692 */
693 public static final int PROPERTY_IS_ADHOC_CONFERENCE = 0x00002000;
694
Sooraj Sasindran64f05b12020-11-18 12:07:10 -0800695 /**
Sooraj Sasindranfa1e57a2021-03-22 13:44:14 -0700696 * Connection is using cross sim technology.
697 * <p>
698 * Indicates that the {@link Connection} is using a cross sim technology which would
699 * register IMS over internet APN of default data subscription.
700 * <p>
Sooraj Sasindran64f05b12020-11-18 12:07:10 -0800701 */
702 public static final int PROPERTY_CROSS_SIM = 0x00004000;
703
Grace Jia22c8b962021-10-28 17:04:29 -0700704 /**
705 * Connection is a tethered external call.
706 * Indicates that the {@link Connection} is fixed on this device but the audio streams are
707 * re-routed to another device.
708 */
709 public static final int PROPERTY_TETHERED_CALL = 0x00008000;
710
Andrew Lee2378ea72015-04-29 14:38:11 -0700711 //******************************************************************************************
Grace Jia22c8b962021-10-28 17:04:29 -0700712 // Next PROPERTY value: 0x00010000
Tyler Gunnd11a3152015-03-18 13:09:14 -0700713 //******************************************************************************************
Tyler Gunn068085b2015-02-06 13:56:52 -0800714
Tyler Gunn1e406ca2021-03-18 16:47:14 -0700715 private final @CallState int mState;
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800716 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700717 private final Uri mHandle;
718 private final int mHandlePresentation;
719 private final String mCallerDisplayName;
720 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700721 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700722 private final int mCallCapabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700723 private final int mCallProperties;
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800724 private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700725 private final DisconnectCause mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700726 private final long mConnectTimeMillis;
727 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700728 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700729 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700730 private final Bundle mExtras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700731 private final Bundle mIntentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700732 private final long mCreationTimeMillis;
Hall Liuef98bf82020-01-09 15:22:44 -0800733 private final String mContactDisplayName;
Tyler Gunn94f8f112018-12-17 09:56:11 -0800734 private final @CallDirection int mCallDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700735 private final @Connection.VerificationStatus int mCallerNumberVerificationStatus;
Ihab Awade63fadb2014-07-09 21:52:04 -0700736
737 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800738 * Whether the supplied capabilities supports the specified capability.
739 *
740 * @param capabilities A bit field of capabilities.
741 * @param capability The capability to check capabilities for.
742 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800743 */
744 public static boolean can(int capabilities, int capability) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800745 return (capabilities & capability) == capability;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800746 }
747
748 /**
749 * Whether the capabilities of this {@code Details} supports the specified capability.
750 *
751 * @param capability The capability to check capabilities for.
752 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800753 */
754 public boolean can(int capability) {
755 return can(mCallCapabilities, capability);
756 }
757
758 /**
759 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
760 *
761 * @param capabilities A capability bit field.
762 * @return A human readable string representation.
763 */
764 public static String capabilitiesToString(int capabilities) {
765 StringBuilder builder = new StringBuilder();
766 builder.append("[Capabilities:");
767 if (can(capabilities, CAPABILITY_HOLD)) {
768 builder.append(" CAPABILITY_HOLD");
769 }
770 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
771 builder.append(" CAPABILITY_SUPPORT_HOLD");
772 }
773 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
774 builder.append(" CAPABILITY_MERGE_CONFERENCE");
775 }
776 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
777 builder.append(" CAPABILITY_SWAP_CONFERENCE");
778 }
779 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
780 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
781 }
782 if (can(capabilities, CAPABILITY_MUTE)) {
783 builder.append(" CAPABILITY_MUTE");
784 }
785 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
786 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
787 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700788 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
789 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
790 }
791 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
792 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
793 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700794 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
795 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800796 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700797 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
798 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
799 }
800 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
801 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
802 }
Tyler Gunnf97a0092016-01-19 15:59:34 -0800803 if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
804 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
805 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700806 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
807 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800808 }
Dong Zhou89f41eb2015-03-15 11:59:49 -0500809 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
Tyler Gunnd11a3152015-03-18 13:09:14 -0700810 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
Dong Zhou89f41eb2015-03-15 11:59:49 -0500811 }
Rekha Kumar07366812015-03-24 16:42:31 -0700812 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
813 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
814 }
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700815 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
816 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
817 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700818 if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
819 builder.append(" CAPABILITY_CAN_PULL_CALL");
820 }
Pooja Jaind34698d2017-12-28 14:15:31 +0530821 if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
822 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
823 }
Ravi Paluri404babb2020-01-23 19:02:44 +0530824 if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) {
825 builder.append(" CAPABILITY_ADD_PARTICIPANT");
826 }
Ravi Palurif4b38e72020-02-05 12:35:41 +0530827 if (can(capabilities, CAPABILITY_TRANSFER)) {
828 builder.append(" CAPABILITY_TRANSFER");
829 }
830 if (can(capabilities, CAPABILITY_TRANSFER_CONSULTATIVE)) {
831 builder.append(" CAPABILITY_TRANSFER_CONSULTATIVE");
832 }
Alvin Dey2f37d772018-05-18 23:16:10 +0530833 if (can(capabilities, CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT)) {
834 builder.append(" CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT");
835 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800836 builder.append("]");
837 return builder.toString();
838 }
839
840 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700841 * Whether the supplied properties includes the specified property.
842 *
843 * @param properties A bit field of properties.
844 * @param property The property to check properties for.
845 * @return Whether the specified property is supported.
846 */
847 public static boolean hasProperty(int properties, int property) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800848 return (properties & property) == property;
Andrew Lee2378ea72015-04-29 14:38:11 -0700849 }
850
851 /**
852 * Whether the properties of this {@code Details} includes the specified property.
853 *
854 * @param property The property to check properties for.
855 * @return Whether the specified property is supported.
856 */
857 public boolean hasProperty(int property) {
858 return hasProperty(mCallProperties, property);
859 }
860
861 /**
862 * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
863 *
864 * @param properties A property bit field.
865 * @return A human readable string representation.
866 */
867 public static String propertiesToString(int properties) {
868 StringBuilder builder = new StringBuilder();
869 builder.append("[Properties:");
870 if (hasProperty(properties, PROPERTY_CONFERENCE)) {
871 builder.append(" PROPERTY_CONFERENCE");
872 }
873 if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
874 builder.append(" PROPERTY_GENERIC_CONFERENCE");
875 }
876 if (hasProperty(properties, PROPERTY_WIFI)) {
877 builder.append(" PROPERTY_WIFI");
878 }
879 if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
880 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
881 }
882 if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
Yorke Leebe2a4a22015-06-12 10:10:55 -0700883 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
Andrew Lee2378ea72015-04-29 14:38:11 -0700884 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700885 if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
886 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
887 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700888 if (hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
Brad Ebinger15847072016-05-18 11:08:36 -0700889 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
890 }
Tyler Gunnc9503d62020-01-27 10:30:51 -0800891 if (hasProperty(properties, PROPERTY_ASSISTED_DIALING)) {
Eric Erfanianec881872017-12-06 16:27:53 -0800892 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
893 }
Tyler Gunn5bd90852018-09-21 09:37:07 -0700894 if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
895 builder.append(" PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL");
896 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700897 if (hasProperty(properties, PROPERTY_RTT)) {
898 builder.append(" PROPERTY_RTT");
899 }
900 if (hasProperty(properties, PROPERTY_VOIP_AUDIO_MODE)) {
901 builder.append(" PROPERTY_VOIP_AUDIO_MODE");
902 }
Ravi Paluri80aa2142019-12-02 11:57:37 +0530903 if (hasProperty(properties, PROPERTY_IS_ADHOC_CONFERENCE)) {
904 builder.append(" PROPERTY_IS_ADHOC_CONFERENCE");
905 }
Sooraj Sasindran64f05b12020-11-18 12:07:10 -0800906 if (hasProperty(properties, PROPERTY_CROSS_SIM)) {
907 builder.append(" PROPERTY_CROSS_SIM");
908 }
Grace Jia22c8b962021-10-28 17:04:29 -0700909 if (hasProperty(properties, PROPERTY_TETHERED_CALL)) {
910 builder.append(" PROPERTY_TETHERED_CALL");
911 }
Andrew Lee2378ea72015-04-29 14:38:11 -0700912 builder.append("]");
913 return builder.toString();
914 }
915
Tyler Gunn1e406ca2021-03-18 16:47:14 -0700916 /**
917 * @return the state of the {@link Call} represented by this {@link Call.Details}.
918 */
919 public final @CallState int getState() {
920 return mState;
921 }
922
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800923 /** {@hide} */
Hall Liu31de23d2019-10-11 15:38:29 -0700924 @TestApi
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800925 public String getTelecomCallId() {
926 return mTelecomCallId;
927 }
928
Andrew Lee2378ea72015-04-29 14:38:11 -0700929 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700930 * @return The handle (e.g., phone number) to which the {@code Call} is currently
931 * connected.
932 */
933 public Uri getHandle() {
934 return mHandle;
935 }
936
937 /**
938 * @return The presentation requirements for the handle. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700939 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700940 */
941 public int getHandlePresentation() {
942 return mHandlePresentation;
943 }
944
945 /**
Tyler Gunnd081f042018-12-04 12:56:45 -0800946 * The display name for the caller.
947 * <p>
948 * This is the name as reported by the {@link ConnectionService} associated with this call.
Tyler Gunnd081f042018-12-04 12:56:45 -0800949 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700950 * @return The display name for the caller.
951 */
952 public String getCallerDisplayName() {
953 return mCallerDisplayName;
954 }
955
956 /**
957 * @return The presentation requirements for the caller display name. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700958 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700959 */
960 public int getCallerDisplayNamePresentation() {
961 return mCallerDisplayNamePresentation;
962 }
963
964 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700965 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
966 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700967 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700968 public PhoneAccountHandle getAccountHandle() {
969 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -0700970 }
971
972 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800973 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
974 * {@code CAPABILITY_*} constants in this class.
Ihab Awade63fadb2014-07-09 21:52:04 -0700975 */
Ihab Awad5d0410f2014-07-30 10:07:40 -0700976 public int getCallCapabilities() {
977 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700978 }
979
980 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700981 * @return A bitmask of the properties of the {@code Call}, as defined by the various
982 * {@code PROPERTY_*} constants in this class.
Andrew Lee223ad142014-08-27 16:33:08 -0700983 */
984 public int getCallProperties() {
985 return mCallProperties;
986 }
987
988 /**
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800989 * @return a bitmask of the audio routes available for the call.
990 *
991 * @hide
992 */
993 public int getSupportedAudioRoutes() {
994 return mSupportedAudioRoutes;
995 }
996
997 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700998 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
Nancy Chenf4cf77c2014-09-19 10:53:21 -0700999 * by {@link android.telecom.DisconnectCause}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001000 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001001 public DisconnectCause getDisconnectCause() {
1002 return mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -07001003 }
1004
1005 /**
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001006 * Returns the time the {@link Call} connected (i.e. became active). This information is
1007 * updated periodically, but user interfaces should not rely on this to display the "call
1008 * time clock". For the time when the call was first added to Telecom, see
1009 * {@link #getCreationTimeMillis()}.
1010 *
1011 * @return The time the {@link Call} connected in milliseconds since the epoch.
Ihab Awade63fadb2014-07-09 21:52:04 -07001012 */
Jay Shrauner164a0ac2015-04-14 18:16:10 -07001013 public final long getConnectTimeMillis() {
Ihab Awade63fadb2014-07-09 21:52:04 -07001014 return mConnectTimeMillis;
1015 }
1016
1017 /**
1018 * @return Information about any calling gateway the {@code Call} may be using.
1019 */
1020 public GatewayInfo getGatewayInfo() {
1021 return mGatewayInfo;
1022 }
1023
Andrew Lee7a341382014-07-15 17:05:08 -07001024 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -07001025 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -07001026 */
1027 public int getVideoState() {
1028 return mVideoState;
1029 }
1030
Ihab Awad5d0410f2014-07-30 10:07:40 -07001031 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001032 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
Ihab Awad5d0410f2014-07-30 10:07:40 -07001033 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -07001034 */
1035 public StatusHints getStatusHints() {
1036 return mStatusHints;
1037 }
1038
Nancy Chen10798dc2014-08-08 14:00:25 -07001039 /**
Santos Cordon6b7f9552015-05-27 17:21:45 -07001040 * @return The extras associated with this call.
Nancy Chen10798dc2014-08-08 14:00:25 -07001041 */
1042 public Bundle getExtras() {
1043 return mExtras;
1044 }
1045
Santos Cordon6b7f9552015-05-27 17:21:45 -07001046 /**
1047 * @return The extras used with the original intent to place this call.
1048 */
1049 public Bundle getIntentExtras() {
1050 return mIntentExtras;
1051 }
1052
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001053 /**
1054 * Returns the time when the call was first created and added to Telecom. This is the same
1055 * time that is logged as the start time in the Call Log (see
1056 * {@link android.provider.CallLog.Calls#DATE}). To determine when the call was connected
1057 * (became active), see {@link #getConnectTimeMillis()}.
1058 *
1059 * @return The creation time of the call, in millis since the epoch.
1060 */
1061 public long getCreationTimeMillis() {
1062 return mCreationTimeMillis;
1063 }
1064
Tyler Gunnd081f042018-12-04 12:56:45 -08001065 /**
Hall Liuef98bf82020-01-09 15:22:44 -08001066 * Returns the name of the caller on the remote end, as derived from a
1067 * {@link android.provider.ContactsContract} lookup of the call's handle.
1068 * @return The name of the caller, or {@code null} if the lookup is not yet complete, if
1069 * there's no contacts entry for the caller, or if the {@link InCallService} does
1070 * not hold the {@link android.Manifest.permission#READ_CONTACTS} permission.
1071 */
1072 public @Nullable String getContactDisplayName() {
1073 return mContactDisplayName;
1074 }
1075
1076 /**
Tyler Gunn94f8f112018-12-17 09:56:11 -08001077 * Indicates whether the call is an incoming or outgoing call.
1078 * @return The call's direction.
1079 */
1080 public @CallDirection int getCallDirection() {
1081 return mCallDirection;
1082 }
1083
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001084 /**
1085 * Gets the verification status for the phone number of an incoming call as identified in
1086 * ATIS-1000082.
Tyler Gunn9c642492020-10-08 13:37:03 -07001087 * <p>
1088 * For incoming calls, the number verification status indicates whether the device was
1089 * able to verify the authenticity of the calling number using the STIR process outlined
1090 * in ATIS-1000082. {@link Connection#VERIFICATION_STATUS_NOT_VERIFIED} indicates that
1091 * the network was not able to use STIR to verify the caller's number (i.e. nothing is
1092 * known regarding the authenticity of the number.
1093 * {@link Connection#VERIFICATION_STATUS_PASSED} indicates that the network was able to
1094 * use STIR to verify the caller's number. This indicates that the network has a high
1095 * degree of confidence that the incoming call actually originated from the indicated
1096 * number. {@link Connection#VERIFICATION_STATUS_FAILED} indicates that the network's
1097 * STIR verification did not pass. This indicates that the incoming call may not
1098 * actually be from the indicated number. This could occur if, for example, the caller
1099 * is using an impersonated phone number.
1100 * <p>
1101 * A {@link CallScreeningService} can use this information to help determine if an
1102 * incoming call is potentially an unwanted call. A verification status of
1103 * {@link Connection#VERIFICATION_STATUS_FAILED} indicates that an incoming call may not
1104 * actually be from the number indicated on the call (i.e. impersonated number) and that it
1105 * should potentially be blocked. Likewise,
1106 * {@link Connection#VERIFICATION_STATUS_PASSED} can be used as a positive signal to
1107 * help clarify that the incoming call is originating from the indicated number and it
1108 * is less likely to be an undesirable call.
1109 * <p>
1110 * An {@link InCallService} can use this information to provide a visual indicator to the
1111 * user regarding the verification status of a call and to help identify calls from
1112 * potentially impersonated numbers.
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001113 * @return the verification status.
1114 */
1115 public @Connection.VerificationStatus int getCallerNumberVerificationStatus() {
1116 return mCallerNumberVerificationStatus;
1117 }
1118
Ihab Awade63fadb2014-07-09 21:52:04 -07001119 @Override
1120 public boolean equals(Object o) {
1121 if (o instanceof Details) {
1122 Details d = (Details) o;
1123 return
Grace Jiae04723f2022-01-26 16:24:48 +00001124 Objects.equals(mState, d.mState) &&
1125 Objects.equals(mHandle, d.mHandle) &&
1126 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
1127 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
1128 Objects.equals(mCallerDisplayNamePresentation,
1129 d.mCallerDisplayNamePresentation) &&
1130 Objects.equals(mAccountHandle, d.mAccountHandle) &&
1131 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
1132 Objects.equals(mCallProperties, d.mCallProperties) &&
1133 Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
1134 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
1135 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
1136 Objects.equals(mVideoState, d.mVideoState) &&
1137 Objects.equals(mStatusHints, d.mStatusHints) &&
1138 areBundlesEqual(mExtras, d.mExtras) &&
1139 areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
1140 Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis) &&
1141 Objects.equals(mContactDisplayName, d.mContactDisplayName) &&
1142 Objects.equals(mCallDirection, d.mCallDirection) &&
1143 Objects.equals(mCallerNumberVerificationStatus,
1144 d.mCallerNumberVerificationStatus);
Ihab Awade63fadb2014-07-09 21:52:04 -07001145 }
1146 return false;
1147 }
1148
1149 @Override
1150 public int hashCode() {
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001151 return Objects.hash(mState,
1152 mHandle,
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001153 mHandlePresentation,
1154 mCallerDisplayName,
1155 mCallerDisplayNamePresentation,
1156 mAccountHandle,
1157 mCallCapabilities,
1158 mCallProperties,
1159 mDisconnectCause,
1160 mConnectTimeMillis,
1161 mGatewayInfo,
1162 mVideoState,
1163 mStatusHints,
1164 mExtras,
1165 mIntentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -08001166 mCreationTimeMillis,
Hall Liuef98bf82020-01-09 15:22:44 -08001167 mContactDisplayName,
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001168 mCallDirection,
1169 mCallerNumberVerificationStatus);
Ihab Awade63fadb2014-07-09 21:52:04 -07001170 }
1171
1172 /** {@hide} */
1173 public Details(
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001174 @CallState int state,
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001175 String telecomCallId,
Ihab Awade63fadb2014-07-09 21:52:04 -07001176 Uri handle,
1177 int handlePresentation,
1178 String callerDisplayName,
1179 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -07001180 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -07001181 int capabilities,
Andrew Lee223ad142014-08-27 16:33:08 -07001182 int properties,
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001183 DisconnectCause disconnectCause,
Ihab Awade63fadb2014-07-09 21:52:04 -07001184 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -07001185 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -07001186 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -07001187 StatusHints statusHints,
Santos Cordon6b7f9552015-05-27 17:21:45 -07001188 Bundle extras,
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001189 Bundle intentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -08001190 long creationTimeMillis,
Hall Liuef98bf82020-01-09 15:22:44 -08001191 String contactDisplayName,
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001192 int callDirection,
Grace Jiae04723f2022-01-26 16:24:48 +00001193 int callerNumberVerificationStatus) {
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001194 mState = state;
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001195 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001196 mHandle = handle;
1197 mHandlePresentation = handlePresentation;
1198 mCallerDisplayName = callerDisplayName;
1199 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -07001200 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -07001201 mCallCapabilities = capabilities;
Andrew Lee223ad142014-08-27 16:33:08 -07001202 mCallProperties = properties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001203 mDisconnectCause = disconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -07001204 mConnectTimeMillis = connectTimeMillis;
1205 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -07001206 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -07001207 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -07001208 mExtras = extras;
Santos Cordon6b7f9552015-05-27 17:21:45 -07001209 mIntentExtras = intentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001210 mCreationTimeMillis = creationTimeMillis;
Hall Liuef98bf82020-01-09 15:22:44 -08001211 mContactDisplayName = contactDisplayName;
Tyler Gunn94f8f112018-12-17 09:56:11 -08001212 mCallDirection = callDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001213 mCallerNumberVerificationStatus = callerNumberVerificationStatus;
Ihab Awade63fadb2014-07-09 21:52:04 -07001214 }
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001215
1216 /** {@hide} */
1217 public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
1218 return new Details(
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001219 parcelableCall.getState(),
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001220 parcelableCall.getId(),
1221 parcelableCall.getHandle(),
1222 parcelableCall.getHandlePresentation(),
1223 parcelableCall.getCallerDisplayName(),
1224 parcelableCall.getCallerDisplayNamePresentation(),
1225 parcelableCall.getAccountHandle(),
1226 parcelableCall.getCapabilities(),
1227 parcelableCall.getProperties(),
1228 parcelableCall.getDisconnectCause(),
1229 parcelableCall.getConnectTimeMillis(),
1230 parcelableCall.getGatewayInfo(),
1231 parcelableCall.getVideoState(),
1232 parcelableCall.getStatusHints(),
1233 parcelableCall.getExtras(),
Tyler Gunnc0bf6de2017-03-17 11:27:09 -07001234 parcelableCall.getIntentExtras(),
Tyler Gunnd081f042018-12-04 12:56:45 -08001235 parcelableCall.getCreationTimeMillis(),
Hall Liuef98bf82020-01-09 15:22:44 -08001236 parcelableCall.getContactDisplayName(),
Tyler Gunnd57d76c2019-09-24 14:53:23 -07001237 parcelableCall.getCallDirection(),
Grace Jiae04723f2022-01-26 16:24:48 +00001238 parcelableCall.getCallerNumberVerificationStatus());
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001239 }
Santos Cordon3c20d632016-02-25 16:12:35 -08001240
1241 @Override
1242 public String toString() {
1243 StringBuilder sb = new StringBuilder();
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001244 sb.append("[id: ");
1245 sb.append(mTelecomCallId);
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001246 sb.append(", state: ");
1247 sb.append(Call.stateToString(mState));
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001248 sb.append(", pa: ");
Santos Cordon3c20d632016-02-25 16:12:35 -08001249 sb.append(mAccountHandle);
1250 sb.append(", hdl: ");
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001251 sb.append(Log.piiHandle(mHandle));
1252 sb.append(", hdlPres: ");
1253 sb.append(mHandlePresentation);
1254 sb.append(", videoState: ");
1255 sb.append(VideoProfile.videoStateToString(mVideoState));
Santos Cordon3c20d632016-02-25 16:12:35 -08001256 sb.append(", caps: ");
1257 sb.append(capabilitiesToString(mCallCapabilities));
1258 sb.append(", props: ");
Tyler Gunn720c6642016-03-22 09:02:47 -07001259 sb.append(propertiesToString(mCallProperties));
Santos Cordon3c20d632016-02-25 16:12:35 -08001260 sb.append("]");
1261 return sb.toString();
1262 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001263 }
1264
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001265 /**
1266 * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
1267 * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
1268 * implementation.
1269 * <p>
1270 * You can handle these callbacks by extending the {@link Callback} class and overriding the
1271 * callbacks that your {@link InCallService} is interested in. The callback methods include the
1272 * {@link Call} for which the callback applies, allowing reuse of a single instance of your
1273 * {@link Callback} implementation, if desired.
1274 * <p>
1275 * Use {@link Call#registerCallback(Callback)} to register your callback(s). Ensure
1276 * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
1277 * (typically in {@link InCallService#onCallRemoved(Call)}).
1278 * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
1279 * reach your implementation of {@link Callback}, so it is important to register your callback
1280 * as soon as your {@link InCallService} is notified of a new call via
1281 * {@link InCallService#onCallAdded(Call)}.
1282 */
Andrew Leeda80c872015-04-15 14:09:50 -07001283 public static abstract class Callback {
Ihab Awade63fadb2014-07-09 21:52:04 -07001284 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001285 * @hide
1286 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001287 @IntDef(prefix = { "HANDOVER_" },
1288 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
Tyler Gunn5c60d712018-03-16 09:53:44 -07001289 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
Tyler Gunn9d127732018-03-02 15:45:51 -08001290 HANDOVER_FAILURE_UNKNOWN})
Sanket Padawea8eddd42017-11-03 11:07:35 -07001291 @Retention(RetentionPolicy.SOURCE)
1292 public @interface HandoverFailureErrors {}
1293
1294 /**
1295 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
Tyler Gunn9d127732018-03-02 15:45:51 -08001296 * to handover the call to rejects the handover request.
1297 * <p>
1298 * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
1299 * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
1300 * {@code null} {@link Connection} from
1301 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1302 * ConnectionRequest)}.
1303 * <p>
1304 * For more information on call handovers, see
1305 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001306 */
1307 public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
1308
1309 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001310 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1311 * is initiated but the source or destination app does not support handover.
1312 * <p>
1313 * Will be returned when a handover is requested via
1314 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
1315 * {@link PhoneAccountHandle} does not declare
1316 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}. May also be returned when a handover is
1317 * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
1318 * {@link Details#getAccountHandle()}) does not declare
1319 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
1320 * <p>
1321 * For more information on call handovers, see
1322 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001323 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001324 public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001325
1326 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001327 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
1328 * user rejects the handover request.
1329 * <p>
1330 * For more information on call handovers, see
1331 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001332 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001333 public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001334
Sanket Padawe85291f62017-12-01 13:59:27 -08001335 /**
1336 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
1337 * is ongoing emergency call.
Tyler Gunn9d127732018-03-02 15:45:51 -08001338 * <p>
1339 * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
1340 * called on an emergency call, or if any other call is an emergency call.
1341 * <p>
1342 * Handovers are not permitted while there are ongoing emergency calls.
1343 * <p>
1344 * For more information on call handovers, see
1345 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawe85291f62017-12-01 13:59:27 -08001346 */
Tyler Gunn5c60d712018-03-16 09:53:44 -07001347 public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
Sanket Padawe85291f62017-12-01 13:59:27 -08001348
Tyler Gunn9d127732018-03-02 15:45:51 -08001349 /**
1350 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1351 * fails for an unknown reason.
1352 * <p>
1353 * For more information on call handovers, see
1354 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
1355 */
1356 public static final int HANDOVER_FAILURE_UNKNOWN = 5;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001357
1358 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001359 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
1360 *
Ihab Awade63fadb2014-07-09 21:52:04 -07001361 * @param call The {@code Call} invoking this method.
1362 * @param state The new state of the {@code Call}.
1363 */
Tyler Gunn1e406ca2021-03-18 16:47:14 -07001364 public void onStateChanged(Call call, @CallState int state) {}
Ihab Awade63fadb2014-07-09 21:52:04 -07001365
1366 /**
1367 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
1368 *
1369 * @param call The {@code Call} invoking this method.
1370 * @param parent The new parent of the {@code Call}.
1371 */
1372 public void onParentChanged(Call call, Call parent) {}
1373
1374 /**
1375 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
1376 *
1377 * @param call The {@code Call} invoking this method.
1378 * @param children The new children of the {@code Call}.
1379 */
1380 public void onChildrenChanged(Call call, List<Call> children) {}
1381
1382 /**
1383 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
1384 *
1385 * @param call The {@code Call} invoking this method.
1386 * @param details A {@code Details} object describing the {@code Call}.
1387 */
1388 public void onDetailsChanged(Call call, Details details) {}
1389
1390 /**
1391 * Invoked when the text messages that can be used as responses to the incoming
1392 * {@code Call} are loaded from the relevant database.
1393 * See {@link #getCannedTextResponses()}.
1394 *
1395 * @param call The {@code Call} invoking this method.
1396 * @param cannedTextResponses The text messages useable as responses.
1397 */
1398 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
1399
1400 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001401 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
1402 * character. This causes the post-dial signals to stop pending user confirmation. An
1403 * implementation should present this choice to the user and invoke
1404 * {@link #postDialContinue(boolean)} when the user makes the choice.
1405 *
1406 * @param call The {@code Call} invoking this method.
1407 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
1408 */
1409 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
1410
1411 /**
Andrew Lee50aca232014-07-22 16:41:54 -07001412 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -07001413 *
1414 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -07001415 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001416 */
Andrew Lee50aca232014-07-22 16:41:54 -07001417 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -07001418
1419 /**
1420 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
1421 * up their UI for the {@code Call} in response to state transitions. Specifically,
1422 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
1423 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
1424 * clients should wait for this method to be invoked.
1425 *
1426 * @param call The {@code Call} being destroyed.
1427 */
1428 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001429
1430 /**
1431 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
1432 * conferenced.
1433 *
1434 * @param call The {@code Call} being updated.
1435 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
1436 * conferenced.
1437 */
1438 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001439
1440 /**
Tyler Gunn5567d742019-10-31 13:04:37 -07001441 * Invoked when a {@link Call} receives an event from its associated {@link Connection} or
1442 * {@link Conference}.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001443 * <p>
1444 * Where possible, the Call should make an attempt to handle {@link Connection} events which
1445 * are part of the {@code android.telecom.*} namespace. The Call should ignore any events
1446 * it does not wish to handle. Unexpected events should be handled gracefully, as it is
1447 * possible that a {@link ConnectionService} has defined its own Connection events which a
1448 * Call is not aware of.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001449 * <p>
Tyler Gunn5567d742019-10-31 13:04:37 -07001450 * See {@link Connection#sendConnectionEvent(String, Bundle)},
1451 * {@link Conference#sendConferenceEvent(String, Bundle)}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001452 *
1453 * @param call The {@code Call} receiving the event.
1454 * @param event The event.
1455 * @param extras Extras associated with the connection event.
1456 */
1457 public void onConnectionEvent(Call call, String event, Bundle extras) {}
Hall Liu95d55872017-01-25 17:12:49 -08001458
1459 /**
1460 * Invoked when the RTT mode changes for this call.
1461 * @param call The call whose RTT mode has changed.
1462 * @param mode the new RTT mode, one of
1463 * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
1464 * or {@link RttCall#RTT_MODE_VCO}
1465 */
1466 public void onRttModeChanged(Call call, int mode) {}
1467
1468 /**
1469 * Invoked when the call's RTT status changes, either from off to on or from on to off.
1470 * @param call The call whose RTT status has changed.
1471 * @param enabled whether RTT is now enabled or disabled
1472 * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
1473 * on, null otherwise.
1474 */
1475 public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
1476
1477 /**
1478 * Invoked when the remote end of the connection has requested that an RTT communication
1479 * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
1480 * with the same ID that this method is invoked with.
1481 * @param call The call which the RTT request was placed on
1482 * @param id The ID of the request.
1483 */
1484 public void onRttRequest(Call call, int id) {}
Hall Liu57006aa2017-02-06 10:49:48 -08001485
1486 /**
1487 * Invoked when the RTT session failed to initiate for some reason, including rejection
1488 * by the remote party.
1489 * @param call The call which the RTT initiation failure occurred on.
1490 * @param reason One of the status codes defined in
1491 * {@link android.telecom.Connection.RttModifyStatus}, with the exception of
1492 * {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
1493 */
1494 public void onRttInitiationFailure(Call call, int reason) {}
Sanket Padawea8eddd42017-11-03 11:07:35 -07001495
1496 /**
1497 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1498 * has completed successfully.
Tyler Gunn9d127732018-03-02 15:45:51 -08001499 * <p>
1500 * For a full discussion of the handover process and the APIs involved, see
1501 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1502 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001503 * @param call The call which had initiated handover.
1504 */
1505 public void onHandoverComplete(Call call) {}
1506
1507 /**
1508 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1509 * has failed.
Tyler Gunn9d127732018-03-02 15:45:51 -08001510 * <p>
1511 * For a full discussion of the handover process and the APIs involved, see
1512 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1513 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001514 * @param call The call which had initiated handover.
Tyler Gunn9d127732018-03-02 15:45:51 -08001515 * @param failureReason Error reason for failure.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001516 */
1517 public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
Hall Liu95d55872017-01-25 17:12:49 -08001518 }
1519
1520 /**
1521 * A class that holds the state that describes the state of the RTT channel to the remote
1522 * party, if it is active.
1523 */
1524 public static final class RttCall {
Hall Liu07094df2017-02-28 15:17:44 -08001525 /** @hide */
Hall Liu95d55872017-01-25 17:12:49 -08001526 @Retention(RetentionPolicy.SOURCE)
1527 @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
1528 public @interface RttAudioMode {}
1529
1530 /**
1531 * For metrics use. Default value in the proto.
1532 * @hide
1533 */
1534 public static final int RTT_MODE_INVALID = 0;
1535
1536 /**
1537 * Indicates that there should be a bidirectional audio stream between the two parties
1538 * on the call.
1539 */
1540 public static final int RTT_MODE_FULL = 1;
1541
1542 /**
1543 * Indicates that the local user should be able to hear the audio stream from the remote
1544 * user, but not vice versa. Equivalent to muting the microphone.
1545 */
1546 public static final int RTT_MODE_HCO = 2;
1547
1548 /**
1549 * Indicates that the remote user should be able to hear the audio stream from the local
1550 * user, but not vice versa. Equivalent to setting the volume to zero.
1551 */
1552 public static final int RTT_MODE_VCO = 3;
1553
1554 private static final int READ_BUFFER_SIZE = 1000;
1555
1556 private InputStreamReader mReceiveStream;
1557 private OutputStreamWriter mTransmitStream;
1558 private int mRttMode;
1559 private final InCallAdapter mInCallAdapter;
Hall Liu57006aa2017-02-06 10:49:48 -08001560 private final String mTelecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001561 private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
1562
1563 /**
1564 * @hide
1565 */
Hall Liu57006aa2017-02-06 10:49:48 -08001566 public RttCall(String telecomCallId, InputStreamReader receiveStream,
1567 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
1568 mTelecomCallId = telecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001569 mReceiveStream = receiveStream;
1570 mTransmitStream = transmitStream;
1571 mRttMode = mode;
1572 mInCallAdapter = inCallAdapter;
1573 }
1574
1575 /**
1576 * Returns the current RTT audio mode.
1577 * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
1578 * {@link #RTT_MODE_HCO}.
1579 */
1580 public int getRttAudioMode() {
1581 return mRttMode;
1582 }
1583
1584 /**
1585 * Sets the RTT audio mode. The requested mode change will be communicated through
1586 * {@link Callback#onRttModeChanged(Call, int)}.
1587 * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
1588 * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
1589 */
1590 public void setRttMode(@RttAudioMode int mode) {
Hall Liu57006aa2017-02-06 10:49:48 -08001591 mInCallAdapter.setRttMode(mTelecomCallId, mode);
Hall Liu95d55872017-01-25 17:12:49 -08001592 }
1593
1594 /**
1595 * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
Hall Liudc46c852020-10-29 16:15:33 -07001596 * RTT transmits text in real-time, this method should be called once for each user action.
1597 * For example, when the user enters text as discrete characters using the keyboard, this
1598 * method should be called once for each character. However, if the user enters text by
1599 * pasting or autocomplete, the entire contents of the pasted or autocompleted text should
1600 * be sent in one call to this method.
Hall Liu95d55872017-01-25 17:12:49 -08001601 *
1602 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1603 * lead to interleaved text.
1604 * @param input The message to send to the remote user.
1605 */
1606 public void write(String input) throws IOException {
1607 mTransmitStream.write(input);
1608 mTransmitStream.flush();
1609 }
1610
1611 /**
1612 * Reads a string from the remote user, blocking if there is no data available. Returns
1613 * {@code null} if the RTT conversation has been terminated and there is no further data
1614 * to read.
1615 *
1616 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1617 * lead to interleaved text.
1618 * @return A string containing text sent by the remote user, or {@code null} if the
1619 * conversation has been terminated or if there was an error while reading.
1620 */
Hall Liub1c8a772017-07-17 17:04:41 -07001621 public String read() {
1622 try {
1623 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1624 if (numRead < 0) {
1625 return null;
1626 }
1627 return new String(mReadBuffer, 0, numRead);
1628 } catch (IOException e) {
1629 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
Jeff Sharkey90396362017-06-12 16:26:53 -06001630 return null;
Hall Liuffa4a812017-03-02 16:11:00 -08001631 }
Hall Liuffa4a812017-03-02 16:11:00 -08001632 }
1633
1634 /**
1635 * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
1636 * be read.
1637 * @return A string containing text entered by the user, or {@code null} if the user has
1638 * not entered any new text yet.
1639 */
1640 public String readImmediately() throws IOException {
1641 if (mReceiveStream.ready()) {
Hall Liub1c8a772017-07-17 17:04:41 -07001642 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1643 if (numRead < 0) {
1644 return null;
1645 }
1646 return new String(mReadBuffer, 0, numRead);
Hall Liuffa4a812017-03-02 16:11:00 -08001647 } else {
Hall Liu95d55872017-01-25 17:12:49 -08001648 return null;
1649 }
1650 }
Hall Liue9041242018-02-09 16:40:03 -08001651
1652 /**
1653 * Closes the underlying file descriptors
1654 * @hide
1655 */
1656 public void close() {
1657 try {
1658 mReceiveStream.close();
1659 } catch (IOException e) {
1660 // ignore
1661 }
1662 try {
1663 mTransmitStream.close();
1664 } catch (IOException e) {
1665 // ignore
1666 }
1667 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001668 }
1669
Andrew Leeda80c872015-04-15 14:09:50 -07001670 /**
1671 * @deprecated Use {@code Call.Callback} instead.
1672 * @hide
1673 */
1674 @Deprecated
1675 @SystemApi
1676 public static abstract class Listener extends Callback { }
1677
Ihab Awade63fadb2014-07-09 21:52:04 -07001678 private final Phone mPhone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001679 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001680 private final InCallAdapter mInCallAdapter;
Santos Cordon823fd3c2014-08-07 18:35:18 -07001681 private final List<String> mChildrenIds = new ArrayList<>();
Ihab Awade63fadb2014-07-09 21:52:04 -07001682 private final List<Call> mChildren = new ArrayList<>();
1683 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Andrew Lee011728f2015-04-23 15:47:06 -07001684 private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001685 private final List<Call> mConferenceableCalls = new ArrayList<>();
1686 private final List<Call> mUnmodifiableConferenceableCalls =
1687 Collections.unmodifiableList(mConferenceableCalls);
1688
Santos Cordon823fd3c2014-08-07 18:35:18 -07001689 private boolean mChildrenCached;
1690 private String mParentId = null;
Hall Liuef98bf82020-01-09 15:22:44 -08001691 private String mActiveGenericConferenceChild = null;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001692 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -07001693 private List<String> mCannedTextResponses = null;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001694 private String mCallingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001695 private int mTargetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07001696 private String mRemainingPostDialSequence;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001697 private VideoCallImpl mVideoCallImpl;
Hall Liu95d55872017-01-25 17:12:49 -08001698 private RttCall mRttCall;
Ihab Awade63fadb2014-07-09 21:52:04 -07001699 private Details mDetails;
Tyler Gunndee56a82016-03-23 16:06:34 -07001700 private Bundle mExtras;
Ihab Awade63fadb2014-07-09 21:52:04 -07001701
1702 /**
1703 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
1704 *
1705 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
1706 * remaining or this {@code Call} is not in a post-dial state.
1707 */
1708 public String getRemainingPostDialSequence() {
1709 return mRemainingPostDialSequence;
1710 }
1711
1712 /**
1713 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001714 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -07001715 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001716 public void answer(@VideoProfile.VideoState int videoState) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001717 mInCallAdapter.answerCall(mTelecomCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -07001718 }
1719
1720 /**
Pooja Jaind34698d2017-12-28 14:15:31 +05301721 * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
1722 *
1723 * @param address The address to which the call will be deflected.
1724 */
1725 public void deflect(Uri address) {
1726 mInCallAdapter.deflectCall(mTelecomCallId, address);
1727 }
1728
1729 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001730 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
1731 *
1732 * @param rejectWithMessage Whether to reject with a text message.
1733 * @param textMessage An optional text message with which to respond.
1734 */
1735 public void reject(boolean rejectWithMessage, String textMessage) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001736 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
Ihab Awade63fadb2014-07-09 21:52:04 -07001737 }
1738
1739 /**
Tyler Gunnfacfdee2020-01-23 13:10:37 -08001740 * Instructs the {@link ConnectionService} providing this {@link #STATE_RINGING} call that the
1741 * user has chosen to reject the call and has indicated a reason why the call is being rejected.
1742 *
1743 * @param rejectReason the reason the call is being rejected.
1744 */
1745 public void reject(@RejectReason int rejectReason) {
1746 mInCallAdapter.rejectCall(mTelecomCallId, rejectReason);
1747 }
1748
1749 /**
Ravi Palurif4b38e72020-02-05 12:35:41 +05301750 * Instructs this {@code Call} to be transferred to another number.
1751 *
1752 * @param targetNumber The address to which the call will be transferred.
Tyler Gunn460360d2020-07-29 10:21:45 -07001753 * @param isConfirmationRequired if {@code true} it will initiate a confirmed transfer,
1754 * if {@code false}, it will initiate an unconfirmed transfer.
Ravi Palurif4b38e72020-02-05 12:35:41 +05301755 *
1756 * @hide
1757 */
1758 public void transfer(@NonNull Uri targetNumber, boolean isConfirmationRequired) {
1759 mInCallAdapter.transferCall(mTelecomCallId, targetNumber, isConfirmationRequired);
1760 }
1761
1762 /**
1763 * Instructs this {@code Call} to be transferred to another ongoing call.
1764 * This will initiate CONSULTATIVE transfer.
1765 * @param toCall The other ongoing {@code Call} to which this call will be transferred.
1766 *
1767 * @hide
1768 */
1769 public void transfer(@NonNull android.telecom.Call toCall) {
1770 mInCallAdapter.transferCall(mTelecomCallId, toCall.mTelecomCallId);
1771 }
1772
1773 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001774 * Instructs this {@code Call} to disconnect.
1775 */
1776 public void disconnect() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001777 mInCallAdapter.disconnectCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001778 }
1779
1780 /**
1781 * Instructs this {@code Call} to go on hold.
1782 */
1783 public void hold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001784 mInCallAdapter.holdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001785 }
1786
1787 /**
1788 * Instructs this {@link #STATE_HOLDING} call to release from hold.
1789 */
1790 public void unhold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001791 mInCallAdapter.unholdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001792 }
1793
1794 /**
Hall Liu6dfa2492019-10-01 17:20:39 -07001795 * Instructs Telecom to put the call into the background audio processing state.
Tyler Gunn460b7d42020-05-15 10:19:32 -07001796 * <p>
Hall Liu6dfa2492019-10-01 17:20:39 -07001797 * This method can be called either when the call is in {@link #STATE_RINGING} or
1798 * {@link #STATE_ACTIVE}. After Telecom acknowledges the request by setting the call's state to
1799 * {@link #STATE_AUDIO_PROCESSING}, your app may setup the audio paths with the audio stack in
1800 * order to capture and play audio on the call stream.
Tyler Gunn460b7d42020-05-15 10:19:32 -07001801 * <p>
Hall Liu6dfa2492019-10-01 17:20:39 -07001802 * This method can only be called by the default dialer app.
Tyler Gunn460b7d42020-05-15 10:19:32 -07001803 * <p>
1804 * Apps built with SDK version {@link android.os.Build.VERSION_CODES#R} or later which are using
1805 * the microphone as part of audio processing should specify the foreground service type using
1806 * the attribute {@link android.R.attr#foregroundServiceType} in the {@link InCallService}
1807 * service element of the app's manifest file.
1808 * The {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} attribute should be specified.
1809 * @see <a href="https://developer.android.com/preview/privacy/foreground-service-types">
1810 * the Android Developer Site</a> for more information.
Hall Liu6dfa2492019-10-01 17:20:39 -07001811 * @hide
1812 */
1813 @SystemApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001814 public void enterBackgroundAudioProcessing() {
1815 if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
1816 throw new IllegalStateException("Call must be active or ringing");
1817 }
1818 mInCallAdapter.enterBackgroundAudioProcessing(mTelecomCallId);
1819 }
1820
1821 /**
1822 * Instructs Telecom to come out of the background audio processing state requested by
1823 * {@link #enterBackgroundAudioProcessing()} or from the call screening service.
1824 *
1825 * This method can only be called when the call is in {@link #STATE_AUDIO_PROCESSING}.
1826 *
1827 * @param shouldRing If true, Telecom will put the call into the
1828 * {@link #STATE_SIMULATED_RINGING} state and notify other apps that there is
1829 * a ringing call. Otherwise, the call will go into {@link #STATE_ACTIVE}
1830 * immediately.
1831 * @hide
1832 */
1833 @SystemApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001834 public void exitBackgroundAudioProcessing(boolean shouldRing) {
1835 if (mState != STATE_AUDIO_PROCESSING) {
1836 throw new IllegalStateException("Call must in the audio processing state");
1837 }
1838 mInCallAdapter.exitBackgroundAudioProcessing(mTelecomCallId, shouldRing);
1839 }
1840
1841 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001842 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
1843 *
1844 * Any other currently playing DTMF tone in the specified call is immediately stopped.
1845 *
1846 * @param digit A character representing the DTMF digit for which to play the tone. This
1847 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
1848 */
1849 public void playDtmfTone(char digit) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001850 mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
Ihab Awade63fadb2014-07-09 21:52:04 -07001851 }
1852
1853 /**
1854 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
1855 * currently playing.
1856 *
1857 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
1858 * currently playing, this method will do nothing.
1859 */
1860 public void stopDtmfTone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001861 mInCallAdapter.stopDtmfTone(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001862 }
1863
1864 /**
1865 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
1866 *
1867 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
1868 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -07001869 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001870 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -07001871 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
1872 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001873 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
Andrew Leeda80c872015-04-15 14:09:50 -07001874 * {@code Call} will pause playing the tones and notify callbacks via
1875 * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
Ihab Awade63fadb2014-07-09 21:52:04 -07001876 * should display to the user an indication of this state and an affordance to continue
1877 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
1878 * app should invoke the {@link #postDialContinue(boolean)} method.
1879 *
1880 * @param proceed Whether or not to continue with the post-dial sequence.
1881 */
1882 public void postDialContinue(boolean proceed) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001883 mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
Ihab Awade63fadb2014-07-09 21:52:04 -07001884 }
1885
1886 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -07001887 * Notifies this {@code Call} that an account has been selected and to proceed with placing
Nancy Chen36c62f32014-10-21 18:36:39 -07001888 * an outgoing call. Optionally sets this account as the default account.
Nancy Chen5da0fd52014-07-08 14:16:17 -07001889 */
Nancy Chen36c62f32014-10-21 18:36:39 -07001890 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
1891 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
Nancy Chen5da0fd52014-07-08 14:16:17 -07001892
1893 }
1894
1895 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001896 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001897 *
1898 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -07001899 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001900 public void conference(Call callToConferenceWith) {
1901 if (callToConferenceWith != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001902 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001903 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001904 }
1905
1906 /**
1907 * Instructs this {@code Call} to split from any conference call with which it may be
1908 * connected.
1909 */
1910 public void splitFromConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001911 mInCallAdapter.splitFromConference(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001912 }
1913
1914 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001915 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001916 */
1917 public void mergeConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001918 mInCallAdapter.mergeConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001919 }
1920
1921 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001922 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001923 */
1924 public void swapConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001925 mInCallAdapter.swapConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001926 }
1927
1928 /**
Ravi Paluri404babb2020-01-23 19:02:44 +05301929 * Pulls participants to existing call by forming a conference call.
1930 * See {@link Details#CAPABILITY_ADD_PARTICIPANT}.
1931 *
1932 * @param participants participants to be pulled to existing call.
1933 */
1934 public void addConferenceParticipants(@NonNull List<Uri> participants) {
1935 mInCallAdapter.addConferenceParticipants(mTelecomCallId, participants);
1936 }
1937
1938 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001939 * Initiates a request to the {@link ConnectionService} to pull an external call to the local
Grace Jiae04723f2022-01-26 16:24:48 +00001940 * device.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001941 * <p>
1942 * Calls to this method are ignored if the call does not have the
1943 * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
1944 * <p>
1945 * An {@link InCallService} will only see calls which support this method if it has the
1946 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
1947 * in its manifest.
1948 */
Grace Jiae04723f2022-01-26 16:24:48 +00001949 public void pullExternalCall() {
1950 // If this isn't an external call, ignore the request.
1951 if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
1952 return;
1953 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001954
Grace Jiae04723f2022-01-26 16:24:48 +00001955 mInCallAdapter.pullExternalCall(mTelecomCallId);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001956 }
1957
1958 /**
1959 * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
1960 * the {@link ConnectionService}.
1961 * <p>
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001962 * Call events are used to communicate point in time information from an {@link InCallService}
1963 * to a {@link ConnectionService}. A {@link ConnectionService} implementation could define
1964 * events which enable the {@link InCallService}, for example, toggle a unique feature of the
1965 * {@link ConnectionService}.
1966 * <p>
1967 * A {@link ConnectionService} can communicate to the {@link InCallService} using
1968 * {@link Connection#sendConnectionEvent(String, Bundle)}.
1969 * <p>
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001970 * Events are exposed to {@link ConnectionService} implementations via
1971 * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
1972 * <p>
1973 * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001974 * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
1975 * ignore some events altogether.
1976 * <p>
1977 * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
1978 * conflicts between {@link InCallService} implementations. Further, {@link InCallService}
1979 * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
1980 * they define their own event types in this namespace. When defining a custom event type,
1981 * ensure the contents of the extras {@link Bundle} is clearly defined. Extra keys for this
1982 * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
1983 * <p>
1984 * When defining events and the associated extras, it is important to keep their behavior
1985 * consistent when the associated {@link InCallService} is updated. Support for deprecated
1986 * events/extras should me maintained to ensure backwards compatibility with older
1987 * {@link ConnectionService} implementations which were built to support the older behavior.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001988 *
1989 * @param event The connection event.
1990 * @param extras Bundle containing extra information associated with the event.
1991 */
1992 public void sendCallEvent(String event, Bundle extras) {
Sanket Padawef6a9e5b2018-01-05 14:26:16 -08001993 mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001994 }
1995
1996 /**
Hall Liu95d55872017-01-25 17:12:49 -08001997 * Sends an RTT upgrade request to the remote end of the connection. Success is not
1998 * guaranteed, and notification of success will be via the
1999 * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
2000 */
2001 public void sendRttRequest() {
Hall Liu57006aa2017-02-06 10:49:48 -08002002 mInCallAdapter.sendRttRequest(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08002003 }
2004
2005 /**
2006 * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
2007 * callback.
2008 * The ID used here should be the same as the ID that was received via the callback.
2009 * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
2010 * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
2011 */
2012 public void respondToRttRequest(int id, boolean accept) {
Hall Liu57006aa2017-02-06 10:49:48 -08002013 mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
Hall Liu95d55872017-01-25 17:12:49 -08002014 }
2015
2016 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07002017 * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
2018 * by {@code toHandle}. The videoState specified indicates the desired video state after the
2019 * handover.
2020 * <p>
Tyler Gunn9d127732018-03-02 15:45:51 -08002021 * A call handover is the process where an ongoing call is transferred from one app (i.e.
2022 * {@link ConnectionService} to another app. The user could, for example, choose to continue a
2023 * mobile network call in a video calling app. The mobile network call via the Telephony stack
2024 * is referred to as the source of the handover, and the video calling app is referred to as the
2025 * destination.
2026 * <p>
2027 * When considering a handover scenario the device this method is called on is considered the
2028 * <em>initiating</em> device (since the user initiates the handover from this device), and the
2029 * other device is considered the <em>receiving</em> device.
2030 * <p>
2031 * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
2032 * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
2033 * and invoke
2034 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
2035 * ConnectionRequest)} to inform the destination app that a request has been made to handover a
2036 * call to it. The app returns an instance of {@link Connection} to represent the handover call
2037 * At this point the app should display UI to indicate to the user that a call
2038 * handover is in process.
2039 * <p>
2040 * The destination app is responsible for communicating the handover request from the
2041 * <em>initiating</em> device to the <em>receiving</em> device.
2042 * <p>
2043 * When the app on the <em>receiving</em> device receives the handover request, it calls
2044 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
2045 * process from the <em>initiating</em> device to the <em>receiving</em> device. At this point
2046 * the destination app on the <em>receiving</em> device should show UI to allow the user to
2047 * choose whether they want to continue their call in the destination app.
2048 * <p>
2049 * When the destination app on the <em>receiving</em> device calls
2050 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
2051 * {@link ConnectionService} and call
2052 * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
2053 * ConnectionRequest)} to inform it of the handover request. The app returns an instance of
2054 * {@link Connection} to represent the handover call.
2055 * <p>
2056 * If the user of the <em>receiving</em> device accepts the handover, the app calls
2057 * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
2058 * original call. If the user rejects the handover, the app calls
2059 * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
2060 * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
2061 * <p>
2062 * Telecom will only allow handovers from {@link PhoneAccount}s which declare
2063 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}. Similarly, the {@link PhoneAccount}
2064 * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
2065 * <p>
2066 * Errors in the handover process are reported to the {@link InCallService} via
2067 * {@link Callback#onHandoverFailed(Call, int)}. Errors in the handover process are reported to
2068 * the involved {@link ConnectionService}s via
2069 * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07002070 *
2071 * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
2072 * this call to.
Tyler Gunn9d127732018-03-02 15:45:51 -08002073 * @param videoState Indicates the video state desired after the handover (see the
2074 * {@code STATE_*} constants defined in {@link VideoProfile}).
Sanket Padawea8eddd42017-11-03 11:07:35 -07002075 * @param extras Bundle containing extra information to be passed to the
2076 * {@link ConnectionService}
2077 */
Tyler Gunn9d127732018-03-02 15:45:51 -08002078 public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
2079 Bundle extras) {
Sanket Padawea8eddd42017-11-03 11:07:35 -07002080 mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
2081 }
2082
2083 /**
Hall Liu95d55872017-01-25 17:12:49 -08002084 * Terminate the RTT session on this call. The resulting state change will be notified via
2085 * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
2086 */
2087 public void stopRtt() {
Hall Liu57006aa2017-02-06 10:49:48 -08002088 mInCallAdapter.stopRtt(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08002089 }
2090
2091 /**
Tyler Gunndee56a82016-03-23 16:06:34 -07002092 * Adds some extras to this {@link Call}. Existing keys are replaced and new ones are
2093 * added.
2094 * <p>
2095 * No assumptions should be made as to how an In-Call UI or service will handle these
2096 * extras. Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
2097 *
2098 * @param extras The extras to add.
2099 */
2100 public final void putExtras(Bundle extras) {
2101 if (extras == null) {
2102 return;
2103 }
2104
2105 if (mExtras == null) {
2106 mExtras = new Bundle();
2107 }
2108 mExtras.putAll(extras);
2109 mInCallAdapter.putExtras(mTelecomCallId, extras);
2110 }
2111
2112 /**
2113 * Adds a boolean extra to this {@link Call}.
2114 *
2115 * @param key The extra key.
2116 * @param value The value.
2117 * @hide
2118 */
2119 public final void putExtra(String key, boolean value) {
2120 if (mExtras == null) {
2121 mExtras = new Bundle();
2122 }
2123 mExtras.putBoolean(key, value);
2124 mInCallAdapter.putExtra(mTelecomCallId, key, value);
2125 }
2126
2127 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002128 * Adds an integer extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07002129 *
2130 * @param key The extra key.
2131 * @param value The value.
2132 * @hide
2133 */
2134 public final void putExtra(String key, int value) {
2135 if (mExtras == null) {
2136 mExtras = new Bundle();
2137 }
2138 mExtras.putInt(key, value);
2139 mInCallAdapter.putExtra(mTelecomCallId, key, value);
2140 }
2141
2142 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002143 * Adds a string extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07002144 *
2145 * @param key The extra key.
2146 * @param value The value.
2147 * @hide
2148 */
2149 public final void putExtra(String key, String value) {
2150 if (mExtras == null) {
2151 mExtras = new Bundle();
2152 }
2153 mExtras.putString(key, value);
2154 mInCallAdapter.putExtra(mTelecomCallId, key, value);
2155 }
2156
2157 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002158 * Removes extras from this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07002159 *
2160 * @param keys The keys of the extras to remove.
2161 */
2162 public final void removeExtras(List<String> keys) {
2163 if (mExtras != null) {
2164 for (String key : keys) {
2165 mExtras.remove(key);
2166 }
2167 if (mExtras.size() == 0) {
2168 mExtras = null;
2169 }
2170 }
2171 mInCallAdapter.removeExtras(mTelecomCallId, keys);
2172 }
2173
2174 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07002175 * Removes extras from this {@link Call}.
2176 *
2177 * @param keys The keys of the extras to remove.
2178 */
2179 public final void removeExtras(String ... keys) {
2180 removeExtras(Arrays.asList(keys));
2181 }
2182
2183 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002184 * Obtains the parent of this {@code Call} in a conference, if any.
2185 *
2186 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
2187 * child of any conference {@code Call}s.
2188 */
2189 public Call getParent() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002190 if (mParentId != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002191 return mPhone.internalGetCallByTelecomId(mParentId);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002192 }
2193 return null;
Ihab Awade63fadb2014-07-09 21:52:04 -07002194 }
2195
2196 /**
2197 * Obtains the children of this conference {@code Call}, if any.
2198 *
2199 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
2200 * {@code List} otherwise.
2201 */
2202 public List<Call> getChildren() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002203 if (!mChildrenCached) {
2204 mChildrenCached = true;
2205 mChildren.clear();
2206
2207 for(String id : mChildrenIds) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002208 Call call = mPhone.internalGetCallByTelecomId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -07002209 if (call == null) {
2210 // At least one child was still not found, so do not save true for "cached"
2211 mChildrenCached = false;
2212 } else {
2213 mChildren.add(call);
2214 }
2215 }
2216 }
2217
Ihab Awade63fadb2014-07-09 21:52:04 -07002218 return mUnmodifiableChildren;
2219 }
2220
2221 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002222 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
2223 *
2224 * @return The list of conferenceable {@code Call}s.
2225 */
2226 public List<Call> getConferenceableCalls() {
2227 return mUnmodifiableConferenceableCalls;
2228 }
2229
2230 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002231 * Obtains the state of this {@code Call}.
2232 *
Tyler Gunn1e406ca2021-03-18 16:47:14 -07002233 * @return The call state.
2234 * @deprecated The call state is available via {@link Call.Details#getState()}.
Ihab Awade63fadb2014-07-09 21:52:04 -07002235 */
Tyler Gunn1e406ca2021-03-18 16:47:14 -07002236 @Deprecated
2237 public @CallState int getState() {
Ihab Awade63fadb2014-07-09 21:52:04 -07002238 return mState;
2239 }
2240
2241 /**
Hall Liuef98bf82020-01-09 15:22:44 -08002242 * Returns the child {@link Call} in a generic conference that is currently active.
Hall Liu135e53aa2020-02-27 18:34:11 -08002243 *
2244 * A "generic conference" is the mechanism used to support two simultaneous calls on a device
2245 * in CDMA networks. It is effectively equivalent to having one call active and one call on hold
2246 * in GSM or IMS calls. This method returns the currently active call.
2247 *
2248 * In a generic conference, the network exposes the conference to us as a single call, and we
2249 * switch between talking to the two participants using a CDMA flash command. Since the network
2250 * exposes no additional information about the call, the only way we know which caller we're
2251 * currently talking to is by keeping track of the flash commands that we've sent to the
2252 * network.
2253 *
Hall Liuef98bf82020-01-09 15:22:44 -08002254 * For calls that are not generic conferences, or when the generic conference has more than
2255 * 2 children, returns {@code null}.
2256 * @see Details#PROPERTY_GENERIC_CONFERENCE
2257 * @return The active child call.
2258 */
2259 public @Nullable Call getGenericConferenceActiveChildCall() {
2260 if (mActiveGenericConferenceChild != null) {
2261 return mPhone.internalGetCallByTelecomId(mActiveGenericConferenceChild);
2262 }
2263 return null;
2264 }
2265
2266 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002267 * Obtains a list of canned, pre-configured message responses to present to the user as
Tyler Gunn434fc2c2020-10-06 14:23:54 -07002268 * ways of rejecting an incoming {@code Call} using via a text message.
2269 * <p>
2270 * <em>Note:</em> Since canned responses may be loaded from the file system, they are not
2271 * guaranteed to be present when this {@link Call} is first added to the {@link InCallService}
2272 * via {@link InCallService#onCallAdded(Call)}. The callback
2273 * {@link Call.Callback#onCannedTextResponsesLoaded(Call, List)} will be called when/if canned
2274 * responses for the call become available.
Ihab Awade63fadb2014-07-09 21:52:04 -07002275 *
2276 * @see #reject(boolean, String)
2277 *
2278 * @return A list of canned text message responses.
2279 */
2280 public List<String> getCannedTextResponses() {
2281 return mCannedTextResponses;
2282 }
2283
2284 /**
2285 * Obtains an object that can be used to display video from this {@code Call}.
2286 *
Andrew Lee50aca232014-07-22 16:41:54 -07002287 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -07002288 */
Andrew Lee50aca232014-07-22 16:41:54 -07002289 public InCallService.VideoCall getVideoCall() {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002290 return mVideoCallImpl;
Ihab Awade63fadb2014-07-09 21:52:04 -07002291 }
2292
2293 /**
2294 * Obtains an object containing call details.
2295 *
2296 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
2297 * result may be {@code null}.
2298 */
2299 public Details getDetails() {
2300 return mDetails;
2301 }
2302
2303 /**
Hall Liu95d55872017-01-25 17:12:49 -08002304 * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
2305 * receive RTT text data, as well as to change the RTT mode.
2306 * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
2307 */
2308 public @Nullable RttCall getRttCall() {
2309 return mRttCall;
2310 }
2311
2312 /**
2313 * Returns whether this call has an active RTT connection.
2314 * @return true if there is a connection, false otherwise.
2315 */
2316 public boolean isRttActive() {
Hall Liue9041242018-02-09 16:40:03 -08002317 return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
Hall Liu95d55872017-01-25 17:12:49 -08002318 }
2319
2320 /**
Andrew Leeda80c872015-04-15 14:09:50 -07002321 * Registers a callback to this {@code Call}.
2322 *
2323 * @param callback A {@code Callback}.
2324 */
2325 public void registerCallback(Callback callback) {
Andrew Lee011728f2015-04-23 15:47:06 -07002326 registerCallback(callback, new Handler());
2327 }
2328
2329 /**
2330 * Registers a callback to this {@code Call}.
2331 *
2332 * @param callback A {@code Callback}.
2333 * @param handler A handler which command and status changes will be delivered to.
2334 */
2335 public void registerCallback(Callback callback, Handler handler) {
2336 unregisterCallback(callback);
Roshan Pius1ca62072015-07-07 17:34:51 -07002337 // Don't allow new callback registration if the call is already being destroyed.
2338 if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002339 mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
2340 }
Andrew Leeda80c872015-04-15 14:09:50 -07002341 }
2342
2343 /**
2344 * Unregisters a callback from this {@code Call}.
2345 *
2346 * @param callback A {@code Callback}.
2347 */
2348 public void unregisterCallback(Callback callback) {
Roshan Pius1ca62072015-07-07 17:34:51 -07002349 // Don't allow callback deregistration if the call is already being destroyed.
2350 if (callback != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002351 for (CallbackRecord<Callback> record : mCallbackRecords) {
2352 if (record.getCallback() == callback) {
2353 mCallbackRecords.remove(record);
2354 break;
2355 }
2356 }
Andrew Leeda80c872015-04-15 14:09:50 -07002357 }
2358 }
2359
Santos Cordon3c20d632016-02-25 16:12:35 -08002360 @Override
2361 public String toString() {
2362 return new StringBuilder().
2363 append("Call [id: ").
2364 append(mTelecomCallId).
2365 append(", state: ").
2366 append(stateToString(mState)).
2367 append(", details: ").
2368 append(mDetails).
2369 append("]").toString();
2370 }
2371
2372 /**
2373 * @param state An integer value of a {@code STATE_*} constant.
2374 * @return A string representation of the value.
2375 */
2376 private static String stateToString(int state) {
2377 switch (state) {
2378 case STATE_NEW:
2379 return "NEW";
2380 case STATE_RINGING:
2381 return "RINGING";
2382 case STATE_DIALING:
2383 return "DIALING";
2384 case STATE_ACTIVE:
2385 return "ACTIVE";
2386 case STATE_HOLDING:
2387 return "HOLDING";
2388 case STATE_DISCONNECTED:
2389 return "DISCONNECTED";
2390 case STATE_CONNECTING:
2391 return "CONNECTING";
2392 case STATE_DISCONNECTING:
2393 return "DISCONNECTING";
2394 case STATE_SELECT_PHONE_ACCOUNT:
2395 return "SELECT_PHONE_ACCOUNT";
Hall Liu4e35b642019-10-14 17:50:45 -07002396 case STATE_SIMULATED_RINGING:
2397 return "SIMULATED_RINGING";
2398 case STATE_AUDIO_PROCESSING:
2399 return "AUDIO_PROCESSING";
Santos Cordon3c20d632016-02-25 16:12:35 -08002400 default:
2401 Log.w(Call.class, "Unknown state %d", state);
2402 return "UNKNOWN";
2403 }
2404 }
2405
Andrew Leeda80c872015-04-15 14:09:50 -07002406 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002407 * Adds a listener to this {@code Call}.
2408 *
2409 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002410 * @deprecated Use {@link #registerCallback} instead.
2411 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002412 */
Andrew Leeda80c872015-04-15 14:09:50 -07002413 @Deprecated
2414 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002415 public void addListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002416 registerCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002417 }
2418
2419 /**
2420 * Removes a listener from this {@code Call}.
2421 *
2422 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002423 * @deprecated Use {@link #unregisterCallback} instead.
2424 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002425 */
Andrew Leeda80c872015-04-15 14:09:50 -07002426 @Deprecated
2427 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002428 public void removeListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002429 unregisterCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002430 }
2431
2432 /** {@hide} */
Tyler Gunn159f35c2017-03-02 09:28:37 -08002433 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
2434 int targetSdkVersion) {
Ihab Awade63fadb2014-07-09 21:52:04 -07002435 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002436 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002437 mInCallAdapter = inCallAdapter;
2438 mState = STATE_NEW;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002439 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002440 mTargetSdkVersion = targetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07002441 }
2442
2443 /** {@hide} */
Tyler Gunnb88b3112016-11-09 10:19:23 -08002444 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
Tyler Gunn159f35c2017-03-02 09:28:37 -08002445 String callingPackage, int targetSdkVersion) {
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002446 mPhone = phone;
2447 mTelecomCallId = telecomCallId;
2448 mInCallAdapter = inCallAdapter;
2449 mState = state;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002450 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002451 mTargetSdkVersion = targetSdkVersion;
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002452 }
2453
2454 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002455 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002456 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002457 }
2458
2459 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002460 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Tyler Gunnb88b3112016-11-09 10:19:23 -08002461
Ihab Awade63fadb2014-07-09 21:52:04 -07002462 // First, we update the internal state as far as possible before firing any updates.
Sailesh Nepal1bef3392016-01-24 18:21:53 -08002463 Details details = Details.createFromParcelableCall(parcelableCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07002464 boolean detailsChanged = !Objects.equals(mDetails, details);
2465 if (detailsChanged) {
2466 mDetails = details;
2467 }
2468
2469 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -07002470 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
2471 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
2472 mCannedTextResponses =
2473 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Yorke Leee886f632015-08-04 13:43:31 -07002474 cannedTextResponsesChanged = true;
Ihab Awade63fadb2014-07-09 21:52:04 -07002475 }
2476
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002477 IVideoProvider previousVideoProvider = mVideoCallImpl == null ? null :
2478 mVideoCallImpl.getVideoProvider();
2479 IVideoProvider newVideoProvider = parcelableCall.getVideoProvider();
2480
2481 // parcelableCall.isVideoCallProviderChanged is only true when we have a video provider
2482 // specified; so we should check if the actual IVideoProvider changes as well.
2483 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged()
2484 && !Objects.equals(previousVideoProvider, newVideoProvider);
Andrew Lee50aca232014-07-22 16:41:54 -07002485 if (videoCallChanged) {
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002486 if (mVideoCallImpl != null) {
2487 mVideoCallImpl.destroy();
2488 }
2489 mVideoCallImpl = parcelableCall.isVideoCallProviderChanged() ?
2490 parcelableCall.getVideoCallImpl(mCallingPackage, mTargetSdkVersion) : null;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002491 }
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002492
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002493 if (mVideoCallImpl != null) {
2494 mVideoCallImpl.setVideoState(getDetails().getVideoState());
Ihab Awade63fadb2014-07-09 21:52:04 -07002495 }
2496
Santos Cordone3c507b2015-04-23 14:44:19 -07002497 int state = parcelableCall.getState();
Hall Liu31de23d2019-10-11 15:38:29 -07002498 if (mTargetSdkVersion < Phone.SDK_VERSION_R && state == Call.STATE_SIMULATED_RINGING) {
2499 state = Call.STATE_RINGING;
2500 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002501 boolean stateChanged = mState != state;
2502 if (stateChanged) {
2503 mState = state;
2504 }
2505
Santos Cordon823fd3c2014-08-07 18:35:18 -07002506 String parentId = parcelableCall.getParentCallId();
2507 boolean parentChanged = !Objects.equals(mParentId, parentId);
2508 if (parentChanged) {
2509 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002510 }
2511
Santos Cordon823fd3c2014-08-07 18:35:18 -07002512 List<String> childCallIds = parcelableCall.getChildCallIds();
2513 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
2514 if (childrenChanged) {
2515 mChildrenIds.clear();
2516 mChildrenIds.addAll(parcelableCall.getChildCallIds());
2517 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -07002518 }
2519
Hall Liuef98bf82020-01-09 15:22:44 -08002520 String activeChildCallId = parcelableCall.getActiveChildCallId();
2521 boolean activeChildChanged = !Objects.equals(activeChildCallId,
2522 mActiveGenericConferenceChild);
2523 if (activeChildChanged) {
2524 mActiveGenericConferenceChild = activeChildCallId;
2525 }
2526
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002527 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
2528 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
2529 for (String otherId : conferenceableCallIds) {
2530 if (callIdMap.containsKey(otherId)) {
2531 conferenceableCalls.add(callIdMap.get(otherId));
2532 }
2533 }
2534
2535 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
2536 mConferenceableCalls.clear();
2537 mConferenceableCalls.addAll(conferenceableCalls);
2538 fireConferenceableCallsChanged();
2539 }
2540
Hall Liu95d55872017-01-25 17:12:49 -08002541 boolean isRttChanged = false;
2542 boolean rttModeChanged = false;
Hall Liue9041242018-02-09 16:40:03 -08002543 if (parcelableCall.getIsRttCallChanged()
2544 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
Hall Liu95d55872017-01-25 17:12:49 -08002545 ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
2546 InputStreamReader receiveStream = new InputStreamReader(
2547 new ParcelFileDescriptor.AutoCloseInputStream(
2548 parcelableRttCall.getReceiveStream()),
2549 StandardCharsets.UTF_8);
2550 OutputStreamWriter transmitStream = new OutputStreamWriter(
2551 new ParcelFileDescriptor.AutoCloseOutputStream(
2552 parcelableRttCall.getTransmitStream()),
2553 StandardCharsets.UTF_8);
Hall Liu57006aa2017-02-06 10:49:48 -08002554 RttCall newRttCall = new Call.RttCall(mTelecomCallId,
Hall Liu95d55872017-01-25 17:12:49 -08002555 receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
2556 if (mRttCall == null) {
2557 isRttChanged = true;
2558 } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
2559 rttModeChanged = true;
2560 }
2561 mRttCall = newRttCall;
2562 } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
2563 && parcelableCall.getIsRttCallChanged()) {
2564 isRttChanged = true;
Tyler Gunn4cd42482021-04-30 16:23:15 -07002565 mRttCall.close();
Hall Liu95d55872017-01-25 17:12:49 -08002566 mRttCall = null;
2567 }
2568
Ihab Awade63fadb2014-07-09 21:52:04 -07002569 // Now we fire updates, ensuring that any client who listens to any of these notifications
2570 // gets the most up-to-date state.
2571
2572 if (stateChanged) {
2573 fireStateChanged(mState);
2574 }
2575 if (detailsChanged) {
2576 fireDetailsChanged(mDetails);
2577 }
2578 if (cannedTextResponsesChanged) {
2579 fireCannedTextResponsesLoaded(mCannedTextResponses);
2580 }
Andrew Lee50aca232014-07-22 16:41:54 -07002581 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002582 fireVideoCallChanged(mVideoCallImpl);
Ihab Awade63fadb2014-07-09 21:52:04 -07002583 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002584 if (parentChanged) {
2585 fireParentChanged(getParent());
2586 }
Hall Liuef98bf82020-01-09 15:22:44 -08002587 if (childrenChanged || activeChildChanged) {
Santos Cordon823fd3c2014-08-07 18:35:18 -07002588 fireChildrenChanged(getChildren());
2589 }
Hall Liu95d55872017-01-25 17:12:49 -08002590 if (isRttChanged) {
2591 fireOnIsRttChanged(mRttCall != null, mRttCall);
2592 }
2593 if (rttModeChanged) {
2594 fireOnRttModeChanged(mRttCall.getRttAudioMode());
2595 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002596
2597 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
2598 // remove ourselves from the Phone. Note that we do this after completing all state updates
2599 // so a client can cleanly transition all their UI to the state appropriate for a
2600 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
2601 if (mState == STATE_DISCONNECTED) {
2602 fireCallDestroyed();
Ihab Awade63fadb2014-07-09 21:52:04 -07002603 }
2604 }
2605
2606 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002607 final void internalSetPostDialWait(String remaining) {
2608 mRemainingPostDialSequence = remaining;
2609 firePostDialWait(mRemainingPostDialSequence);
2610 }
2611
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07002612 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -07002613 final void internalSetDisconnected() {
2614 if (mState != Call.STATE_DISCONNECTED) {
2615 mState = Call.STATE_DISCONNECTED;
Tyler Gunn1e406ca2021-03-18 16:47:14 -07002616 if (mDetails != null) {
2617 mDetails = new Details(mState,
2618 mDetails.getTelecomCallId(),
2619 mDetails.getHandle(),
2620 mDetails.getHandlePresentation(),
2621 mDetails.getCallerDisplayName(),
2622 mDetails.getCallerDisplayNamePresentation(),
2623 mDetails.getAccountHandle(),
2624 mDetails.getCallCapabilities(),
2625 mDetails.getCallProperties(),
2626 mDetails.getDisconnectCause(),
2627 mDetails.getConnectTimeMillis(),
2628 mDetails.getGatewayInfo(),
2629 mDetails.getVideoState(),
2630 mDetails.getStatusHints(),
2631 mDetails.getExtras(),
2632 mDetails.getIntentExtras(),
2633 mDetails.getCreationTimeMillis(),
2634 mDetails.getContactDisplayName(),
2635 mDetails.getCallDirection(),
Grace Jiae04723f2022-01-26 16:24:48 +00002636 mDetails.getCallerNumberVerificationStatus()
Tyler Gunn1e406ca2021-03-18 16:47:14 -07002637 );
2638 fireDetailsChanged(mDetails);
2639 }
Santos Cordonf30d7e92014-08-26 09:54:33 -07002640 fireStateChanged(mState);
2641 fireCallDestroyed();
Santos Cordonf30d7e92014-08-26 09:54:33 -07002642 }
2643 }
2644
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002645 /** {@hide} */
2646 final void internalOnConnectionEvent(String event, Bundle extras) {
2647 fireOnConnectionEvent(event, extras);
2648 }
2649
Hall Liu95d55872017-01-25 17:12:49 -08002650 /** {@hide} */
2651 final void internalOnRttUpgradeRequest(final int requestId) {
2652 for (CallbackRecord<Callback> record : mCallbackRecords) {
2653 final Call call = this;
2654 final Callback callback = record.getCallback();
2655 record.getHandler().post(() -> callback.onRttRequest(call, requestId));
2656 }
2657 }
2658
Hall Liu57006aa2017-02-06 10:49:48 -08002659 /** @hide */
2660 final void internalOnRttInitiationFailure(int reason) {
2661 for (CallbackRecord<Callback> record : mCallbackRecords) {
2662 final Call call = this;
2663 final Callback callback = record.getCallback();
2664 record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
2665 }
2666 }
2667
Sanket Padawe85291f62017-12-01 13:59:27 -08002668 /** {@hide} */
2669 final void internalOnHandoverFailed(int error) {
2670 for (CallbackRecord<Callback> record : mCallbackRecords) {
2671 final Call call = this;
2672 final Callback callback = record.getCallback();
2673 record.getHandler().post(() -> callback.onHandoverFailed(call, error));
2674 }
2675 }
2676
Tyler Gunn858bfaf2018-01-22 15:17:54 -08002677 /** {@hide} */
Grace Jiae04723f2022-01-26 16:24:48 +00002678 final void internalOnHandoverComplete() {
Tyler Gunn858bfaf2018-01-22 15:17:54 -08002679 for (CallbackRecord<Callback> record : mCallbackRecords) {
2680 final Call call = this;
2681 final Callback callback = record.getCallback();
2682 record.getHandler().post(() -> callback.onHandoverComplete(call));
2683 }
2684 }
2685
Andrew Lee011728f2015-04-23 15:47:06 -07002686 private void fireStateChanged(final int newState) {
2687 for (CallbackRecord<Callback> record : mCallbackRecords) {
2688 final Call call = this;
2689 final Callback callback = record.getCallback();
2690 record.getHandler().post(new Runnable() {
2691 @Override
2692 public void run() {
2693 callback.onStateChanged(call, newState);
2694 }
2695 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002696 }
2697 }
2698
Andrew Lee011728f2015-04-23 15:47:06 -07002699 private void fireParentChanged(final Call newParent) {
2700 for (CallbackRecord<Callback> record : mCallbackRecords) {
2701 final Call call = this;
2702 final Callback callback = record.getCallback();
2703 record.getHandler().post(new Runnable() {
2704 @Override
2705 public void run() {
2706 callback.onParentChanged(call, newParent);
2707 }
2708 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002709 }
2710 }
2711
Andrew Lee011728f2015-04-23 15:47:06 -07002712 private void fireChildrenChanged(final List<Call> children) {
2713 for (CallbackRecord<Callback> record : mCallbackRecords) {
2714 final Call call = this;
2715 final Callback callback = record.getCallback();
2716 record.getHandler().post(new Runnable() {
2717 @Override
2718 public void run() {
2719 callback.onChildrenChanged(call, children);
2720 }
2721 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002722 }
2723 }
2724
Andrew Lee011728f2015-04-23 15:47:06 -07002725 private void fireDetailsChanged(final Details details) {
2726 for (CallbackRecord<Callback> record : mCallbackRecords) {
2727 final Call call = this;
2728 final Callback callback = record.getCallback();
2729 record.getHandler().post(new Runnable() {
2730 @Override
2731 public void run() {
2732 callback.onDetailsChanged(call, details);
2733 }
2734 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002735 }
2736 }
2737
Andrew Lee011728f2015-04-23 15:47:06 -07002738 private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
2739 for (CallbackRecord<Callback> record : mCallbackRecords) {
2740 final Call call = this;
2741 final Callback callback = record.getCallback();
2742 record.getHandler().post(new Runnable() {
2743 @Override
2744 public void run() {
2745 callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
2746 }
2747 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002748 }
2749 }
2750
Andrew Lee011728f2015-04-23 15:47:06 -07002751 private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
2752 for (CallbackRecord<Callback> record : mCallbackRecords) {
2753 final Call call = this;
2754 final Callback callback = record.getCallback();
2755 record.getHandler().post(new Runnable() {
2756 @Override
2757 public void run() {
2758 callback.onVideoCallChanged(call, videoCall);
2759 }
2760 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002761 }
2762 }
2763
Andrew Lee011728f2015-04-23 15:47:06 -07002764 private void firePostDialWait(final String remainingPostDialSequence) {
2765 for (CallbackRecord<Callback> record : mCallbackRecords) {
2766 final Call call = this;
2767 final Callback callback = record.getCallback();
2768 record.getHandler().post(new Runnable() {
2769 @Override
2770 public void run() {
2771 callback.onPostDialWait(call, remainingPostDialSequence);
2772 }
2773 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002774 }
2775 }
2776
2777 private void fireCallDestroyed() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002778 /**
2779 * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
2780 * onCallRemoved callback, we remove this call from the Phone's record
2781 * only once all of the registered onCallDestroyed callbacks are executed.
2782 * All the callbacks get removed from our records as a part of this operation
2783 * since onCallDestroyed is the final callback.
2784 */
2785 final Call call = this;
2786 if (mCallbackRecords.isEmpty()) {
2787 // No callbacks registered, remove the call from Phone's record.
2788 mPhone.internalRemoveCall(call);
2789 }
2790 for (final CallbackRecord<Callback> record : mCallbackRecords) {
Andrew Lee011728f2015-04-23 15:47:06 -07002791 final Callback callback = record.getCallback();
2792 record.getHandler().post(new Runnable() {
2793 @Override
2794 public void run() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002795 boolean isFinalRemoval = false;
2796 RuntimeException toThrow = null;
2797 try {
2798 callback.onCallDestroyed(call);
2799 } catch (RuntimeException e) {
2800 toThrow = e;
2801 }
2802 synchronized(Call.this) {
2803 mCallbackRecords.remove(record);
2804 if (mCallbackRecords.isEmpty()) {
2805 isFinalRemoval = true;
2806 }
2807 }
2808 if (isFinalRemoval) {
2809 mPhone.internalRemoveCall(call);
2810 }
2811 if (toThrow != null) {
2812 throw toThrow;
2813 }
Andrew Lee011728f2015-04-23 15:47:06 -07002814 }
2815 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002816 }
2817 }
2818
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002819 private void fireConferenceableCallsChanged() {
Andrew Lee011728f2015-04-23 15:47:06 -07002820 for (CallbackRecord<Callback> record : mCallbackRecords) {
2821 final Call call = this;
2822 final Callback callback = record.getCallback();
2823 record.getHandler().post(new Runnable() {
2824 @Override
2825 public void run() {
2826 callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
2827 }
2828 });
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002829 }
2830 }
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002831
2832 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002833 * Notifies listeners of an incoming connection event.
2834 * <p>
2835 * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
2836 *
2837 * @param event
2838 * @param extras
2839 */
2840 private void fireOnConnectionEvent(final String event, final Bundle extras) {
2841 for (CallbackRecord<Callback> record : mCallbackRecords) {
2842 final Call call = this;
2843 final Callback callback = record.getCallback();
2844 record.getHandler().post(new Runnable() {
2845 @Override
2846 public void run() {
2847 callback.onConnectionEvent(call, event, extras);
2848 }
2849 });
2850 }
2851 }
2852
2853 /**
Hall Liu95d55872017-01-25 17:12:49 -08002854 * Notifies listeners of an RTT on/off change
2855 *
2856 * @param enabled True if RTT is now enabled, false otherwise
2857 */
2858 private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
2859 for (CallbackRecord<Callback> record : mCallbackRecords) {
2860 final Call call = this;
2861 final Callback callback = record.getCallback();
2862 record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
2863 }
2864 }
2865
2866 /**
2867 * Notifies listeners of a RTT mode change
2868 *
2869 * @param mode The new RTT mode
2870 */
2871 private void fireOnRttModeChanged(final int mode) {
2872 for (CallbackRecord<Callback> record : mCallbackRecords) {
2873 final Call call = this;
2874 final Callback callback = record.getCallback();
2875 record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
2876 }
2877 }
2878
2879 /**
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002880 * Determines if two bundles are equal.
2881 *
2882 * @param bundle The original bundle.
2883 * @param newBundle The bundle to compare with.
2884 * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
2885 */
2886 private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
2887 if (bundle == null || newBundle == null) {
2888 return bundle == newBundle;
2889 }
2890
2891 if (bundle.size() != newBundle.size()) {
2892 return false;
2893 }
2894
2895 for(String key : bundle.keySet()) {
2896 if (key != null) {
2897 final Object value = bundle.get(key);
2898 final Object newValue = newBundle.get(key);
2899 if (!Objects.equals(value, newValue)) {
2900 return false;
2901 }
2902 }
2903 }
2904 return true;
2905 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002906}