blob: a8852a849604693ccbef436f8058a5c0b8b8d495 [file] [log] [blame]
Ihab Awade63fadb2014-07-09 21:52:04 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tyler Gunnef9f6f92014-09-12 22:16:17 -070017package android.telecom;
Ihab Awade63fadb2014-07-09 21:52:04 -070018
Hall Liu95d55872017-01-25 17:12:49 -080019import android.annotation.IntDef;
20import android.annotation.Nullable;
Andrew Leeda80c872015-04-15 14:09:50 -070021import android.annotation.SystemApi;
Hall Liu6dfa2492019-10-01 17:20:39 -070022import android.annotation.TestApi;
Artur Satayeva5264902019-12-10 17:47:56 +000023import android.compat.annotation.UnsupportedAppUsage;
Ihab Awade63fadb2014-07-09 21:52:04 -070024import android.net.Uri;
Tyler Gunn6e3ecc42018-11-12 11:30:56 -080025import android.os.Build;
Nancy Chen10798dc2014-08-08 14:00:25 -070026import android.os.Bundle;
Andrew Lee011728f2015-04-23 15:47:06 -070027import android.os.Handler;
Hall Liu95d55872017-01-25 17:12:49 -080028import android.os.ParcelFileDescriptor;
Ihab Awade63fadb2014-07-09 21:52:04 -070029
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -080030import com.android.internal.telecom.IVideoProvider;
31
Hall Liu95d55872017-01-25 17:12:49 -080032import java.io.IOException;
33import java.io.InputStreamReader;
34import java.io.OutputStreamWriter;
Hall Liu95d55872017-01-25 17:12:49 -080035import java.lang.annotation.Retention;
36import java.lang.annotation.RetentionPolicy;
37import java.nio.charset.StandardCharsets;
Ihab Awade63fadb2014-07-09 21:52:04 -070038import java.util.ArrayList;
Tyler Gunn071be6f2016-05-10 14:52:33 -070039import java.util.Arrays;
Ihab Awade63fadb2014-07-09 21:52:04 -070040import java.util.Collections;
41import java.util.List;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070042import java.util.Map;
Ihab Awade63fadb2014-07-09 21:52:04 -070043import java.util.Objects;
Jay Shrauner229e3822014-08-15 09:23:07 -070044import java.util.concurrent.CopyOnWriteArrayList;
Ihab Awade63fadb2014-07-09 21:52:04 -070045
46/**
47 * Represents an ongoing phone call that the in-call app should present to the user.
48 */
49public final class Call {
50 /**
51 * The state of a {@code Call} when newly created.
52 */
53 public static final int STATE_NEW = 0;
54
55 /**
56 * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
57 */
58 public static final int STATE_DIALING = 1;
59
60 /**
61 * The state of an incoming {@code Call} when ringing locally, but not yet connected.
62 */
63 public static final int STATE_RINGING = 2;
64
65 /**
66 * The state of a {@code Call} when in a holding state.
67 */
68 public static final int STATE_HOLDING = 3;
69
70 /**
71 * The state of a {@code Call} when actively supporting conversation.
72 */
73 public static final int STATE_ACTIVE = 4;
74
75 /**
76 * The state of a {@code Call} when no further voice or other communication is being
77 * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
78 * is no longer active, and the local data transport has or inevitably will release resources
79 * associated with this {@code Call}.
80 */
81 public static final int STATE_DISCONNECTED = 7;
82
Nancy Chen5da0fd52014-07-08 14:16:17 -070083 /**
Santos Cordone3c507b2015-04-23 14:44:19 -070084 * The state of an outgoing {@code Call} when waiting on user to select a
85 * {@link PhoneAccount} through which to place the call.
Nancy Chen5da0fd52014-07-08 14:16:17 -070086 */
Santos Cordone3c507b2015-04-23 14:44:19 -070087 public static final int STATE_SELECT_PHONE_ACCOUNT = 8;
88
89 /**
90 * @hide
91 * @deprecated use STATE_SELECT_PHONE_ACCOUNT.
92 */
93 @Deprecated
94 @SystemApi
95 public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT;
Nancy Chen5da0fd52014-07-08 14:16:17 -070096
Nancy Chene20930f2014-08-07 16:17:21 -070097 /**
Nancy Chene9b7a8e2014-08-08 14:26:27 -070098 * The initial state of an outgoing {@code Call}.
99 * Common transitions are to {@link #STATE_DIALING} state for a successful call or
100 * {@link #STATE_DISCONNECTED} if it failed.
Nancy Chene20930f2014-08-07 16:17:21 -0700101 */
102 public static final int STATE_CONNECTING = 9;
103
Nancy Chen513c8922014-09-17 14:47:20 -0700104 /**
Tyler Gunn4afc6af2014-10-07 10:14:55 -0700105 * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
106 * call has not yet been disconnected by the underlying {@code ConnectionService}. The next
107 * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
108 */
109 public static final int STATE_DISCONNECTING = 10;
110
111 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700112 * The state of an external call which is in the process of being pulled from a remote device to
113 * the local device.
114 * <p>
115 * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
116 * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
117 * <p>
118 * An {@link InCallService} will only see this state if it has the
119 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
120 * manifest.
121 */
122 public static final int STATE_PULLING_CALL = 11;
123
124 /**
Hall Liu6dfa2492019-10-01 17:20:39 -0700125 * The state of a call that is active with the network, but the audio from the call is
126 * being intercepted by an app on the local device. Telecom does not hold audio focus in this
127 * state, and the call will be invisible to the user except for a persistent notification.
128 */
129 public static final int STATE_AUDIO_PROCESSING = 12;
130
131 /**
132 * The state of a call that is being presented to the user after being in
133 * {@link #STATE_AUDIO_PROCESSING}. The call is still active with the network in this case, and
134 * Telecom will hold audio focus and play a ringtone if appropriate.
135 */
136 public static final int STATE_SIMULATED_RINGING = 13;
137
138 /**
Nancy Chen513c8922014-09-17 14:47:20 -0700139 * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
140 * extras. Used to pass the phone accounts to display on the front end to the user in order to
141 * select phone accounts to (for example) place a call.
Hall Liu34d9e242018-11-21 17:05:58 -0800142 * @deprecated Use the list from {@link #EXTRA_SUGGESTED_PHONE_ACCOUNTS} instead.
Nancy Chen513c8922014-09-17 14:47:20 -0700143 */
Hall Liu34d9e242018-11-21 17:05:58 -0800144 @Deprecated
Nancy Chen513c8922014-09-17 14:47:20 -0700145 public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
146
mike dooley4af561f2016-12-20 08:55:17 -0800147 /**
Hall Liu34d9e242018-11-21 17:05:58 -0800148 * Key for extra used to pass along a list of {@link PhoneAccountSuggestion}s to the in-call
149 * UI when a call enters the {@link #STATE_SELECT_PHONE_ACCOUNT} state. The list included here
150 * will have the same length and be in the same order as the list passed with
151 * {@link #AVAILABLE_PHONE_ACCOUNTS}.
152 */
153 public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS =
154 "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS";
155
156 /**
mike dooley91217422017-03-09 12:58:42 -0800157 * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC)
158 * when the last outgoing emergency call was made. This is used to identify potential emergency
159 * callbacks.
mike dooley4af561f2016-12-20 08:55:17 -0800160 */
161 public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
162 "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
163
Usman Abdullahb0dc29a2019-03-06 15:54:56 -0800164
165 /**
166 * Extra key used to indicate whether a {@link CallScreeningService} has requested to silence
167 * the ringtone for a call. If the {@link InCallService} declares
168 * {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} in its manifest, it should not
169 * play a ringtone for an incoming call with this extra key set.
170 */
171 public static final String EXTRA_SILENT_RINGING_REQUESTED =
172 "android.telecom.extra.SILENT_RINGING_REQUESTED";
173
Tyler Gunn8bf76572017-04-06 15:30:08 -0700174 /**
175 * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
176 * Telecom that the user has requested that the current {@link Call} should be handed over
177 * to another {@link ConnectionService}.
178 * <p>
179 * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
180 * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
181 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700182 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
183 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700184 */
185 public static final String EVENT_REQUEST_HANDOVER =
186 "android.telecom.event.REQUEST_HANDOVER";
187
188 /**
189 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
190 * {@link PhoneAccountHandle} to which a call should be handed over to.
191 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700192 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
193 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700194 */
195 public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
196 "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
197
198 /**
199 * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
200 * video state of the call when it is handed over to the new {@link PhoneAccount}.
201 * <p>
202 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
203 * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
204 * {@link VideoProfile#STATE_TX_ENABLED}.
205 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700206 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
207 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700208 */
209 public static final String EXTRA_HANDOVER_VIDEO_STATE =
210 "android.telecom.extra.HANDOVER_VIDEO_STATE";
211
212 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700213 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Used by the
214 * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra
215 * information to the handover {@link ConnectionService} specified by
216 * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}.
217 * <p>
218 * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the
219 * {@link ConnectionService} via the request extras when
220 * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
221 * is called to initate the handover.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700222 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700223 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
224 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700225 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700226 public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700227
228 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700229 * Call event sent from Telecom to the handover {@link ConnectionService} via
230 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
231 * to the {@link ConnectionService} has completed successfully.
232 * <p>
233 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700234 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700235 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
236 * APIs instead.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700237 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700238 public static final String EVENT_HANDOVER_COMPLETE =
239 "android.telecom.event.HANDOVER_COMPLETE";
Tyler Gunn34a2b312017-06-23 08:32:00 -0700240
241 /**
242 * Call event sent from Telecom to the handover destination {@link ConnectionService} via
243 * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the
244 * source connection has disconnected. The {@link Bundle} parameter for the call event will be
245 * {@code null}.
246 * <p>
247 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
248 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700249 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
250 * APIs instead.
Tyler Gunn34a2b312017-06-23 08:32:00 -0700251 */
252 public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
253 "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
254
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700255 /**
256 * Call event sent from Telecom to the handover {@link ConnectionService} via
257 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
258 * to the {@link ConnectionService} has failed.
259 * <p>
260 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
261 * @hide
Tyler Gunn1a505fa2018-09-14 13:36:38 -0700262 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
263 * APIs instead.
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700264 */
265 public static final String EVENT_HANDOVER_FAILED =
266 "android.telecom.event.HANDOVER_FAILED";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700267
Ihab Awade63fadb2014-07-09 21:52:04 -0700268 public static class Details {
Tyler Gunn94f8f112018-12-17 09:56:11 -0800269 /** @hide */
270 @Retention(RetentionPolicy.SOURCE)
271 @IntDef(
272 prefix = { "DIRECTION_" },
273 value = {DIRECTION_UNKNOWN, DIRECTION_INCOMING, DIRECTION_OUTGOING})
274 public @interface CallDirection {}
275
276 /**
277 * Indicates that the call is neither and incoming nor an outgoing call. This can be the
278 * case for calls reported directly by a {@link ConnectionService} in special cases such as
279 * call handovers.
280 */
281 public static final int DIRECTION_UNKNOWN = -1;
282
283 /**
284 * Indicates that the call is an incoming call.
285 */
286 public static final int DIRECTION_INCOMING = 0;
287
288 /**
289 * Indicates that the call is an outgoing call.
290 */
291 public static final int DIRECTION_OUTGOING = 1;
292
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800293 /** Call can currently be put on hold or unheld. */
294 public static final int CAPABILITY_HOLD = 0x00000001;
295
296 /** Call supports the hold feature. */
297 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
298
299 /**
300 * Calls within a conference can be merged. A {@link ConnectionService} has the option to
301 * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
302 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
303 * capability allows a merge button to be shown while the conference call is in the foreground
304 * of the in-call UI.
305 * <p>
306 * This is only intended for use by a {@link Conference}.
307 */
308 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
309
310 /**
311 * Calls within a conference can be swapped between foreground and background.
312 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
313 * <p>
314 * This is only intended for use by a {@link Conference}.
315 */
316 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
317
318 /**
319 * @hide
320 */
Andrew Lee2378ea72015-04-29 14:38:11 -0700321 public static final int CAPABILITY_UNUSED_1 = 0x00000010;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800322
323 /** Call supports responding via text option. */
324 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
325
326 /** Call can be muted. */
327 public static final int CAPABILITY_MUTE = 0x00000040;
328
329 /**
330 * Call supports conference call management. This capability only applies to {@link Conference}
331 * calls which can have {@link Connection}s as children.
332 */
333 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
334
335 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700336 * Local device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800337 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700338 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800339
340 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700341 * Local device supports transmitting video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800342 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700343 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800344
345 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700346 * Local device supports bidirectional video calling.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800347 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700348 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700349 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800350
351 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700352 * Remote device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800353 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700354 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
355
356 /**
357 * Remote device supports transmitting video.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700358 */
359 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
360
361 /**
362 * Remote device supports bidirectional video calling.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700363 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700364 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700365 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800366
367 /**
368 * Call is able to be separated from its parent {@code Conference}, if any.
369 */
370 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
371
372 /**
373 * Call is able to be individually disconnected when in a {@code Conference}.
374 */
375 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
376
377 /**
Dong Zhou89f41eb2015-03-15 11:59:49 -0500378 * Speed up audio setup for MT call.
379 * @hide
380 */
Tyler Gunn96d6c402015-03-18 12:39:23 -0700381 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
382
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700383 /**
384 * Call can be upgraded to a video call.
Rekha Kumar07366812015-03-24 16:42:31 -0700385 * @hide
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800386 * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
387 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call
388 * whether or not video calling is supported.
Rekha Kumar07366812015-03-24 16:42:31 -0700389 */
Tyler Gunn6e3ecc42018-11-12 11:30:56 -0800390 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
Rekha Kumar07366812015-03-24 16:42:31 -0700391 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
392
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700393 /**
394 * For video calls, indicates whether the outgoing video for the call can be paused using
Yorke Lee32f24732015-05-12 16:18:03 -0700395 * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700396 */
397 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
398
Bryce Lee81901682015-08-28 16:38:02 -0700399 /**
400 * Call sends responses through connection.
401 * @hide
402 */
Tyler Gunnf97a0092016-01-19 15:59:34 -0800403 public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;
404
405 /**
406 * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
407 * <p>
408 * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
409 * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
410 * downgraded from a video call back to a VideoState of
411 * {@link VideoProfile#STATE_AUDIO_ONLY}.
412 * <p>
413 * Intuitively, a call which can be downgraded to audio should also have local and remote
414 * video
415 * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
416 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
417 */
418 public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
Bryce Lee81901682015-08-28 16:38:02 -0700419
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700420 /**
421 * When set for an external call, indicates that this {@code Call} can be pulled from a
422 * remote device to the current device.
423 * <p>
424 * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
425 * <p>
426 * An {@link InCallService} will only see calls with this capability if it has the
427 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
428 * in its manifest.
429 * <p>
430 * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
Tyler Gunn720c6642016-03-22 09:02:47 -0700431 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700432 */
433 public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
434
Pooja Jaind34698d2017-12-28 14:15:31 +0530435 /** Call supports the deflect feature. */
436 public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
437
Tyler Gunnd11a3152015-03-18 13:09:14 -0700438 //******************************************************************************************
Pooja Jaind34698d2017-12-28 14:15:31 +0530439 // Next CAPABILITY value: 0x02000000
Andrew Lee2378ea72015-04-29 14:38:11 -0700440 //******************************************************************************************
441
442 /**
443 * Whether the call is currently a conference.
444 */
445 public static final int PROPERTY_CONFERENCE = 0x00000001;
446
447 /**
448 * Whether the call is a generic conference, where we do not know the precise state of
449 * participants in the conference (eg. on CDMA).
450 */
451 public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
452
453 /**
454 * Whether the call is made while the device is in emergency callback mode.
455 */
456 public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
457
458 /**
459 * Connection is using WIFI.
460 */
461 public static final int PROPERTY_WIFI = 0x00000008;
462
463 /**
Tyler Gunn6b6ae552018-10-11 10:42:10 -0700464 * When set, the UI should indicate to the user that a call is using high definition
465 * audio.
466 * <p>
467 * The underlying {@link ConnectionService} is responsible for reporting this
468 * property. It is important to note that this property is not intended to report the
469 * actual audio codec being used for a Call, but whether the call should be indicated
470 * to the user as high definition.
471 * <p>
472 * The Android Telephony stack reports this property for calls based on a number
473 * of factors, including which audio codec is used and whether a call is using an HD
474 * codec end-to-end. Some mobile operators choose to suppress display of an HD indication,
475 * and in these cases this property will not be set for a call even if the underlying audio
476 * codec is in fact "high definition".
Andrew Lee2378ea72015-04-29 14:38:11 -0700477 */
478 public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
479
Tony Maka68dcce2015-12-17 09:31:18 +0000480 /**
Tony Mak53b5df42016-05-19 13:40:38 +0100481 * Whether the call is associated with the work profile.
482 */
483 public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;
484
485 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700486 * When set, indicates that this {@code Call} does not actually exist locally for the
487 * {@link ConnectionService}.
488 * <p>
489 * Consider, for example, a scenario where a user has two phones with the same phone number.
490 * When a user places a call on one device, the telephony stack can represent that call on
491 * the other device by adding it to the {@link ConnectionService} with the
Tyler Gunn720c6642016-03-22 09:02:47 -0700492 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700493 * <p>
494 * An {@link InCallService} will only see calls with this property if it has the
495 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
496 * in its manifest.
497 * <p>
Tyler Gunn720c6642016-03-22 09:02:47 -0700498 * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700499 */
500 public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
501
Brad Ebinger15847072016-05-18 11:08:36 -0700502 /**
503 * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
504 */
505 public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
506
Tyler Gunn24e18332017-02-10 09:42:49 -0800507 /**
508 * Indicates that the call is from a self-managed {@link ConnectionService}.
509 * <p>
510 * See also {@link Connection#PROPERTY_SELF_MANAGED}
511 */
512 public static final int PROPERTY_SELF_MANAGED = 0x00000100;
513
Eric Erfanianec881872017-12-06 16:27:53 -0800514 /**
515 * Indicates the call used Assisted Dialing.
Tyler Gunn5567d742019-10-31 13:04:37 -0700516 *
517 * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING
Eric Erfanianec881872017-12-06 16:27:53 -0800518 */
519 public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200;
520
Hall Liue9041242018-02-09 16:40:03 -0800521 /**
522 * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
523 * {@link RttCall} object that is used to send and receive text.
524 */
525 public static final int PROPERTY_RTT = 0x00000400;
526
Tyler Gunn5bd90852018-09-21 09:37:07 -0700527 /**
528 * Indicates that the call has been identified as the network as an emergency call. This
529 * property may be set for both incoming and outgoing calls which the network identifies as
530 * emergency calls.
531 */
532 public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 0x00000800;
533
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700534 /**
535 * Indicates that the call is using VoIP audio mode.
536 * <p>
537 * When this property is set, the {@link android.media.AudioManager} audio mode for this
538 * call will be {@link android.media.AudioManager#MODE_IN_COMMUNICATION}. When this
539 * property is not set, the audio mode for this call will be
540 * {@link android.media.AudioManager#MODE_IN_CALL}.
541 * <p>
542 * This property reflects changes made using {@link Connection#setAudioModeIsVoip(boolean)}.
543 * <p>
544 * You can use this property to determine whether an un-answered incoming call or a held
545 * call will use VoIP audio mode (if the call does not currently have focus, the system
546 * audio mode may not reflect the mode the call will use).
547 */
548 public static final int PROPERTY_VOIP_AUDIO_MODE = 0x00001000;
549
Andrew Lee2378ea72015-04-29 14:38:11 -0700550 //******************************************************************************************
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700551 // Next PROPERTY value: 0x00002000
Tyler Gunnd11a3152015-03-18 13:09:14 -0700552 //******************************************************************************************
Tyler Gunn068085b2015-02-06 13:56:52 -0800553
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800554 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700555 private final Uri mHandle;
556 private final int mHandlePresentation;
557 private final String mCallerDisplayName;
558 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700559 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700560 private final int mCallCapabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700561 private final int mCallProperties;
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800562 private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700563 private final DisconnectCause mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700564 private final long mConnectTimeMillis;
565 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700566 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700567 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700568 private final Bundle mExtras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700569 private final Bundle mIntentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700570 private final long mCreationTimeMillis;
Tyler Gunn94f8f112018-12-17 09:56:11 -0800571 private final @CallDirection int mCallDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700572 private final @Connection.VerificationStatus int mCallerNumberVerificationStatus;
Ihab Awade63fadb2014-07-09 21:52:04 -0700573
574 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800575 * Whether the supplied capabilities supports the specified capability.
576 *
577 * @param capabilities A bit field of capabilities.
578 * @param capability The capability to check capabilities for.
579 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800580 */
581 public static boolean can(int capabilities, int capability) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800582 return (capabilities & capability) == capability;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800583 }
584
585 /**
586 * Whether the capabilities of this {@code Details} supports the specified capability.
587 *
588 * @param capability The capability to check capabilities for.
589 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800590 */
591 public boolean can(int capability) {
592 return can(mCallCapabilities, capability);
593 }
594
595 /**
596 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
597 *
598 * @param capabilities A capability bit field.
599 * @return A human readable string representation.
600 */
601 public static String capabilitiesToString(int capabilities) {
602 StringBuilder builder = new StringBuilder();
603 builder.append("[Capabilities:");
604 if (can(capabilities, CAPABILITY_HOLD)) {
605 builder.append(" CAPABILITY_HOLD");
606 }
607 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
608 builder.append(" CAPABILITY_SUPPORT_HOLD");
609 }
610 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
611 builder.append(" CAPABILITY_MERGE_CONFERENCE");
612 }
613 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
614 builder.append(" CAPABILITY_SWAP_CONFERENCE");
615 }
616 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
617 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
618 }
619 if (can(capabilities, CAPABILITY_MUTE)) {
620 builder.append(" CAPABILITY_MUTE");
621 }
622 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
623 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
624 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700625 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
626 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
627 }
628 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
629 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
630 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700631 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
632 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800633 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700634 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
635 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
636 }
637 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
638 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
639 }
Tyler Gunnf97a0092016-01-19 15:59:34 -0800640 if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
641 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
642 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700643 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
644 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800645 }
Dong Zhou89f41eb2015-03-15 11:59:49 -0500646 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
Tyler Gunnd11a3152015-03-18 13:09:14 -0700647 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
Dong Zhou89f41eb2015-03-15 11:59:49 -0500648 }
Rekha Kumar07366812015-03-24 16:42:31 -0700649 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
650 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
651 }
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700652 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
653 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
654 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700655 if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
656 builder.append(" CAPABILITY_CAN_PULL_CALL");
657 }
Pooja Jaind34698d2017-12-28 14:15:31 +0530658 if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
659 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
660 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800661 builder.append("]");
662 return builder.toString();
663 }
664
665 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700666 * Whether the supplied properties includes the specified property.
667 *
668 * @param properties A bit field of properties.
669 * @param property The property to check properties for.
670 * @return Whether the specified property is supported.
671 */
672 public static boolean hasProperty(int properties, int property) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800673 return (properties & property) == property;
Andrew Lee2378ea72015-04-29 14:38:11 -0700674 }
675
676 /**
677 * Whether the properties of this {@code Details} includes the specified property.
678 *
679 * @param property The property to check properties for.
680 * @return Whether the specified property is supported.
681 */
682 public boolean hasProperty(int property) {
683 return hasProperty(mCallProperties, property);
684 }
685
686 /**
687 * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
688 *
689 * @param properties A property bit field.
690 * @return A human readable string representation.
691 */
692 public static String propertiesToString(int properties) {
693 StringBuilder builder = new StringBuilder();
694 builder.append("[Properties:");
695 if (hasProperty(properties, PROPERTY_CONFERENCE)) {
696 builder.append(" PROPERTY_CONFERENCE");
697 }
698 if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
699 builder.append(" PROPERTY_GENERIC_CONFERENCE");
700 }
701 if (hasProperty(properties, PROPERTY_WIFI)) {
702 builder.append(" PROPERTY_WIFI");
703 }
704 if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
705 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
706 }
707 if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
Yorke Leebe2a4a22015-06-12 10:10:55 -0700708 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
Andrew Lee2378ea72015-04-29 14:38:11 -0700709 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700710 if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
711 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
712 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700713 if (hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
Brad Ebinger15847072016-05-18 11:08:36 -0700714 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
715 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700716 if (hasProperty(properties, PROPERTY_ASSISTED_DIALING_USED)) {
Eric Erfanianec881872017-12-06 16:27:53 -0800717 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
718 }
Tyler Gunn5bd90852018-09-21 09:37:07 -0700719 if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
720 builder.append(" PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL");
721 }
Tyler Gunn80a5e1e2018-06-22 15:52:27 -0700722 if (hasProperty(properties, PROPERTY_RTT)) {
723 builder.append(" PROPERTY_RTT");
724 }
725 if (hasProperty(properties, PROPERTY_VOIP_AUDIO_MODE)) {
726 builder.append(" PROPERTY_VOIP_AUDIO_MODE");
727 }
Andrew Lee2378ea72015-04-29 14:38:11 -0700728 builder.append("]");
729 return builder.toString();
730 }
731
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800732 /** {@hide} */
Hall Liu31de23d2019-10-11 15:38:29 -0700733 @TestApi
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800734 public String getTelecomCallId() {
735 return mTelecomCallId;
736 }
737
Andrew Lee2378ea72015-04-29 14:38:11 -0700738 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700739 * @return The handle (e.g., phone number) to which the {@code Call} is currently
740 * connected.
741 */
742 public Uri getHandle() {
743 return mHandle;
744 }
745
746 /**
747 * @return The presentation requirements for the handle. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700748 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700749 */
750 public int getHandlePresentation() {
751 return mHandlePresentation;
752 }
753
754 /**
Tyler Gunnd081f042018-12-04 12:56:45 -0800755 * The display name for the caller.
756 * <p>
757 * This is the name as reported by the {@link ConnectionService} associated with this call.
Tyler Gunnd081f042018-12-04 12:56:45 -0800758 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700759 * @return The display name for the caller.
760 */
761 public String getCallerDisplayName() {
762 return mCallerDisplayName;
763 }
764
765 /**
766 * @return The presentation requirements for the caller display name. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700767 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700768 */
769 public int getCallerDisplayNamePresentation() {
770 return mCallerDisplayNamePresentation;
771 }
772
773 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700774 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
775 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700776 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700777 public PhoneAccountHandle getAccountHandle() {
778 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -0700779 }
780
781 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800782 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
783 * {@code CAPABILITY_*} constants in this class.
Ihab Awade63fadb2014-07-09 21:52:04 -0700784 */
Ihab Awad5d0410f2014-07-30 10:07:40 -0700785 public int getCallCapabilities() {
786 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700787 }
788
789 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700790 * @return A bitmask of the properties of the {@code Call}, as defined by the various
791 * {@code PROPERTY_*} constants in this class.
Andrew Lee223ad142014-08-27 16:33:08 -0700792 */
793 public int getCallProperties() {
794 return mCallProperties;
795 }
796
797 /**
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800798 * @return a bitmask of the audio routes available for the call.
799 *
800 * @hide
801 */
802 public int getSupportedAudioRoutes() {
803 return mSupportedAudioRoutes;
804 }
805
806 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700807 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
Nancy Chenf4cf77c2014-09-19 10:53:21 -0700808 * by {@link android.telecom.DisconnectCause}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700809 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700810 public DisconnectCause getDisconnectCause() {
811 return mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700812 }
813
814 /**
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700815 * Returns the time the {@link Call} connected (i.e. became active). This information is
816 * updated periodically, but user interfaces should not rely on this to display the "call
817 * time clock". For the time when the call was first added to Telecom, see
818 * {@link #getCreationTimeMillis()}.
819 *
820 * @return The time the {@link Call} connected in milliseconds since the epoch.
Ihab Awade63fadb2014-07-09 21:52:04 -0700821 */
Jay Shrauner164a0ac2015-04-14 18:16:10 -0700822 public final long getConnectTimeMillis() {
Ihab Awade63fadb2014-07-09 21:52:04 -0700823 return mConnectTimeMillis;
824 }
825
826 /**
827 * @return Information about any calling gateway the {@code Call} may be using.
828 */
829 public GatewayInfo getGatewayInfo() {
830 return mGatewayInfo;
831 }
832
Andrew Lee7a341382014-07-15 17:05:08 -0700833 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -0700834 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -0700835 */
836 public int getVideoState() {
837 return mVideoState;
838 }
839
Ihab Awad5d0410f2014-07-30 10:07:40 -0700840 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700841 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
Ihab Awad5d0410f2014-07-30 10:07:40 -0700842 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -0700843 */
844 public StatusHints getStatusHints() {
845 return mStatusHints;
846 }
847
Nancy Chen10798dc2014-08-08 14:00:25 -0700848 /**
Santos Cordon6b7f9552015-05-27 17:21:45 -0700849 * @return The extras associated with this call.
Nancy Chen10798dc2014-08-08 14:00:25 -0700850 */
851 public Bundle getExtras() {
852 return mExtras;
853 }
854
Santos Cordon6b7f9552015-05-27 17:21:45 -0700855 /**
856 * @return The extras used with the original intent to place this call.
857 */
858 public Bundle getIntentExtras() {
859 return mIntentExtras;
860 }
861
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700862 /**
863 * Returns the time when the call was first created and added to Telecom. This is the same
864 * time that is logged as the start time in the Call Log (see
865 * {@link android.provider.CallLog.Calls#DATE}). To determine when the call was connected
866 * (became active), see {@link #getConnectTimeMillis()}.
867 *
868 * @return The creation time of the call, in millis since the epoch.
869 */
870 public long getCreationTimeMillis() {
871 return mCreationTimeMillis;
872 }
873
Tyler Gunnd081f042018-12-04 12:56:45 -0800874 /**
Tyler Gunn94f8f112018-12-17 09:56:11 -0800875 * Indicates whether the call is an incoming or outgoing call.
876 * @return The call's direction.
877 */
878 public @CallDirection int getCallDirection() {
879 return mCallDirection;
880 }
881
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700882 /**
883 * Gets the verification status for the phone number of an incoming call as identified in
884 * ATIS-1000082.
885 * @return the verification status.
886 */
887 public @Connection.VerificationStatus int getCallerNumberVerificationStatus() {
888 return mCallerNumberVerificationStatus;
889 }
890
Ihab Awade63fadb2014-07-09 21:52:04 -0700891 @Override
892 public boolean equals(Object o) {
893 if (o instanceof Details) {
894 Details d = (Details) o;
895 return
896 Objects.equals(mHandle, d.mHandle) &&
897 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
898 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
899 Objects.equals(mCallerDisplayNamePresentation,
900 d.mCallerDisplayNamePresentation) &&
Evan Charlton8c8a0622014-07-20 12:31:00 -0700901 Objects.equals(mAccountHandle, d.mAccountHandle) &&
Ihab Awad5d0410f2014-07-30 10:07:40 -0700902 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Andrew Lee223ad142014-08-27 16:33:08 -0700903 Objects.equals(mCallProperties, d.mCallProperties) &&
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700904 Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
Ihab Awade63fadb2014-07-09 21:52:04 -0700905 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Andrew Lee85f5d422014-07-11 17:22:03 -0700906 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Evan Charlton5b49ade2014-07-15 17:03:20 -0700907 Objects.equals(mVideoState, d.mVideoState) &&
Nancy Chen10798dc2014-08-08 14:00:25 -0700908 Objects.equals(mStatusHints, d.mStatusHints) &&
Tyler Gunn1e9bfc62015-08-19 11:18:58 -0700909 areBundlesEqual(mExtras, d.mExtras) &&
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700910 areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
Tyler Gunnd081f042018-12-04 12:56:45 -0800911 Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis) &&
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700912 Objects.equals(mCallDirection, d.mCallDirection) &&
913 Objects.equals(mCallerNumberVerificationStatus,
914 d.mCallerNumberVerificationStatus);
Ihab Awade63fadb2014-07-09 21:52:04 -0700915 }
916 return false;
917 }
918
919 @Override
920 public int hashCode() {
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700921 return Objects.hash(mHandle,
922 mHandlePresentation,
923 mCallerDisplayName,
924 mCallerDisplayNamePresentation,
925 mAccountHandle,
926 mCallCapabilities,
927 mCallProperties,
928 mDisconnectCause,
929 mConnectTimeMillis,
930 mGatewayInfo,
931 mVideoState,
932 mStatusHints,
933 mExtras,
934 mIntentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -0800935 mCreationTimeMillis,
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700936 mCallDirection,
937 mCallerNumberVerificationStatus);
Ihab Awade63fadb2014-07-09 21:52:04 -0700938 }
939
940 /** {@hide} */
941 public Details(
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800942 String telecomCallId,
Ihab Awade63fadb2014-07-09 21:52:04 -0700943 Uri handle,
944 int handlePresentation,
945 String callerDisplayName,
946 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -0700947 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -0700948 int capabilities,
Andrew Lee223ad142014-08-27 16:33:08 -0700949 int properties,
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700950 DisconnectCause disconnectCause,
Ihab Awade63fadb2014-07-09 21:52:04 -0700951 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -0700952 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -0700953 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -0700954 StatusHints statusHints,
Santos Cordon6b7f9552015-05-27 17:21:45 -0700955 Bundle extras,
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700956 Bundle intentExtras,
Tyler Gunnd081f042018-12-04 12:56:45 -0800957 long creationTimeMillis,
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700958 int callDirection,
959 int callerNumberVerificationStatus) {
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800960 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700961 mHandle = handle;
962 mHandlePresentation = handlePresentation;
963 mCallerDisplayName = callerDisplayName;
964 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700965 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700966 mCallCapabilities = capabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700967 mCallProperties = properties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700968 mDisconnectCause = disconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700969 mConnectTimeMillis = connectTimeMillis;
970 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700971 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700972 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700973 mExtras = extras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700974 mIntentExtras = intentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700975 mCreationTimeMillis = creationTimeMillis;
Tyler Gunn94f8f112018-12-17 09:56:11 -0800976 mCallDirection = callDirection;
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700977 mCallerNumberVerificationStatus = callerNumberVerificationStatus;
Ihab Awade63fadb2014-07-09 21:52:04 -0700978 }
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800979
980 /** {@hide} */
981 public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
982 return new Details(
983 parcelableCall.getId(),
984 parcelableCall.getHandle(),
985 parcelableCall.getHandlePresentation(),
986 parcelableCall.getCallerDisplayName(),
987 parcelableCall.getCallerDisplayNamePresentation(),
988 parcelableCall.getAccountHandle(),
989 parcelableCall.getCapabilities(),
990 parcelableCall.getProperties(),
991 parcelableCall.getDisconnectCause(),
992 parcelableCall.getConnectTimeMillis(),
993 parcelableCall.getGatewayInfo(),
994 parcelableCall.getVideoState(),
995 parcelableCall.getStatusHints(),
996 parcelableCall.getExtras(),
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700997 parcelableCall.getIntentExtras(),
Tyler Gunnd081f042018-12-04 12:56:45 -0800998 parcelableCall.getCreationTimeMillis(),
Tyler Gunnd57d76c2019-09-24 14:53:23 -0700999 parcelableCall.getCallDirection(),
1000 parcelableCall.getCallerNumberVerificationStatus());
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001001 }
Santos Cordon3c20d632016-02-25 16:12:35 -08001002
1003 @Override
1004 public String toString() {
1005 StringBuilder sb = new StringBuilder();
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001006 sb.append("[id: ");
1007 sb.append(mTelecomCallId);
1008 sb.append(", pa: ");
Santos Cordon3c20d632016-02-25 16:12:35 -08001009 sb.append(mAccountHandle);
1010 sb.append(", hdl: ");
Tyler Gunn3cd820f2018-11-30 14:21:18 -08001011 sb.append(Log.piiHandle(mHandle));
1012 sb.append(", hdlPres: ");
1013 sb.append(mHandlePresentation);
1014 sb.append(", videoState: ");
1015 sb.append(VideoProfile.videoStateToString(mVideoState));
Santos Cordon3c20d632016-02-25 16:12:35 -08001016 sb.append(", caps: ");
1017 sb.append(capabilitiesToString(mCallCapabilities));
1018 sb.append(", props: ");
Tyler Gunn720c6642016-03-22 09:02:47 -07001019 sb.append(propertiesToString(mCallProperties));
Santos Cordon3c20d632016-02-25 16:12:35 -08001020 sb.append("]");
1021 return sb.toString();
1022 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001023 }
1024
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001025 /**
1026 * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
1027 * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
1028 * implementation.
1029 * <p>
1030 * You can handle these callbacks by extending the {@link Callback} class and overriding the
1031 * callbacks that your {@link InCallService} is interested in. The callback methods include the
1032 * {@link Call} for which the callback applies, allowing reuse of a single instance of your
1033 * {@link Callback} implementation, if desired.
1034 * <p>
1035 * Use {@link Call#registerCallback(Callback)} to register your callback(s). Ensure
1036 * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
1037 * (typically in {@link InCallService#onCallRemoved(Call)}).
1038 * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
1039 * reach your implementation of {@link Callback}, so it is important to register your callback
1040 * as soon as your {@link InCallService} is notified of a new call via
1041 * {@link InCallService#onCallAdded(Call)}.
1042 */
Andrew Leeda80c872015-04-15 14:09:50 -07001043 public static abstract class Callback {
Ihab Awade63fadb2014-07-09 21:52:04 -07001044 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001045 * @hide
1046 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001047 @IntDef(prefix = { "HANDOVER_" },
1048 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
Tyler Gunn5c60d712018-03-16 09:53:44 -07001049 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
Tyler Gunn9d127732018-03-02 15:45:51 -08001050 HANDOVER_FAILURE_UNKNOWN})
Sanket Padawea8eddd42017-11-03 11:07:35 -07001051 @Retention(RetentionPolicy.SOURCE)
1052 public @interface HandoverFailureErrors {}
1053
1054 /**
1055 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
Tyler Gunn9d127732018-03-02 15:45:51 -08001056 * to handover the call to rejects the handover request.
1057 * <p>
1058 * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
1059 * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
1060 * {@code null} {@link Connection} from
1061 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1062 * ConnectionRequest)}.
1063 * <p>
1064 * For more information on call handovers, see
1065 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001066 */
1067 public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
1068
1069 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001070 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1071 * is initiated but the source or destination app does not support handover.
1072 * <p>
1073 * Will be returned when a handover is requested via
1074 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
1075 * {@link PhoneAccountHandle} does not declare
1076 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}. May also be returned when a handover is
1077 * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
1078 * {@link Details#getAccountHandle()}) does not declare
1079 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
1080 * <p>
1081 * For more information on call handovers, see
1082 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001083 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001084 public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001085
1086 /**
Tyler Gunn9d127732018-03-02 15:45:51 -08001087 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
1088 * user rejects the handover request.
1089 * <p>
1090 * For more information on call handovers, see
1091 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001092 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001093 public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001094
Sanket Padawe85291f62017-12-01 13:59:27 -08001095 /**
1096 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
1097 * is ongoing emergency call.
Tyler Gunn9d127732018-03-02 15:45:51 -08001098 * <p>
1099 * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
1100 * called on an emergency call, or if any other call is an emergency call.
1101 * <p>
1102 * Handovers are not permitted while there are ongoing emergency calls.
1103 * <p>
1104 * For more information on call handovers, see
1105 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawe85291f62017-12-01 13:59:27 -08001106 */
Tyler Gunn5c60d712018-03-16 09:53:44 -07001107 public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
Sanket Padawe85291f62017-12-01 13:59:27 -08001108
Tyler Gunn9d127732018-03-02 15:45:51 -08001109 /**
1110 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1111 * fails for an unknown reason.
1112 * <p>
1113 * For more information on call handovers, see
1114 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
1115 */
1116 public static final int HANDOVER_FAILURE_UNKNOWN = 5;
Sanket Padawea8eddd42017-11-03 11:07:35 -07001117
1118 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001119 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
1120 *
Ihab Awade63fadb2014-07-09 21:52:04 -07001121 * @param call The {@code Call} invoking this method.
1122 * @param state The new state of the {@code Call}.
1123 */
1124 public void onStateChanged(Call call, int state) {}
1125
1126 /**
1127 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
1128 *
1129 * @param call The {@code Call} invoking this method.
1130 * @param parent The new parent of the {@code Call}.
1131 */
1132 public void onParentChanged(Call call, Call parent) {}
1133
1134 /**
1135 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
1136 *
1137 * @param call The {@code Call} invoking this method.
1138 * @param children The new children of the {@code Call}.
1139 */
1140 public void onChildrenChanged(Call call, List<Call> children) {}
1141
1142 /**
1143 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
1144 *
1145 * @param call The {@code Call} invoking this method.
1146 * @param details A {@code Details} object describing the {@code Call}.
1147 */
1148 public void onDetailsChanged(Call call, Details details) {}
1149
1150 /**
1151 * Invoked when the text messages that can be used as responses to the incoming
1152 * {@code Call} are loaded from the relevant database.
1153 * See {@link #getCannedTextResponses()}.
1154 *
1155 * @param call The {@code Call} invoking this method.
1156 * @param cannedTextResponses The text messages useable as responses.
1157 */
1158 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
1159
1160 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001161 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
1162 * character. This causes the post-dial signals to stop pending user confirmation. An
1163 * implementation should present this choice to the user and invoke
1164 * {@link #postDialContinue(boolean)} when the user makes the choice.
1165 *
1166 * @param call The {@code Call} invoking this method.
1167 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
1168 */
1169 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
1170
1171 /**
Andrew Lee50aca232014-07-22 16:41:54 -07001172 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -07001173 *
1174 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -07001175 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001176 */
Andrew Lee50aca232014-07-22 16:41:54 -07001177 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -07001178
1179 /**
1180 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
1181 * up their UI for the {@code Call} in response to state transitions. Specifically,
1182 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
1183 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
1184 * clients should wait for this method to be invoked.
1185 *
1186 * @param call The {@code Call} being destroyed.
1187 */
1188 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001189
1190 /**
1191 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
1192 * conferenced.
1193 *
1194 * @param call The {@code Call} being updated.
1195 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
1196 * conferenced.
1197 */
1198 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001199
1200 /**
Tyler Gunn5567d742019-10-31 13:04:37 -07001201 * Invoked when a {@link Call} receives an event from its associated {@link Connection} or
1202 * {@link Conference}.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001203 * <p>
1204 * Where possible, the Call should make an attempt to handle {@link Connection} events which
1205 * are part of the {@code android.telecom.*} namespace. The Call should ignore any events
1206 * it does not wish to handle. Unexpected events should be handled gracefully, as it is
1207 * possible that a {@link ConnectionService} has defined its own Connection events which a
1208 * Call is not aware of.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001209 * <p>
Tyler Gunn5567d742019-10-31 13:04:37 -07001210 * See {@link Connection#sendConnectionEvent(String, Bundle)},
1211 * {@link Conference#sendConferenceEvent(String, Bundle)}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001212 *
1213 * @param call The {@code Call} receiving the event.
1214 * @param event The event.
1215 * @param extras Extras associated with the connection event.
1216 */
1217 public void onConnectionEvent(Call call, String event, Bundle extras) {}
Hall Liu95d55872017-01-25 17:12:49 -08001218
1219 /**
1220 * Invoked when the RTT mode changes for this call.
1221 * @param call The call whose RTT mode has changed.
1222 * @param mode the new RTT mode, one of
1223 * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
1224 * or {@link RttCall#RTT_MODE_VCO}
1225 */
1226 public void onRttModeChanged(Call call, int mode) {}
1227
1228 /**
1229 * Invoked when the call's RTT status changes, either from off to on or from on to off.
1230 * @param call The call whose RTT status has changed.
1231 * @param enabled whether RTT is now enabled or disabled
1232 * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
1233 * on, null otherwise.
1234 */
1235 public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
1236
1237 /**
1238 * Invoked when the remote end of the connection has requested that an RTT communication
1239 * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
1240 * with the same ID that this method is invoked with.
1241 * @param call The call which the RTT request was placed on
1242 * @param id The ID of the request.
1243 */
1244 public void onRttRequest(Call call, int id) {}
Hall Liu57006aa2017-02-06 10:49:48 -08001245
1246 /**
1247 * Invoked when the RTT session failed to initiate for some reason, including rejection
1248 * by the remote party.
1249 * @param call The call which the RTT initiation failure occurred on.
1250 * @param reason One of the status codes defined in
1251 * {@link android.telecom.Connection.RttModifyStatus}, with the exception of
1252 * {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
1253 */
1254 public void onRttInitiationFailure(Call call, int reason) {}
Sanket Padawea8eddd42017-11-03 11:07:35 -07001255
1256 /**
1257 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1258 * has completed successfully.
Tyler Gunn9d127732018-03-02 15:45:51 -08001259 * <p>
1260 * For a full discussion of the handover process and the APIs involved, see
1261 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1262 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001263 * @param call The call which had initiated handover.
1264 */
1265 public void onHandoverComplete(Call call) {}
1266
1267 /**
1268 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1269 * has failed.
Tyler Gunn9d127732018-03-02 15:45:51 -08001270 * <p>
1271 * For a full discussion of the handover process and the APIs involved, see
1272 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1273 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001274 * @param call The call which had initiated handover.
Tyler Gunn9d127732018-03-02 15:45:51 -08001275 * @param failureReason Error reason for failure.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001276 */
1277 public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
Hall Liu95d55872017-01-25 17:12:49 -08001278 }
1279
1280 /**
1281 * A class that holds the state that describes the state of the RTT channel to the remote
1282 * party, if it is active.
1283 */
1284 public static final class RttCall {
Hall Liu07094df2017-02-28 15:17:44 -08001285 /** @hide */
Hall Liu95d55872017-01-25 17:12:49 -08001286 @Retention(RetentionPolicy.SOURCE)
1287 @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
1288 public @interface RttAudioMode {}
1289
1290 /**
1291 * For metrics use. Default value in the proto.
1292 * @hide
1293 */
1294 public static final int RTT_MODE_INVALID = 0;
1295
1296 /**
1297 * Indicates that there should be a bidirectional audio stream between the two parties
1298 * on the call.
1299 */
1300 public static final int RTT_MODE_FULL = 1;
1301
1302 /**
1303 * Indicates that the local user should be able to hear the audio stream from the remote
1304 * user, but not vice versa. Equivalent to muting the microphone.
1305 */
1306 public static final int RTT_MODE_HCO = 2;
1307
1308 /**
1309 * Indicates that the remote user should be able to hear the audio stream from the local
1310 * user, but not vice versa. Equivalent to setting the volume to zero.
1311 */
1312 public static final int RTT_MODE_VCO = 3;
1313
1314 private static final int READ_BUFFER_SIZE = 1000;
1315
1316 private InputStreamReader mReceiveStream;
1317 private OutputStreamWriter mTransmitStream;
1318 private int mRttMode;
1319 private final InCallAdapter mInCallAdapter;
Hall Liu57006aa2017-02-06 10:49:48 -08001320 private final String mTelecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001321 private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
1322
1323 /**
1324 * @hide
1325 */
Hall Liu57006aa2017-02-06 10:49:48 -08001326 public RttCall(String telecomCallId, InputStreamReader receiveStream,
1327 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
1328 mTelecomCallId = telecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001329 mReceiveStream = receiveStream;
1330 mTransmitStream = transmitStream;
1331 mRttMode = mode;
1332 mInCallAdapter = inCallAdapter;
1333 }
1334
1335 /**
1336 * Returns the current RTT audio mode.
1337 * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
1338 * {@link #RTT_MODE_HCO}.
1339 */
1340 public int getRttAudioMode() {
1341 return mRttMode;
1342 }
1343
1344 /**
1345 * Sets the RTT audio mode. The requested mode change will be communicated through
1346 * {@link Callback#onRttModeChanged(Call, int)}.
1347 * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
1348 * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
1349 */
1350 public void setRttMode(@RttAudioMode int mode) {
Hall Liu57006aa2017-02-06 10:49:48 -08001351 mInCallAdapter.setRttMode(mTelecomCallId, mode);
Hall Liu95d55872017-01-25 17:12:49 -08001352 }
1353
1354 /**
1355 * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
1356 * RTT transmits text in real-time, this method should be called once for each character
1357 * the user enters into the device.
1358 *
1359 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1360 * lead to interleaved text.
1361 * @param input The message to send to the remote user.
1362 */
1363 public void write(String input) throws IOException {
1364 mTransmitStream.write(input);
1365 mTransmitStream.flush();
1366 }
1367
1368 /**
1369 * Reads a string from the remote user, blocking if there is no data available. Returns
1370 * {@code null} if the RTT conversation has been terminated and there is no further data
1371 * to read.
1372 *
1373 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1374 * lead to interleaved text.
1375 * @return A string containing text sent by the remote user, or {@code null} if the
1376 * conversation has been terminated or if there was an error while reading.
1377 */
Hall Liub1c8a772017-07-17 17:04:41 -07001378 public String read() {
1379 try {
1380 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1381 if (numRead < 0) {
1382 return null;
1383 }
1384 return new String(mReadBuffer, 0, numRead);
1385 } catch (IOException e) {
1386 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
Jeff Sharkey90396362017-06-12 16:26:53 -06001387 return null;
Hall Liuffa4a812017-03-02 16:11:00 -08001388 }
Hall Liuffa4a812017-03-02 16:11:00 -08001389 }
1390
1391 /**
1392 * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
1393 * be read.
1394 * @return A string containing text entered by the user, or {@code null} if the user has
1395 * not entered any new text yet.
1396 */
1397 public String readImmediately() throws IOException {
1398 if (mReceiveStream.ready()) {
Hall Liub1c8a772017-07-17 17:04:41 -07001399 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1400 if (numRead < 0) {
1401 return null;
1402 }
1403 return new String(mReadBuffer, 0, numRead);
Hall Liuffa4a812017-03-02 16:11:00 -08001404 } else {
Hall Liu95d55872017-01-25 17:12:49 -08001405 return null;
1406 }
1407 }
Hall Liue9041242018-02-09 16:40:03 -08001408
1409 /**
1410 * Closes the underlying file descriptors
1411 * @hide
1412 */
1413 public void close() {
1414 try {
1415 mReceiveStream.close();
1416 } catch (IOException e) {
1417 // ignore
1418 }
1419 try {
1420 mTransmitStream.close();
1421 } catch (IOException e) {
1422 // ignore
1423 }
1424 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001425 }
1426
Andrew Leeda80c872015-04-15 14:09:50 -07001427 /**
1428 * @deprecated Use {@code Call.Callback} instead.
1429 * @hide
1430 */
1431 @Deprecated
1432 @SystemApi
1433 public static abstract class Listener extends Callback { }
1434
Ihab Awade63fadb2014-07-09 21:52:04 -07001435 private final Phone mPhone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001436 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001437 private final InCallAdapter mInCallAdapter;
Santos Cordon823fd3c2014-08-07 18:35:18 -07001438 private final List<String> mChildrenIds = new ArrayList<>();
Ihab Awade63fadb2014-07-09 21:52:04 -07001439 private final List<Call> mChildren = new ArrayList<>();
1440 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Andrew Lee011728f2015-04-23 15:47:06 -07001441 private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001442 private final List<Call> mConferenceableCalls = new ArrayList<>();
1443 private final List<Call> mUnmodifiableConferenceableCalls =
1444 Collections.unmodifiableList(mConferenceableCalls);
1445
Santos Cordon823fd3c2014-08-07 18:35:18 -07001446 private boolean mChildrenCached;
1447 private String mParentId = null;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001448 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -07001449 private List<String> mCannedTextResponses = null;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001450 private String mCallingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001451 private int mTargetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07001452 private String mRemainingPostDialSequence;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001453 private VideoCallImpl mVideoCallImpl;
Hall Liu95d55872017-01-25 17:12:49 -08001454 private RttCall mRttCall;
Ihab Awade63fadb2014-07-09 21:52:04 -07001455 private Details mDetails;
Tyler Gunndee56a82016-03-23 16:06:34 -07001456 private Bundle mExtras;
Ihab Awade63fadb2014-07-09 21:52:04 -07001457
1458 /**
1459 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
1460 *
1461 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
1462 * remaining or this {@code Call} is not in a post-dial state.
1463 */
1464 public String getRemainingPostDialSequence() {
1465 return mRemainingPostDialSequence;
1466 }
1467
1468 /**
1469 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001470 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -07001471 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001472 public void answer(@VideoProfile.VideoState int videoState) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001473 mInCallAdapter.answerCall(mTelecomCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -07001474 }
1475
1476 /**
Pooja Jaind34698d2017-12-28 14:15:31 +05301477 * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
1478 *
1479 * @param address The address to which the call will be deflected.
1480 */
1481 public void deflect(Uri address) {
1482 mInCallAdapter.deflectCall(mTelecomCallId, address);
1483 }
1484
1485 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001486 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
1487 *
1488 * @param rejectWithMessage Whether to reject with a text message.
1489 * @param textMessage An optional text message with which to respond.
1490 */
1491 public void reject(boolean rejectWithMessage, String textMessage) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001492 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
Ihab Awade63fadb2014-07-09 21:52:04 -07001493 }
1494
1495 /**
1496 * Instructs this {@code Call} to disconnect.
1497 */
1498 public void disconnect() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001499 mInCallAdapter.disconnectCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001500 }
1501
1502 /**
1503 * Instructs this {@code Call} to go on hold.
1504 */
1505 public void hold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001506 mInCallAdapter.holdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001507 }
1508
1509 /**
1510 * Instructs this {@link #STATE_HOLDING} call to release from hold.
1511 */
1512 public void unhold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001513 mInCallAdapter.unholdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001514 }
1515
1516 /**
Hall Liu6dfa2492019-10-01 17:20:39 -07001517 * Instructs Telecom to put the call into the background audio processing state.
1518 *
1519 * This method can be called either when the call is in {@link #STATE_RINGING} or
1520 * {@link #STATE_ACTIVE}. After Telecom acknowledges the request by setting the call's state to
1521 * {@link #STATE_AUDIO_PROCESSING}, your app may setup the audio paths with the audio stack in
1522 * order to capture and play audio on the call stream.
1523 *
1524 * This method can only be called by the default dialer app.
1525 * @hide
1526 */
1527 @SystemApi
1528 @TestApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001529 public void enterBackgroundAudioProcessing() {
1530 if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
1531 throw new IllegalStateException("Call must be active or ringing");
1532 }
1533 mInCallAdapter.enterBackgroundAudioProcessing(mTelecomCallId);
1534 }
1535
1536 /**
1537 * Instructs Telecom to come out of the background audio processing state requested by
1538 * {@link #enterBackgroundAudioProcessing()} or from the call screening service.
1539 *
1540 * This method can only be called when the call is in {@link #STATE_AUDIO_PROCESSING}.
1541 *
1542 * @param shouldRing If true, Telecom will put the call into the
1543 * {@link #STATE_SIMULATED_RINGING} state and notify other apps that there is
1544 * a ringing call. Otherwise, the call will go into {@link #STATE_ACTIVE}
1545 * immediately.
1546 * @hide
1547 */
1548 @SystemApi
1549 @TestApi
Hall Liu6dfa2492019-10-01 17:20:39 -07001550 public void exitBackgroundAudioProcessing(boolean shouldRing) {
1551 if (mState != STATE_AUDIO_PROCESSING) {
1552 throw new IllegalStateException("Call must in the audio processing state");
1553 }
1554 mInCallAdapter.exitBackgroundAudioProcessing(mTelecomCallId, shouldRing);
1555 }
1556
1557 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001558 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
1559 *
1560 * Any other currently playing DTMF tone in the specified call is immediately stopped.
1561 *
1562 * @param digit A character representing the DTMF digit for which to play the tone. This
1563 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
1564 */
1565 public void playDtmfTone(char digit) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001566 mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
Ihab Awade63fadb2014-07-09 21:52:04 -07001567 }
1568
1569 /**
1570 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
1571 * currently playing.
1572 *
1573 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
1574 * currently playing, this method will do nothing.
1575 */
1576 public void stopDtmfTone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001577 mInCallAdapter.stopDtmfTone(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001578 }
1579
1580 /**
1581 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
1582 *
1583 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
1584 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -07001585 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001586 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -07001587 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
1588 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001589 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
Andrew Leeda80c872015-04-15 14:09:50 -07001590 * {@code Call} will pause playing the tones and notify callbacks via
1591 * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
Ihab Awade63fadb2014-07-09 21:52:04 -07001592 * should display to the user an indication of this state and an affordance to continue
1593 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
1594 * app should invoke the {@link #postDialContinue(boolean)} method.
1595 *
1596 * @param proceed Whether or not to continue with the post-dial sequence.
1597 */
1598 public void postDialContinue(boolean proceed) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001599 mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
Ihab Awade63fadb2014-07-09 21:52:04 -07001600 }
1601
1602 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -07001603 * Notifies this {@code Call} that an account has been selected and to proceed with placing
Nancy Chen36c62f32014-10-21 18:36:39 -07001604 * an outgoing call. Optionally sets this account as the default account.
Nancy Chen5da0fd52014-07-08 14:16:17 -07001605 */
Nancy Chen36c62f32014-10-21 18:36:39 -07001606 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
1607 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
Nancy Chen5da0fd52014-07-08 14:16:17 -07001608
1609 }
1610
1611 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001612 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001613 *
1614 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -07001615 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001616 public void conference(Call callToConferenceWith) {
1617 if (callToConferenceWith != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001618 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001619 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001620 }
1621
1622 /**
1623 * Instructs this {@code Call} to split from any conference call with which it may be
1624 * connected.
1625 */
1626 public void splitFromConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001627 mInCallAdapter.splitFromConference(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001628 }
1629
1630 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001631 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001632 */
1633 public void mergeConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001634 mInCallAdapter.mergeConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001635 }
1636
1637 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001638 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001639 */
1640 public void swapConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001641 mInCallAdapter.swapConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001642 }
1643
1644 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001645 * Initiates a request to the {@link ConnectionService} to pull an external call to the local
1646 * device.
1647 * <p>
1648 * Calls to this method are ignored if the call does not have the
1649 * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
1650 * <p>
1651 * An {@link InCallService} will only see calls which support this method if it has the
1652 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
1653 * in its manifest.
1654 */
1655 public void pullExternalCall() {
1656 // If this isn't an external call, ignore the request.
1657 if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
1658 return;
1659 }
1660
1661 mInCallAdapter.pullExternalCall(mTelecomCallId);
1662 }
1663
1664 /**
1665 * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
1666 * the {@link ConnectionService}.
1667 * <p>
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001668 * Call events are used to communicate point in time information from an {@link InCallService}
1669 * to a {@link ConnectionService}. A {@link ConnectionService} implementation could define
1670 * events which enable the {@link InCallService}, for example, toggle a unique feature of the
1671 * {@link ConnectionService}.
1672 * <p>
1673 * A {@link ConnectionService} can communicate to the {@link InCallService} using
1674 * {@link Connection#sendConnectionEvent(String, Bundle)}.
1675 * <p>
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001676 * Events are exposed to {@link ConnectionService} implementations via
1677 * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
1678 * <p>
1679 * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001680 * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
1681 * ignore some events altogether.
1682 * <p>
1683 * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
1684 * conflicts between {@link InCallService} implementations. Further, {@link InCallService}
1685 * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
1686 * they define their own event types in this namespace. When defining a custom event type,
1687 * ensure the contents of the extras {@link Bundle} is clearly defined. Extra keys for this
1688 * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
1689 * <p>
1690 * When defining events and the associated extras, it is important to keep their behavior
1691 * consistent when the associated {@link InCallService} is updated. Support for deprecated
1692 * events/extras should me maintained to ensure backwards compatibility with older
1693 * {@link ConnectionService} implementations which were built to support the older behavior.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001694 *
1695 * @param event The connection event.
1696 * @param extras Bundle containing extra information associated with the event.
1697 */
1698 public void sendCallEvent(String event, Bundle extras) {
Sanket Padawef6a9e5b2018-01-05 14:26:16 -08001699 mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001700 }
1701
1702 /**
Hall Liu95d55872017-01-25 17:12:49 -08001703 * Sends an RTT upgrade request to the remote end of the connection. Success is not
1704 * guaranteed, and notification of success will be via the
1705 * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1706 */
1707 public void sendRttRequest() {
Hall Liu57006aa2017-02-06 10:49:48 -08001708 mInCallAdapter.sendRttRequest(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001709 }
1710
1711 /**
1712 * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
1713 * callback.
1714 * The ID used here should be the same as the ID that was received via the callback.
1715 * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
1716 * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
1717 */
1718 public void respondToRttRequest(int id, boolean accept) {
Hall Liu57006aa2017-02-06 10:49:48 -08001719 mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
Hall Liu95d55872017-01-25 17:12:49 -08001720 }
1721
1722 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001723 * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
1724 * by {@code toHandle}. The videoState specified indicates the desired video state after the
1725 * handover.
1726 * <p>
Tyler Gunn9d127732018-03-02 15:45:51 -08001727 * A call handover is the process where an ongoing call is transferred from one app (i.e.
1728 * {@link ConnectionService} to another app. The user could, for example, choose to continue a
1729 * mobile network call in a video calling app. The mobile network call via the Telephony stack
1730 * is referred to as the source of the handover, and the video calling app is referred to as the
1731 * destination.
1732 * <p>
1733 * When considering a handover scenario the device this method is called on is considered the
1734 * <em>initiating</em> device (since the user initiates the handover from this device), and the
1735 * other device is considered the <em>receiving</em> device.
1736 * <p>
1737 * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
1738 * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
1739 * and invoke
1740 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1741 * ConnectionRequest)} to inform the destination app that a request has been made to handover a
1742 * call to it. The app returns an instance of {@link Connection} to represent the handover call
1743 * At this point the app should display UI to indicate to the user that a call
1744 * handover is in process.
1745 * <p>
1746 * The destination app is responsible for communicating the handover request from the
1747 * <em>initiating</em> device to the <em>receiving</em> device.
1748 * <p>
1749 * When the app on the <em>receiving</em> device receives the handover request, it calls
1750 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
1751 * process from the <em>initiating</em> device to the <em>receiving</em> device. At this point
1752 * the destination app on the <em>receiving</em> device should show UI to allow the user to
1753 * choose whether they want to continue their call in the destination app.
1754 * <p>
1755 * When the destination app on the <em>receiving</em> device calls
1756 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
1757 * {@link ConnectionService} and call
1758 * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
1759 * ConnectionRequest)} to inform it of the handover request. The app returns an instance of
1760 * {@link Connection} to represent the handover call.
1761 * <p>
1762 * If the user of the <em>receiving</em> device accepts the handover, the app calls
1763 * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
1764 * original call. If the user rejects the handover, the app calls
1765 * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
1766 * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
1767 * <p>
1768 * Telecom will only allow handovers from {@link PhoneAccount}s which declare
1769 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}. Similarly, the {@link PhoneAccount}
1770 * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
1771 * <p>
1772 * Errors in the handover process are reported to the {@link InCallService} via
1773 * {@link Callback#onHandoverFailed(Call, int)}. Errors in the handover process are reported to
1774 * the involved {@link ConnectionService}s via
1775 * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001776 *
1777 * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
1778 * this call to.
Tyler Gunn9d127732018-03-02 15:45:51 -08001779 * @param videoState Indicates the video state desired after the handover (see the
1780 * {@code STATE_*} constants defined in {@link VideoProfile}).
Sanket Padawea8eddd42017-11-03 11:07:35 -07001781 * @param extras Bundle containing extra information to be passed to the
1782 * {@link ConnectionService}
1783 */
Tyler Gunn9d127732018-03-02 15:45:51 -08001784 public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
1785 Bundle extras) {
Sanket Padawea8eddd42017-11-03 11:07:35 -07001786 mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
1787 }
1788
1789 /**
Hall Liu95d55872017-01-25 17:12:49 -08001790 * Terminate the RTT session on this call. The resulting state change will be notified via
1791 * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1792 */
1793 public void stopRtt() {
Hall Liu57006aa2017-02-06 10:49:48 -08001794 mInCallAdapter.stopRtt(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001795 }
1796
1797 /**
Tyler Gunndee56a82016-03-23 16:06:34 -07001798 * Adds some extras to this {@link Call}. Existing keys are replaced and new ones are
1799 * added.
1800 * <p>
1801 * No assumptions should be made as to how an In-Call UI or service will handle these
1802 * extras. Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
1803 *
1804 * @param extras The extras to add.
1805 */
1806 public final void putExtras(Bundle extras) {
1807 if (extras == null) {
1808 return;
1809 }
1810
1811 if (mExtras == null) {
1812 mExtras = new Bundle();
1813 }
1814 mExtras.putAll(extras);
1815 mInCallAdapter.putExtras(mTelecomCallId, extras);
1816 }
1817
1818 /**
1819 * Adds a boolean extra to this {@link Call}.
1820 *
1821 * @param key The extra key.
1822 * @param value The value.
1823 * @hide
1824 */
1825 public final void putExtra(String key, boolean value) {
1826 if (mExtras == null) {
1827 mExtras = new Bundle();
1828 }
1829 mExtras.putBoolean(key, value);
1830 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1831 }
1832
1833 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001834 * Adds an integer extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001835 *
1836 * @param key The extra key.
1837 * @param value The value.
1838 * @hide
1839 */
1840 public final void putExtra(String key, int value) {
1841 if (mExtras == null) {
1842 mExtras = new Bundle();
1843 }
1844 mExtras.putInt(key, value);
1845 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1846 }
1847
1848 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001849 * Adds a string extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001850 *
1851 * @param key The extra key.
1852 * @param value The value.
1853 * @hide
1854 */
1855 public final void putExtra(String key, String value) {
1856 if (mExtras == null) {
1857 mExtras = new Bundle();
1858 }
1859 mExtras.putString(key, value);
1860 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1861 }
1862
1863 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001864 * Removes extras from this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001865 *
1866 * @param keys The keys of the extras to remove.
1867 */
1868 public final void removeExtras(List<String> keys) {
1869 if (mExtras != null) {
1870 for (String key : keys) {
1871 mExtras.remove(key);
1872 }
1873 if (mExtras.size() == 0) {
1874 mExtras = null;
1875 }
1876 }
1877 mInCallAdapter.removeExtras(mTelecomCallId, keys);
1878 }
1879
1880 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001881 * Removes extras from this {@link Call}.
1882 *
1883 * @param keys The keys of the extras to remove.
1884 */
1885 public final void removeExtras(String ... keys) {
1886 removeExtras(Arrays.asList(keys));
1887 }
1888
1889 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001890 * Obtains the parent of this {@code Call} in a conference, if any.
1891 *
1892 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
1893 * child of any conference {@code Call}s.
1894 */
1895 public Call getParent() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001896 if (mParentId != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001897 return mPhone.internalGetCallByTelecomId(mParentId);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001898 }
1899 return null;
Ihab Awade63fadb2014-07-09 21:52:04 -07001900 }
1901
1902 /**
1903 * Obtains the children of this conference {@code Call}, if any.
1904 *
1905 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
1906 * {@code List} otherwise.
1907 */
1908 public List<Call> getChildren() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001909 if (!mChildrenCached) {
1910 mChildrenCached = true;
1911 mChildren.clear();
1912
1913 for(String id : mChildrenIds) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001914 Call call = mPhone.internalGetCallByTelecomId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001915 if (call == null) {
1916 // At least one child was still not found, so do not save true for "cached"
1917 mChildrenCached = false;
1918 } else {
1919 mChildren.add(call);
1920 }
1921 }
1922 }
1923
Ihab Awade63fadb2014-07-09 21:52:04 -07001924 return mUnmodifiableChildren;
1925 }
1926
1927 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001928 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
1929 *
1930 * @return The list of conferenceable {@code Call}s.
1931 */
1932 public List<Call> getConferenceableCalls() {
1933 return mUnmodifiableConferenceableCalls;
1934 }
1935
1936 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001937 * Obtains the state of this {@code Call}.
1938 *
1939 * @return A state value, chosen from the {@code STATE_*} constants.
1940 */
1941 public int getState() {
1942 return mState;
1943 }
1944
1945 /**
1946 * Obtains a list of canned, pre-configured message responses to present to the user as
1947 * ways of rejecting this {@code Call} using via a text message.
1948 *
1949 * @see #reject(boolean, String)
1950 *
1951 * @return A list of canned text message responses.
1952 */
1953 public List<String> getCannedTextResponses() {
1954 return mCannedTextResponses;
1955 }
1956
1957 /**
1958 * Obtains an object that can be used to display video from this {@code Call}.
1959 *
Andrew Lee50aca232014-07-22 16:41:54 -07001960 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001961 */
Andrew Lee50aca232014-07-22 16:41:54 -07001962 public InCallService.VideoCall getVideoCall() {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001963 return mVideoCallImpl;
Ihab Awade63fadb2014-07-09 21:52:04 -07001964 }
1965
1966 /**
1967 * Obtains an object containing call details.
1968 *
1969 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
1970 * result may be {@code null}.
1971 */
1972 public Details getDetails() {
1973 return mDetails;
1974 }
1975
1976 /**
Hall Liu95d55872017-01-25 17:12:49 -08001977 * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
1978 * receive RTT text data, as well as to change the RTT mode.
1979 * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
1980 */
1981 public @Nullable RttCall getRttCall() {
1982 return mRttCall;
1983 }
1984
1985 /**
1986 * Returns whether this call has an active RTT connection.
1987 * @return true if there is a connection, false otherwise.
1988 */
1989 public boolean isRttActive() {
Hall Liue9041242018-02-09 16:40:03 -08001990 return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
Hall Liu95d55872017-01-25 17:12:49 -08001991 }
1992
1993 /**
Andrew Leeda80c872015-04-15 14:09:50 -07001994 * Registers a callback to this {@code Call}.
1995 *
1996 * @param callback A {@code Callback}.
1997 */
1998 public void registerCallback(Callback callback) {
Andrew Lee011728f2015-04-23 15:47:06 -07001999 registerCallback(callback, new Handler());
2000 }
2001
2002 /**
2003 * Registers a callback to this {@code Call}.
2004 *
2005 * @param callback A {@code Callback}.
2006 * @param handler A handler which command and status changes will be delivered to.
2007 */
2008 public void registerCallback(Callback callback, Handler handler) {
2009 unregisterCallback(callback);
Roshan Pius1ca62072015-07-07 17:34:51 -07002010 // Don't allow new callback registration if the call is already being destroyed.
2011 if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002012 mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
2013 }
Andrew Leeda80c872015-04-15 14:09:50 -07002014 }
2015
2016 /**
2017 * Unregisters a callback from this {@code Call}.
2018 *
2019 * @param callback A {@code Callback}.
2020 */
2021 public void unregisterCallback(Callback callback) {
Roshan Pius1ca62072015-07-07 17:34:51 -07002022 // Don't allow callback deregistration if the call is already being destroyed.
2023 if (callback != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07002024 for (CallbackRecord<Callback> record : mCallbackRecords) {
2025 if (record.getCallback() == callback) {
2026 mCallbackRecords.remove(record);
2027 break;
2028 }
2029 }
Andrew Leeda80c872015-04-15 14:09:50 -07002030 }
2031 }
2032
Santos Cordon3c20d632016-02-25 16:12:35 -08002033 @Override
2034 public String toString() {
2035 return new StringBuilder().
2036 append("Call [id: ").
2037 append(mTelecomCallId).
2038 append(", state: ").
2039 append(stateToString(mState)).
2040 append(", details: ").
2041 append(mDetails).
2042 append("]").toString();
2043 }
2044
2045 /**
2046 * @param state An integer value of a {@code STATE_*} constant.
2047 * @return A string representation of the value.
2048 */
2049 private static String stateToString(int state) {
2050 switch (state) {
2051 case STATE_NEW:
2052 return "NEW";
2053 case STATE_RINGING:
2054 return "RINGING";
2055 case STATE_DIALING:
2056 return "DIALING";
2057 case STATE_ACTIVE:
2058 return "ACTIVE";
2059 case STATE_HOLDING:
2060 return "HOLDING";
2061 case STATE_DISCONNECTED:
2062 return "DISCONNECTED";
2063 case STATE_CONNECTING:
2064 return "CONNECTING";
2065 case STATE_DISCONNECTING:
2066 return "DISCONNECTING";
2067 case STATE_SELECT_PHONE_ACCOUNT:
2068 return "SELECT_PHONE_ACCOUNT";
Hall Liu4e35b642019-10-14 17:50:45 -07002069 case STATE_SIMULATED_RINGING:
2070 return "SIMULATED_RINGING";
2071 case STATE_AUDIO_PROCESSING:
2072 return "AUDIO_PROCESSING";
Santos Cordon3c20d632016-02-25 16:12:35 -08002073 default:
2074 Log.w(Call.class, "Unknown state %d", state);
2075 return "UNKNOWN";
2076 }
2077 }
2078
Andrew Leeda80c872015-04-15 14:09:50 -07002079 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07002080 * Adds a listener to this {@code Call}.
2081 *
2082 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002083 * @deprecated Use {@link #registerCallback} instead.
2084 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002085 */
Andrew Leeda80c872015-04-15 14:09:50 -07002086 @Deprecated
2087 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002088 public void addListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002089 registerCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002090 }
2091
2092 /**
2093 * Removes a listener from this {@code Call}.
2094 *
2095 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07002096 * @deprecated Use {@link #unregisterCallback} instead.
2097 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07002098 */
Andrew Leeda80c872015-04-15 14:09:50 -07002099 @Deprecated
2100 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07002101 public void removeListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07002102 unregisterCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07002103 }
2104
2105 /** {@hide} */
Tyler Gunn159f35c2017-03-02 09:28:37 -08002106 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
2107 int targetSdkVersion) {
Ihab Awade63fadb2014-07-09 21:52:04 -07002108 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002109 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002110 mInCallAdapter = inCallAdapter;
2111 mState = STATE_NEW;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002112 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002113 mTargetSdkVersion = targetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07002114 }
2115
2116 /** {@hide} */
Tyler Gunnb88b3112016-11-09 10:19:23 -08002117 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
Tyler Gunn159f35c2017-03-02 09:28:37 -08002118 String callingPackage, int targetSdkVersion) {
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002119 mPhone = phone;
2120 mTelecomCallId = telecomCallId;
2121 mInCallAdapter = inCallAdapter;
2122 mState = state;
Tyler Gunnb88b3112016-11-09 10:19:23 -08002123 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08002124 mTargetSdkVersion = targetSdkVersion;
Shriram Ganeshddf570e2015-05-31 09:18:48 -07002125 }
2126
2127 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002128 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07002129 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002130 }
2131
2132 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002133 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Tyler Gunnb88b3112016-11-09 10:19:23 -08002134
Ihab Awade63fadb2014-07-09 21:52:04 -07002135 // First, we update the internal state as far as possible before firing any updates.
Sailesh Nepal1bef3392016-01-24 18:21:53 -08002136 Details details = Details.createFromParcelableCall(parcelableCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07002137 boolean detailsChanged = !Objects.equals(mDetails, details);
2138 if (detailsChanged) {
2139 mDetails = details;
2140 }
2141
2142 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -07002143 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
2144 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
2145 mCannedTextResponses =
2146 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Yorke Leee886f632015-08-04 13:43:31 -07002147 cannedTextResponsesChanged = true;
Ihab Awade63fadb2014-07-09 21:52:04 -07002148 }
2149
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002150 IVideoProvider previousVideoProvider = mVideoCallImpl == null ? null :
2151 mVideoCallImpl.getVideoProvider();
2152 IVideoProvider newVideoProvider = parcelableCall.getVideoProvider();
2153
2154 // parcelableCall.isVideoCallProviderChanged is only true when we have a video provider
2155 // specified; so we should check if the actual IVideoProvider changes as well.
2156 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged()
2157 && !Objects.equals(previousVideoProvider, newVideoProvider);
Andrew Lee50aca232014-07-22 16:41:54 -07002158 if (videoCallChanged) {
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002159 if (mVideoCallImpl != null) {
2160 mVideoCallImpl.destroy();
2161 }
2162 mVideoCallImpl = parcelableCall.isVideoCallProviderChanged() ?
2163 parcelableCall.getVideoCallImpl(mCallingPackage, mTargetSdkVersion) : null;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002164 }
Tyler Gunnd1fdf3a2019-11-05 15:47:58 -08002165
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002166 if (mVideoCallImpl != null) {
2167 mVideoCallImpl.setVideoState(getDetails().getVideoState());
Ihab Awade63fadb2014-07-09 21:52:04 -07002168 }
2169
Santos Cordone3c507b2015-04-23 14:44:19 -07002170 int state = parcelableCall.getState();
Hall Liu31de23d2019-10-11 15:38:29 -07002171 if (mTargetSdkVersion < Phone.SDK_VERSION_R && state == Call.STATE_SIMULATED_RINGING) {
2172 state = Call.STATE_RINGING;
2173 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002174 boolean stateChanged = mState != state;
2175 if (stateChanged) {
2176 mState = state;
2177 }
2178
Santos Cordon823fd3c2014-08-07 18:35:18 -07002179 String parentId = parcelableCall.getParentCallId();
2180 boolean parentChanged = !Objects.equals(mParentId, parentId);
2181 if (parentChanged) {
2182 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -07002183 }
2184
Santos Cordon823fd3c2014-08-07 18:35:18 -07002185 List<String> childCallIds = parcelableCall.getChildCallIds();
2186 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
2187 if (childrenChanged) {
2188 mChildrenIds.clear();
2189 mChildrenIds.addAll(parcelableCall.getChildCallIds());
2190 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -07002191 }
2192
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002193 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
2194 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
2195 for (String otherId : conferenceableCallIds) {
2196 if (callIdMap.containsKey(otherId)) {
2197 conferenceableCalls.add(callIdMap.get(otherId));
2198 }
2199 }
2200
2201 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
2202 mConferenceableCalls.clear();
2203 mConferenceableCalls.addAll(conferenceableCalls);
2204 fireConferenceableCallsChanged();
2205 }
2206
Hall Liu95d55872017-01-25 17:12:49 -08002207 boolean isRttChanged = false;
2208 boolean rttModeChanged = false;
Hall Liue9041242018-02-09 16:40:03 -08002209 if (parcelableCall.getIsRttCallChanged()
2210 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
Hall Liu95d55872017-01-25 17:12:49 -08002211 ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
2212 InputStreamReader receiveStream = new InputStreamReader(
2213 new ParcelFileDescriptor.AutoCloseInputStream(
2214 parcelableRttCall.getReceiveStream()),
2215 StandardCharsets.UTF_8);
2216 OutputStreamWriter transmitStream = new OutputStreamWriter(
2217 new ParcelFileDescriptor.AutoCloseOutputStream(
2218 parcelableRttCall.getTransmitStream()),
2219 StandardCharsets.UTF_8);
Hall Liu57006aa2017-02-06 10:49:48 -08002220 RttCall newRttCall = new Call.RttCall(mTelecomCallId,
Hall Liu95d55872017-01-25 17:12:49 -08002221 receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
2222 if (mRttCall == null) {
2223 isRttChanged = true;
2224 } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
2225 rttModeChanged = true;
2226 }
2227 mRttCall = newRttCall;
2228 } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
2229 && parcelableCall.getIsRttCallChanged()) {
2230 isRttChanged = true;
2231 mRttCall = null;
2232 }
2233
Ihab Awade63fadb2014-07-09 21:52:04 -07002234 // Now we fire updates, ensuring that any client who listens to any of these notifications
2235 // gets the most up-to-date state.
2236
2237 if (stateChanged) {
2238 fireStateChanged(mState);
2239 }
2240 if (detailsChanged) {
2241 fireDetailsChanged(mDetails);
2242 }
2243 if (cannedTextResponsesChanged) {
2244 fireCannedTextResponsesLoaded(mCannedTextResponses);
2245 }
Andrew Lee50aca232014-07-22 16:41:54 -07002246 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002247 fireVideoCallChanged(mVideoCallImpl);
Ihab Awade63fadb2014-07-09 21:52:04 -07002248 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002249 if (parentChanged) {
2250 fireParentChanged(getParent());
2251 }
2252 if (childrenChanged) {
2253 fireChildrenChanged(getChildren());
2254 }
Hall Liu95d55872017-01-25 17:12:49 -08002255 if (isRttChanged) {
2256 fireOnIsRttChanged(mRttCall != null, mRttCall);
2257 }
2258 if (rttModeChanged) {
2259 fireOnRttModeChanged(mRttCall.getRttAudioMode());
2260 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002261
2262 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
2263 // remove ourselves from the Phone. Note that we do this after completing all state updates
2264 // so a client can cleanly transition all their UI to the state appropriate for a
2265 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
2266 if (mState == STATE_DISCONNECTED) {
2267 fireCallDestroyed();
Ihab Awade63fadb2014-07-09 21:52:04 -07002268 }
2269 }
2270
2271 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002272 final void internalSetPostDialWait(String remaining) {
2273 mRemainingPostDialSequence = remaining;
2274 firePostDialWait(mRemainingPostDialSequence);
2275 }
2276
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07002277 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -07002278 final void internalSetDisconnected() {
2279 if (mState != Call.STATE_DISCONNECTED) {
2280 mState = Call.STATE_DISCONNECTED;
2281 fireStateChanged(mState);
2282 fireCallDestroyed();
Santos Cordonf30d7e92014-08-26 09:54:33 -07002283 }
2284 }
2285
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002286 /** {@hide} */
2287 final void internalOnConnectionEvent(String event, Bundle extras) {
2288 fireOnConnectionEvent(event, extras);
2289 }
2290
Hall Liu95d55872017-01-25 17:12:49 -08002291 /** {@hide} */
2292 final void internalOnRttUpgradeRequest(final int requestId) {
2293 for (CallbackRecord<Callback> record : mCallbackRecords) {
2294 final Call call = this;
2295 final Callback callback = record.getCallback();
2296 record.getHandler().post(() -> callback.onRttRequest(call, requestId));
2297 }
2298 }
2299
Hall Liu57006aa2017-02-06 10:49:48 -08002300 /** @hide */
2301 final void internalOnRttInitiationFailure(int reason) {
2302 for (CallbackRecord<Callback> record : mCallbackRecords) {
2303 final Call call = this;
2304 final Callback callback = record.getCallback();
2305 record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
2306 }
2307 }
2308
Sanket Padawe85291f62017-12-01 13:59:27 -08002309 /** {@hide} */
2310 final void internalOnHandoverFailed(int error) {
2311 for (CallbackRecord<Callback> record : mCallbackRecords) {
2312 final Call call = this;
2313 final Callback callback = record.getCallback();
2314 record.getHandler().post(() -> callback.onHandoverFailed(call, error));
2315 }
2316 }
2317
Tyler Gunn858bfaf2018-01-22 15:17:54 -08002318 /** {@hide} */
2319 final void internalOnHandoverComplete() {
2320 for (CallbackRecord<Callback> record : mCallbackRecords) {
2321 final Call call = this;
2322 final Callback callback = record.getCallback();
2323 record.getHandler().post(() -> callback.onHandoverComplete(call));
2324 }
2325 }
2326
Andrew Lee011728f2015-04-23 15:47:06 -07002327 private void fireStateChanged(final int newState) {
2328 for (CallbackRecord<Callback> record : mCallbackRecords) {
2329 final Call call = this;
2330 final Callback callback = record.getCallback();
2331 record.getHandler().post(new Runnable() {
2332 @Override
2333 public void run() {
2334 callback.onStateChanged(call, newState);
2335 }
2336 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002337 }
2338 }
2339
Andrew Lee011728f2015-04-23 15:47:06 -07002340 private void fireParentChanged(final Call newParent) {
2341 for (CallbackRecord<Callback> record : mCallbackRecords) {
2342 final Call call = this;
2343 final Callback callback = record.getCallback();
2344 record.getHandler().post(new Runnable() {
2345 @Override
2346 public void run() {
2347 callback.onParentChanged(call, newParent);
2348 }
2349 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002350 }
2351 }
2352
Andrew Lee011728f2015-04-23 15:47:06 -07002353 private void fireChildrenChanged(final List<Call> children) {
2354 for (CallbackRecord<Callback> record : mCallbackRecords) {
2355 final Call call = this;
2356 final Callback callback = record.getCallback();
2357 record.getHandler().post(new Runnable() {
2358 @Override
2359 public void run() {
2360 callback.onChildrenChanged(call, children);
2361 }
2362 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002363 }
2364 }
2365
Andrew Lee011728f2015-04-23 15:47:06 -07002366 private void fireDetailsChanged(final Details details) {
2367 for (CallbackRecord<Callback> record : mCallbackRecords) {
2368 final Call call = this;
2369 final Callback callback = record.getCallback();
2370 record.getHandler().post(new Runnable() {
2371 @Override
2372 public void run() {
2373 callback.onDetailsChanged(call, details);
2374 }
2375 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002376 }
2377 }
2378
Andrew Lee011728f2015-04-23 15:47:06 -07002379 private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
2380 for (CallbackRecord<Callback> record : mCallbackRecords) {
2381 final Call call = this;
2382 final Callback callback = record.getCallback();
2383 record.getHandler().post(new Runnable() {
2384 @Override
2385 public void run() {
2386 callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
2387 }
2388 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002389 }
2390 }
2391
Andrew Lee011728f2015-04-23 15:47:06 -07002392 private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
2393 for (CallbackRecord<Callback> record : mCallbackRecords) {
2394 final Call call = this;
2395 final Callback callback = record.getCallback();
2396 record.getHandler().post(new Runnable() {
2397 @Override
2398 public void run() {
2399 callback.onVideoCallChanged(call, videoCall);
2400 }
2401 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002402 }
2403 }
2404
Andrew Lee011728f2015-04-23 15:47:06 -07002405 private void firePostDialWait(final String remainingPostDialSequence) {
2406 for (CallbackRecord<Callback> record : mCallbackRecords) {
2407 final Call call = this;
2408 final Callback callback = record.getCallback();
2409 record.getHandler().post(new Runnable() {
2410 @Override
2411 public void run() {
2412 callback.onPostDialWait(call, remainingPostDialSequence);
2413 }
2414 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002415 }
2416 }
2417
2418 private void fireCallDestroyed() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002419 /**
2420 * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
2421 * onCallRemoved callback, we remove this call from the Phone's record
2422 * only once all of the registered onCallDestroyed callbacks are executed.
2423 * All the callbacks get removed from our records as a part of this operation
2424 * since onCallDestroyed is the final callback.
2425 */
2426 final Call call = this;
2427 if (mCallbackRecords.isEmpty()) {
2428 // No callbacks registered, remove the call from Phone's record.
2429 mPhone.internalRemoveCall(call);
2430 }
2431 for (final CallbackRecord<Callback> record : mCallbackRecords) {
Andrew Lee011728f2015-04-23 15:47:06 -07002432 final Callback callback = record.getCallback();
2433 record.getHandler().post(new Runnable() {
2434 @Override
2435 public void run() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002436 boolean isFinalRemoval = false;
2437 RuntimeException toThrow = null;
2438 try {
2439 callback.onCallDestroyed(call);
2440 } catch (RuntimeException e) {
2441 toThrow = e;
2442 }
2443 synchronized(Call.this) {
2444 mCallbackRecords.remove(record);
2445 if (mCallbackRecords.isEmpty()) {
2446 isFinalRemoval = true;
2447 }
2448 }
2449 if (isFinalRemoval) {
2450 mPhone.internalRemoveCall(call);
2451 }
2452 if (toThrow != null) {
2453 throw toThrow;
2454 }
Andrew Lee011728f2015-04-23 15:47:06 -07002455 }
2456 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002457 }
2458 }
2459
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002460 private void fireConferenceableCallsChanged() {
Andrew Lee011728f2015-04-23 15:47:06 -07002461 for (CallbackRecord<Callback> record : mCallbackRecords) {
2462 final Call call = this;
2463 final Callback callback = record.getCallback();
2464 record.getHandler().post(new Runnable() {
2465 @Override
2466 public void run() {
2467 callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
2468 }
2469 });
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002470 }
2471 }
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002472
2473 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002474 * Notifies listeners of an incoming connection event.
2475 * <p>
2476 * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
2477 *
2478 * @param event
2479 * @param extras
2480 */
2481 private void fireOnConnectionEvent(final String event, final Bundle extras) {
2482 for (CallbackRecord<Callback> record : mCallbackRecords) {
2483 final Call call = this;
2484 final Callback callback = record.getCallback();
2485 record.getHandler().post(new Runnable() {
2486 @Override
2487 public void run() {
2488 callback.onConnectionEvent(call, event, extras);
2489 }
2490 });
2491 }
2492 }
2493
2494 /**
Hall Liu95d55872017-01-25 17:12:49 -08002495 * Notifies listeners of an RTT on/off change
2496 *
2497 * @param enabled True if RTT is now enabled, false otherwise
2498 */
2499 private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
2500 for (CallbackRecord<Callback> record : mCallbackRecords) {
2501 final Call call = this;
2502 final Callback callback = record.getCallback();
2503 record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
2504 }
2505 }
2506
2507 /**
2508 * Notifies listeners of a RTT mode change
2509 *
2510 * @param mode The new RTT mode
2511 */
2512 private void fireOnRttModeChanged(final int mode) {
2513 for (CallbackRecord<Callback> record : mCallbackRecords) {
2514 final Call call = this;
2515 final Callback callback = record.getCallback();
2516 record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
2517 }
2518 }
2519
2520 /**
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002521 * Determines if two bundles are equal.
2522 *
2523 * @param bundle The original bundle.
2524 * @param newBundle The bundle to compare with.
2525 * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
2526 */
2527 private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
2528 if (bundle == null || newBundle == null) {
2529 return bundle == newBundle;
2530 }
2531
2532 if (bundle.size() != newBundle.size()) {
2533 return false;
2534 }
2535
2536 for(String key : bundle.keySet()) {
2537 if (key != null) {
2538 final Object value = bundle.get(key);
2539 final Object newValue = newBundle.get(key);
2540 if (!Objects.equals(value, newValue)) {
2541 return false;
2542 }
2543 }
2544 }
2545 return true;
2546 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002547}