blob: 8e8443247cab629b98c9c2cda7f5b2fad92f8bf0 [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;
Bill Peckhama74879d2018-09-08 10:06:40 -070022import android.annotation.UnsupportedAppUsage;
Ihab Awade63fadb2014-07-09 21:52:04 -070023import android.net.Uri;
Nancy Chen10798dc2014-08-08 14:00:25 -070024import android.os.Bundle;
Andrew Lee011728f2015-04-23 15:47:06 -070025import android.os.Handler;
Hall Liu95d55872017-01-25 17:12:49 -080026import android.os.ParcelFileDescriptor;
Ihab Awade63fadb2014-07-09 21:52:04 -070027
Hall Liu95d55872017-01-25 17:12:49 -080028import java.io.IOException;
29import java.io.InputStreamReader;
30import java.io.OutputStreamWriter;
Andrew Lee50aca232014-07-22 16:41:54 -070031import java.lang.String;
Hall Liu95d55872017-01-25 17:12:49 -080032import java.lang.annotation.Retention;
33import java.lang.annotation.RetentionPolicy;
34import java.nio.charset.StandardCharsets;
Ihab Awade63fadb2014-07-09 21:52:04 -070035import java.util.ArrayList;
Tyler Gunn071be6f2016-05-10 14:52:33 -070036import java.util.Arrays;
Ihab Awade63fadb2014-07-09 21:52:04 -070037import java.util.Collections;
38import java.util.List;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070039import java.util.Map;
Ihab Awade63fadb2014-07-09 21:52:04 -070040import java.util.Objects;
Jay Shrauner229e3822014-08-15 09:23:07 -070041import java.util.concurrent.CopyOnWriteArrayList;
Ihab Awade63fadb2014-07-09 21:52:04 -070042
43/**
44 * Represents an ongoing phone call that the in-call app should present to the user.
45 */
46public final class Call {
47 /**
48 * The state of a {@code Call} when newly created.
49 */
50 public static final int STATE_NEW = 0;
51
52 /**
53 * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
54 */
55 public static final int STATE_DIALING = 1;
56
57 /**
58 * The state of an incoming {@code Call} when ringing locally, but not yet connected.
59 */
60 public static final int STATE_RINGING = 2;
61
62 /**
63 * The state of a {@code Call} when in a holding state.
64 */
65 public static final int STATE_HOLDING = 3;
66
67 /**
68 * The state of a {@code Call} when actively supporting conversation.
69 */
70 public static final int STATE_ACTIVE = 4;
71
72 /**
73 * The state of a {@code Call} when no further voice or other communication is being
74 * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
75 * is no longer active, and the local data transport has or inevitably will release resources
76 * associated with this {@code Call}.
77 */
78 public static final int STATE_DISCONNECTED = 7;
79
Nancy Chen5da0fd52014-07-08 14:16:17 -070080 /**
Santos Cordone3c507b2015-04-23 14:44:19 -070081 * The state of an outgoing {@code Call} when waiting on user to select a
82 * {@link PhoneAccount} through which to place the call.
Nancy Chen5da0fd52014-07-08 14:16:17 -070083 */
Santos Cordone3c507b2015-04-23 14:44:19 -070084 public static final int STATE_SELECT_PHONE_ACCOUNT = 8;
85
86 /**
87 * @hide
88 * @deprecated use STATE_SELECT_PHONE_ACCOUNT.
89 */
90 @Deprecated
91 @SystemApi
92 public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT;
Nancy Chen5da0fd52014-07-08 14:16:17 -070093
Nancy Chene20930f2014-08-07 16:17:21 -070094 /**
Nancy Chene9b7a8e2014-08-08 14:26:27 -070095 * The initial state of an outgoing {@code Call}.
96 * Common transitions are to {@link #STATE_DIALING} state for a successful call or
97 * {@link #STATE_DISCONNECTED} if it failed.
Nancy Chene20930f2014-08-07 16:17:21 -070098 */
99 public static final int STATE_CONNECTING = 9;
100
Nancy Chen513c8922014-09-17 14:47:20 -0700101 /**
Tyler Gunn4afc6af2014-10-07 10:14:55 -0700102 * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
103 * call has not yet been disconnected by the underlying {@code ConnectionService}. The next
104 * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
105 */
106 public static final int STATE_DISCONNECTING = 10;
107
108 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700109 * The state of an external call which is in the process of being pulled from a remote device to
110 * the local device.
111 * <p>
112 * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
113 * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
114 * <p>
115 * An {@link InCallService} will only see this state if it has the
116 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
117 * manifest.
118 */
119 public static final int STATE_PULLING_CALL = 11;
120
121 /**
Nancy Chen513c8922014-09-17 14:47:20 -0700122 * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
123 * extras. Used to pass the phone accounts to display on the front end to the user in order to
124 * select phone accounts to (for example) place a call.
Nancy Chen513c8922014-09-17 14:47:20 -0700125 */
126 public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
127
mike dooley4af561f2016-12-20 08:55:17 -0800128 /**
mike dooley91217422017-03-09 12:58:42 -0800129 * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC)
130 * when the last outgoing emergency call was made. This is used to identify potential emergency
131 * callbacks.
mike dooley4af561f2016-12-20 08:55:17 -0800132 */
133 public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
134 "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
135
Tyler Gunn8bf76572017-04-06 15:30:08 -0700136 /**
137 * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
138 * Telecom that the user has requested that the current {@link Call} should be handed over
139 * to another {@link ConnectionService}.
140 * <p>
141 * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
142 * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
143 * @hide
144 */
145 public static final String EVENT_REQUEST_HANDOVER =
146 "android.telecom.event.REQUEST_HANDOVER";
147
148 /**
149 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
150 * {@link PhoneAccountHandle} to which a call should be handed over to.
151 * @hide
152 */
153 public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
154 "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
155
156 /**
157 * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
158 * video state of the call when it is handed over to the new {@link PhoneAccount}.
159 * <p>
160 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
161 * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
162 * {@link VideoProfile#STATE_TX_ENABLED}.
163 * @hide
164 */
165 public static final String EXTRA_HANDOVER_VIDEO_STATE =
166 "android.telecom.extra.HANDOVER_VIDEO_STATE";
167
168 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700169 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Used by the
170 * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra
171 * information to the handover {@link ConnectionService} specified by
172 * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}.
173 * <p>
174 * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the
175 * {@link ConnectionService} via the request extras when
176 * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
177 * is called to initate the handover.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700178 * @hide
179 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700180 public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700181
182 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700183 * Call event sent from Telecom to the handover {@link ConnectionService} via
184 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
185 * to the {@link ConnectionService} has completed successfully.
186 * <p>
187 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700188 * @hide
189 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700190 public static final String EVENT_HANDOVER_COMPLETE =
191 "android.telecom.event.HANDOVER_COMPLETE";
Tyler Gunn34a2b312017-06-23 08:32:00 -0700192
193 /**
194 * Call event sent from Telecom to the handover destination {@link ConnectionService} via
195 * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the
196 * source connection has disconnected. The {@link Bundle} parameter for the call event will be
197 * {@code null}.
198 * <p>
199 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
200 * @hide
201 */
202 public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
203 "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
204
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700205 /**
206 * Call event sent from Telecom to the handover {@link ConnectionService} via
207 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
208 * to the {@link ConnectionService} has failed.
209 * <p>
210 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
211 * @hide
212 */
213 public static final String EVENT_HANDOVER_FAILED =
214 "android.telecom.event.HANDOVER_FAILED";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700215
Ihab Awade63fadb2014-07-09 21:52:04 -0700216 public static class Details {
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800217
218 /** Call can currently be put on hold or unheld. */
219 public static final int CAPABILITY_HOLD = 0x00000001;
220
221 /** Call supports the hold feature. */
222 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
223
224 /**
225 * Calls within a conference can be merged. A {@link ConnectionService} has the option to
226 * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
227 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
228 * capability allows a merge button to be shown while the conference call is in the foreground
229 * of the in-call UI.
230 * <p>
231 * This is only intended for use by a {@link Conference}.
232 */
233 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
234
235 /**
236 * Calls within a conference can be swapped between foreground and background.
237 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
238 * <p>
239 * This is only intended for use by a {@link Conference}.
240 */
241 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
242
243 /**
244 * @hide
245 */
Andrew Lee2378ea72015-04-29 14:38:11 -0700246 public static final int CAPABILITY_UNUSED_1 = 0x00000010;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800247
248 /** Call supports responding via text option. */
249 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
250
251 /** Call can be muted. */
252 public static final int CAPABILITY_MUTE = 0x00000040;
253
254 /**
255 * Call supports conference call management. This capability only applies to {@link Conference}
256 * calls which can have {@link Connection}s as children.
257 */
258 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
259
260 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700261 * Local device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800262 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700263 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800264
265 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700266 * Local device supports transmitting video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800267 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700268 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800269
270 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700271 * Local device supports bidirectional video calling.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800272 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700273 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700274 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800275
276 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700277 * Remote device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800278 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700279 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
280
281 /**
282 * Remote device supports transmitting video.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700283 */
284 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
285
286 /**
287 * Remote device supports bidirectional video calling.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700288 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700289 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700290 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800291
292 /**
293 * Call is able to be separated from its parent {@code Conference}, if any.
294 */
295 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
296
297 /**
298 * Call is able to be individually disconnected when in a {@code Conference}.
299 */
300 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
301
302 /**
Dong Zhou89f41eb2015-03-15 11:59:49 -0500303 * Speed up audio setup for MT call.
304 * @hide
305 */
Tyler Gunn96d6c402015-03-18 12:39:23 -0700306 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
307
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700308 /**
309 * Call can be upgraded to a video call.
Rekha Kumar07366812015-03-24 16:42:31 -0700310 * @hide
311 */
Bill Peckhama74879d2018-09-08 10:06:40 -0700312 @UnsupportedAppUsage
Rekha Kumar07366812015-03-24 16:42:31 -0700313 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
314
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700315 /**
316 * For video calls, indicates whether the outgoing video for the call can be paused using
Yorke Lee32f24732015-05-12 16:18:03 -0700317 * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700318 */
319 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
320
Bryce Lee81901682015-08-28 16:38:02 -0700321 /**
322 * Call sends responses through connection.
323 * @hide
324 */
Tyler Gunnf97a0092016-01-19 15:59:34 -0800325 public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;
326
327 /**
328 * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
329 * <p>
330 * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
331 * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
332 * downgraded from a video call back to a VideoState of
333 * {@link VideoProfile#STATE_AUDIO_ONLY}.
334 * <p>
335 * Intuitively, a call which can be downgraded to audio should also have local and remote
336 * video
337 * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
338 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
339 */
340 public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
Bryce Lee81901682015-08-28 16:38:02 -0700341
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700342 /**
343 * When set for an external call, indicates that this {@code Call} can be pulled from a
344 * remote device to the current device.
345 * <p>
346 * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
347 * <p>
348 * An {@link InCallService} will only see calls with this capability if it has the
349 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
350 * in its manifest.
351 * <p>
352 * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
Tyler Gunn720c6642016-03-22 09:02:47 -0700353 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700354 */
355 public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
356
Suchand Ghosh107a58b2017-04-12 14:26:23 +0530357 /**
358 * Add participant in an active or conference call option
359 * @hide
360 */
Divya Sharma4e4914b2018-02-27 08:32:05 -0800361 public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
362
Pooja Jaind34698d2017-12-28 14:15:31 +0530363 /** Call supports the deflect feature. */
364 public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
Suchand Ghosh107a58b2017-04-12 14:26:23 +0530365
Benergy Meenan Ravuri792a7272018-05-18 23:16:10 +0530366 /**
367 * Remote device supports RTT.
368 * @hide
369 */
370
371 public static final int CAPABILITY_SUPPORTS_RTT_REMOTE = 0x04000000;
372
Tyler Gunnd11a3152015-03-18 13:09:14 -0700373 //******************************************************************************************
Benergy Meenan Ravuri792a7272018-05-18 23:16:10 +0530374 // Next CAPABILITY value: 0x08000000
Andrew Lee2378ea72015-04-29 14:38:11 -0700375 //******************************************************************************************
376
377 /**
378 * Whether the call is currently a conference.
379 */
380 public static final int PROPERTY_CONFERENCE = 0x00000001;
381
382 /**
383 * Whether the call is a generic conference, where we do not know the precise state of
384 * participants in the conference (eg. on CDMA).
385 */
386 public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
387
388 /**
389 * Whether the call is made while the device is in emergency callback mode.
390 */
391 public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
392
393 /**
394 * Connection is using WIFI.
395 */
396 public static final int PROPERTY_WIFI = 0x00000008;
397
398 /**
399 * Call is using high definition audio.
400 */
401 public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
402
Tony Maka68dcce2015-12-17 09:31:18 +0000403 /**
Tony Mak53b5df42016-05-19 13:40:38 +0100404 * Whether the call is associated with the work profile.
405 */
406 public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;
407
408 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700409 * When set, indicates that this {@code Call} does not actually exist locally for the
410 * {@link ConnectionService}.
411 * <p>
412 * Consider, for example, a scenario where a user has two phones with the same phone number.
413 * When a user places a call on one device, the telephony stack can represent that call on
414 * the other device by adding it to the {@link ConnectionService} with the
Tyler Gunn720c6642016-03-22 09:02:47 -0700415 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700416 * <p>
417 * An {@link InCallService} will only see calls with this property if it has the
418 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
419 * in its manifest.
420 * <p>
Tyler Gunn720c6642016-03-22 09:02:47 -0700421 * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700422 */
423 public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
424
Brad Ebinger15847072016-05-18 11:08:36 -0700425 /**
426 * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
427 */
428 public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
429
Tyler Gunn24e18332017-02-10 09:42:49 -0800430 /**
431 * Indicates that the call is from a self-managed {@link ConnectionService}.
432 * <p>
433 * See also {@link Connection#PROPERTY_SELF_MANAGED}
434 */
435 public static final int PROPERTY_SELF_MANAGED = 0x00000100;
436
Eric Erfanianec881872017-12-06 16:27:53 -0800437 /**
438 * Indicates the call used Assisted Dialing.
439 * See also {@link Connection#PROPERTY_ASSISTED_DIALING_USED}
Eric Erfaniandd2db2f2018-02-21 19:27:53 +0000440 * @hide
Eric Erfanianec881872017-12-06 16:27:53 -0800441 */
442 public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200;
443
Hall Liua549fed2018-02-09 16:40:03 -0800444 /**
445 * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
446 * {@link RttCall} object that is used to send and receive text.
447 */
448 public static final int PROPERTY_RTT = 0x00000400;
449
Andrew Lee2378ea72015-04-29 14:38:11 -0700450 //******************************************************************************************
Hall Liua549fed2018-02-09 16:40:03 -0800451 // Next PROPERTY value: 0x00000800
Tyler Gunnd11a3152015-03-18 13:09:14 -0700452 //******************************************************************************************
Tyler Gunn068085b2015-02-06 13:56:52 -0800453
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800454 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700455 private final Uri mHandle;
456 private final int mHandlePresentation;
457 private final String mCallerDisplayName;
458 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700459 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700460 private final int mCallCapabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700461 private final int mCallProperties;
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800462 private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700463 private final DisconnectCause mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700464 private final long mConnectTimeMillis;
465 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700466 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700467 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700468 private final Bundle mExtras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700469 private final Bundle mIntentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700470 private final long mCreationTimeMillis;
Ihab Awade63fadb2014-07-09 21:52:04 -0700471
472 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800473 * Whether the supplied capabilities supports the specified capability.
474 *
475 * @param capabilities A bit field of capabilities.
476 * @param capability The capability to check capabilities for.
477 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800478 */
479 public static boolean can(int capabilities, int capability) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800480 return (capabilities & capability) == capability;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800481 }
482
483 /**
484 * Whether the capabilities of this {@code Details} supports the specified capability.
485 *
486 * @param capability The capability to check capabilities for.
487 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800488 */
489 public boolean can(int capability) {
490 return can(mCallCapabilities, capability);
491 }
492
493 /**
494 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
495 *
496 * @param capabilities A capability bit field.
497 * @return A human readable string representation.
498 */
499 public static String capabilitiesToString(int capabilities) {
500 StringBuilder builder = new StringBuilder();
501 builder.append("[Capabilities:");
502 if (can(capabilities, CAPABILITY_HOLD)) {
503 builder.append(" CAPABILITY_HOLD");
504 }
505 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
506 builder.append(" CAPABILITY_SUPPORT_HOLD");
507 }
508 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
509 builder.append(" CAPABILITY_MERGE_CONFERENCE");
510 }
511 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
512 builder.append(" CAPABILITY_SWAP_CONFERENCE");
513 }
514 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
515 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
516 }
517 if (can(capabilities, CAPABILITY_MUTE)) {
518 builder.append(" CAPABILITY_MUTE");
519 }
520 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
521 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
522 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700523 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
524 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
525 }
526 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
527 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
528 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700529 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
530 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800531 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700532 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
533 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
534 }
535 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
536 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
537 }
Tyler Gunnf97a0092016-01-19 15:59:34 -0800538 if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
539 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
540 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700541 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
542 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800543 }
Dong Zhou89f41eb2015-03-15 11:59:49 -0500544 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
Tyler Gunnd11a3152015-03-18 13:09:14 -0700545 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
Dong Zhou89f41eb2015-03-15 11:59:49 -0500546 }
Rekha Kumar07366812015-03-24 16:42:31 -0700547 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
548 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
549 }
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700550 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
551 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
552 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700553 if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
554 builder.append(" CAPABILITY_CAN_PULL_CALL");
555 }
Suchand Ghosh107a58b2017-04-12 14:26:23 +0530556 if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) {
557 builder.append(" CAPABILITY_ADD_PARTICIPANT");
558 }
Pooja Jaind34698d2017-12-28 14:15:31 +0530559 if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
560 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
561 }
Benergy Meenan Ravuri792a7272018-05-18 23:16:10 +0530562 if (can(capabilities, CAPABILITY_SUPPORTS_RTT_REMOTE)) {
563 builder.append(" CAPABILITY_SUPPORTS_RTT_REMOTE");
564 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800565 builder.append("]");
566 return builder.toString();
567 }
568
569 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700570 * Whether the supplied properties includes the specified property.
571 *
572 * @param properties A bit field of properties.
573 * @param property The property to check properties for.
574 * @return Whether the specified property is supported.
575 */
576 public static boolean hasProperty(int properties, int property) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800577 return (properties & property) == property;
Andrew Lee2378ea72015-04-29 14:38:11 -0700578 }
579
580 /**
581 * Whether the properties of this {@code Details} includes the specified property.
582 *
583 * @param property The property to check properties for.
584 * @return Whether the specified property is supported.
585 */
586 public boolean hasProperty(int property) {
587 return hasProperty(mCallProperties, property);
588 }
589
590 /**
591 * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
592 *
593 * @param properties A property bit field.
594 * @return A human readable string representation.
595 */
596 public static String propertiesToString(int properties) {
597 StringBuilder builder = new StringBuilder();
598 builder.append("[Properties:");
599 if (hasProperty(properties, PROPERTY_CONFERENCE)) {
600 builder.append(" PROPERTY_CONFERENCE");
601 }
602 if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
603 builder.append(" PROPERTY_GENERIC_CONFERENCE");
604 }
605 if (hasProperty(properties, PROPERTY_WIFI)) {
606 builder.append(" PROPERTY_WIFI");
607 }
608 if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
609 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
610 }
611 if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
Yorke Leebe2a4a22015-06-12 10:10:55 -0700612 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
Andrew Lee2378ea72015-04-29 14:38:11 -0700613 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700614 if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
615 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
616 }
Brad Ebinger15847072016-05-18 11:08:36 -0700617 if(hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
618 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
619 }
Eric Erfanianec881872017-12-06 16:27:53 -0800620 if(hasProperty(properties, PROPERTY_ASSISTED_DIALING_USED)) {
621 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
622 }
Andrew Lee2378ea72015-04-29 14:38:11 -0700623 builder.append("]");
624 return builder.toString();
625 }
626
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800627 /** {@hide} */
628 public String getTelecomCallId() {
629 return mTelecomCallId;
630 }
631
Andrew Lee2378ea72015-04-29 14:38:11 -0700632 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700633 * @return The handle (e.g., phone number) to which the {@code Call} is currently
634 * connected.
635 */
636 public Uri getHandle() {
637 return mHandle;
638 }
639
640 /**
641 * @return The presentation requirements for the handle. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700642 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700643 */
644 public int getHandlePresentation() {
645 return mHandlePresentation;
646 }
647
648 /**
649 * @return The display name for the caller.
650 */
651 public String getCallerDisplayName() {
652 return mCallerDisplayName;
653 }
654
655 /**
656 * @return The presentation requirements for the caller display name. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700657 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700658 */
659 public int getCallerDisplayNamePresentation() {
660 return mCallerDisplayNamePresentation;
661 }
662
663 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700664 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
665 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700666 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700667 public PhoneAccountHandle getAccountHandle() {
668 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -0700669 }
670
671 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800672 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
673 * {@code CAPABILITY_*} constants in this class.
Ihab Awade63fadb2014-07-09 21:52:04 -0700674 */
Ihab Awad5d0410f2014-07-30 10:07:40 -0700675 public int getCallCapabilities() {
676 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700677 }
678
679 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700680 * @return A bitmask of the properties of the {@code Call}, as defined by the various
681 * {@code PROPERTY_*} constants in this class.
Andrew Lee223ad142014-08-27 16:33:08 -0700682 */
683 public int getCallProperties() {
684 return mCallProperties;
685 }
686
687 /**
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800688 * @return a bitmask of the audio routes available for the call.
689 *
690 * @hide
691 */
692 public int getSupportedAudioRoutes() {
693 return mSupportedAudioRoutes;
694 }
695
696 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700697 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
Nancy Chenf4cf77c2014-09-19 10:53:21 -0700698 * by {@link android.telecom.DisconnectCause}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700699 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700700 public DisconnectCause getDisconnectCause() {
701 return mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700702 }
703
704 /**
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700705 * Returns the time the {@link Call} connected (i.e. became active). This information is
706 * updated periodically, but user interfaces should not rely on this to display the "call
707 * time clock". For the time when the call was first added to Telecom, see
708 * {@link #getCreationTimeMillis()}.
709 *
710 * @return The time the {@link Call} connected in milliseconds since the epoch.
Ihab Awade63fadb2014-07-09 21:52:04 -0700711 */
Jay Shrauner164a0ac2015-04-14 18:16:10 -0700712 public final long getConnectTimeMillis() {
Ihab Awade63fadb2014-07-09 21:52:04 -0700713 return mConnectTimeMillis;
714 }
715
716 /**
717 * @return Information about any calling gateway the {@code Call} may be using.
718 */
719 public GatewayInfo getGatewayInfo() {
720 return mGatewayInfo;
721 }
722
Andrew Lee7a341382014-07-15 17:05:08 -0700723 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -0700724 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -0700725 */
726 public int getVideoState() {
727 return mVideoState;
728 }
729
Ihab Awad5d0410f2014-07-30 10:07:40 -0700730 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700731 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
Ihab Awad5d0410f2014-07-30 10:07:40 -0700732 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -0700733 */
734 public StatusHints getStatusHints() {
735 return mStatusHints;
736 }
737
Nancy Chen10798dc2014-08-08 14:00:25 -0700738 /**
Santos Cordon6b7f9552015-05-27 17:21:45 -0700739 * @return The extras associated with this call.
Nancy Chen10798dc2014-08-08 14:00:25 -0700740 */
741 public Bundle getExtras() {
742 return mExtras;
743 }
744
Santos Cordon6b7f9552015-05-27 17:21:45 -0700745 /**
746 * @return The extras used with the original intent to place this call.
747 */
748 public Bundle getIntentExtras() {
749 return mIntentExtras;
750 }
751
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700752 /**
753 * Returns the time when the call was first created and added to Telecom. This is the same
754 * time that is logged as the start time in the Call Log (see
755 * {@link android.provider.CallLog.Calls#DATE}). To determine when the call was connected
756 * (became active), see {@link #getConnectTimeMillis()}.
757 *
758 * @return The creation time of the call, in millis since the epoch.
759 */
760 public long getCreationTimeMillis() {
761 return mCreationTimeMillis;
762 }
763
Ihab Awade63fadb2014-07-09 21:52:04 -0700764 @Override
765 public boolean equals(Object o) {
766 if (o instanceof Details) {
767 Details d = (Details) o;
768 return
769 Objects.equals(mHandle, d.mHandle) &&
770 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
771 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
772 Objects.equals(mCallerDisplayNamePresentation,
773 d.mCallerDisplayNamePresentation) &&
Evan Charlton8c8a0622014-07-20 12:31:00 -0700774 Objects.equals(mAccountHandle, d.mAccountHandle) &&
Ihab Awad5d0410f2014-07-30 10:07:40 -0700775 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Andrew Lee223ad142014-08-27 16:33:08 -0700776 Objects.equals(mCallProperties, d.mCallProperties) &&
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700777 Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
Ihab Awade63fadb2014-07-09 21:52:04 -0700778 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Andrew Lee85f5d422014-07-11 17:22:03 -0700779 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Evan Charlton5b49ade2014-07-15 17:03:20 -0700780 Objects.equals(mVideoState, d.mVideoState) &&
Nancy Chen10798dc2014-08-08 14:00:25 -0700781 Objects.equals(mStatusHints, d.mStatusHints) &&
Tyler Gunn1e9bfc62015-08-19 11:18:58 -0700782 areBundlesEqual(mExtras, d.mExtras) &&
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700783 areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
784 Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis);
Ihab Awade63fadb2014-07-09 21:52:04 -0700785 }
786 return false;
787 }
788
789 @Override
790 public int hashCode() {
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700791 return Objects.hash(mHandle,
792 mHandlePresentation,
793 mCallerDisplayName,
794 mCallerDisplayNamePresentation,
795 mAccountHandle,
796 mCallCapabilities,
797 mCallProperties,
798 mDisconnectCause,
799 mConnectTimeMillis,
800 mGatewayInfo,
801 mVideoState,
802 mStatusHints,
803 mExtras,
804 mIntentExtras,
805 mCreationTimeMillis);
Ihab Awade63fadb2014-07-09 21:52:04 -0700806 }
807
808 /** {@hide} */
809 public Details(
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800810 String telecomCallId,
Ihab Awade63fadb2014-07-09 21:52:04 -0700811 Uri handle,
812 int handlePresentation,
813 String callerDisplayName,
814 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -0700815 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -0700816 int capabilities,
Andrew Lee223ad142014-08-27 16:33:08 -0700817 int properties,
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700818 DisconnectCause disconnectCause,
Ihab Awade63fadb2014-07-09 21:52:04 -0700819 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -0700820 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -0700821 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -0700822 StatusHints statusHints,
Santos Cordon6b7f9552015-05-27 17:21:45 -0700823 Bundle extras,
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700824 Bundle intentExtras,
825 long creationTimeMillis) {
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800826 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700827 mHandle = handle;
828 mHandlePresentation = handlePresentation;
829 mCallerDisplayName = callerDisplayName;
830 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700831 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700832 mCallCapabilities = capabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700833 mCallProperties = properties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700834 mDisconnectCause = disconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700835 mConnectTimeMillis = connectTimeMillis;
836 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700837 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700838 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700839 mExtras = extras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700840 mIntentExtras = intentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700841 mCreationTimeMillis = creationTimeMillis;
Ihab Awade63fadb2014-07-09 21:52:04 -0700842 }
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800843
844 /** {@hide} */
845 public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
846 return new Details(
847 parcelableCall.getId(),
848 parcelableCall.getHandle(),
849 parcelableCall.getHandlePresentation(),
850 parcelableCall.getCallerDisplayName(),
851 parcelableCall.getCallerDisplayNamePresentation(),
852 parcelableCall.getAccountHandle(),
853 parcelableCall.getCapabilities(),
854 parcelableCall.getProperties(),
855 parcelableCall.getDisconnectCause(),
856 parcelableCall.getConnectTimeMillis(),
857 parcelableCall.getGatewayInfo(),
858 parcelableCall.getVideoState(),
859 parcelableCall.getStatusHints(),
860 parcelableCall.getExtras(),
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700861 parcelableCall.getIntentExtras(),
862 parcelableCall.getCreationTimeMillis());
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800863 }
Santos Cordon3c20d632016-02-25 16:12:35 -0800864
865 @Override
866 public String toString() {
867 StringBuilder sb = new StringBuilder();
868 sb.append("[pa: ");
869 sb.append(mAccountHandle);
870 sb.append(", hdl: ");
871 sb.append(Log.pii(mHandle));
872 sb.append(", caps: ");
873 sb.append(capabilitiesToString(mCallCapabilities));
874 sb.append(", props: ");
Tyler Gunn720c6642016-03-22 09:02:47 -0700875 sb.append(propertiesToString(mCallProperties));
Santos Cordon3c20d632016-02-25 16:12:35 -0800876 sb.append("]");
877 return sb.toString();
878 }
Ihab Awade63fadb2014-07-09 21:52:04 -0700879 }
880
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -0700881 /**
882 * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
883 * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
884 * implementation.
885 * <p>
886 * You can handle these callbacks by extending the {@link Callback} class and overriding the
887 * callbacks that your {@link InCallService} is interested in. The callback methods include the
888 * {@link Call} for which the callback applies, allowing reuse of a single instance of your
889 * {@link Callback} implementation, if desired.
890 * <p>
891 * Use {@link Call#registerCallback(Callback)} to register your callback(s). Ensure
892 * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
893 * (typically in {@link InCallService#onCallRemoved(Call)}).
894 * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
895 * reach your implementation of {@link Callback}, so it is important to register your callback
896 * as soon as your {@link InCallService} is notified of a new call via
897 * {@link InCallService#onCallAdded(Call)}.
898 */
Andrew Leeda80c872015-04-15 14:09:50 -0700899 public static abstract class Callback {
Ihab Awade63fadb2014-07-09 21:52:04 -0700900 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -0700901 * @hide
902 */
Tyler Gunn3a09dc12018-03-07 21:09:48 +0000903 @IntDef(prefix = { "HANDOVER_" },
904 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
Tyler Gunn0ab38012018-03-19 20:14:10 +0000905 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
Tyler Gunn3a09dc12018-03-07 21:09:48 +0000906 HANDOVER_FAILURE_UNKNOWN})
Sanket Padawea8eddd42017-11-03 11:07:35 -0700907 @Retention(RetentionPolicy.SOURCE)
908 public @interface HandoverFailureErrors {}
909
910 /**
911 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
Tyler Gunn3a09dc12018-03-07 21:09:48 +0000912 * to handover the call to rejects the handover request.
913 * <p>
914 * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
915 * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
916 * {@code null} {@link Connection} from
917 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
918 * ConnectionRequest)}.
919 * <p>
920 * For more information on call handovers, see
921 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -0700922 */
923 public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
924
925 /**
Tyler Gunn3a09dc12018-03-07 21:09:48 +0000926 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
927 * is initiated but the source or destination app does not support handover.
928 * <p>
929 * Will be returned when a handover is requested via
930 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
931 * {@link PhoneAccountHandle} does not declare
932 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}. May also be returned when a handover is
933 * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
934 * {@link Details#getAccountHandle()}) does not declare
935 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
936 * <p>
937 * For more information on call handovers, see
938 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -0700939 */
Tyler Gunn3a09dc12018-03-07 21:09:48 +0000940 public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
Sanket Padawea8eddd42017-11-03 11:07:35 -0700941
942 /**
Tyler Gunn3a09dc12018-03-07 21:09:48 +0000943 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
944 * user rejects the handover request.
945 * <p>
946 * For more information on call handovers, see
947 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -0700948 */
Tyler Gunn3a09dc12018-03-07 21:09:48 +0000949 public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
Sanket Padawea8eddd42017-11-03 11:07:35 -0700950
Sanket Padawe85291f62017-12-01 13:59:27 -0800951 /**
952 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
953 * is ongoing emergency call.
Tyler Gunn3a09dc12018-03-07 21:09:48 +0000954 * <p>
955 * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
956 * called on an emergency call, or if any other call is an emergency call.
957 * <p>
958 * Handovers are not permitted while there are ongoing emergency calls.
959 * <p>
960 * For more information on call handovers, see
961 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
Sanket Padawe85291f62017-12-01 13:59:27 -0800962 */
Tyler Gunn0ab38012018-03-19 20:14:10 +0000963 public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
Sanket Padawe85291f62017-12-01 13:59:27 -0800964
Tyler Gunn3a09dc12018-03-07 21:09:48 +0000965 /**
966 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
967 * fails for an unknown reason.
968 * <p>
969 * For more information on call handovers, see
970 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
971 */
972 public static final int HANDOVER_FAILURE_UNKNOWN = 5;
Sanket Padawea8eddd42017-11-03 11:07:35 -0700973
974 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700975 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
976 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700977 * @param call The {@code Call} invoking this method.
978 * @param state The new state of the {@code Call}.
979 */
980 public void onStateChanged(Call call, int state) {}
981
982 /**
983 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
984 *
985 * @param call The {@code Call} invoking this method.
986 * @param parent The new parent of the {@code Call}.
987 */
988 public void onParentChanged(Call call, Call parent) {}
989
990 /**
991 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
992 *
993 * @param call The {@code Call} invoking this method.
994 * @param children The new children of the {@code Call}.
995 */
996 public void onChildrenChanged(Call call, List<Call> children) {}
997
998 /**
999 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
1000 *
1001 * @param call The {@code Call} invoking this method.
1002 * @param details A {@code Details} object describing the {@code Call}.
1003 */
1004 public void onDetailsChanged(Call call, Details details) {}
1005
1006 /**
1007 * Invoked when the text messages that can be used as responses to the incoming
1008 * {@code Call} are loaded from the relevant database.
1009 * See {@link #getCannedTextResponses()}.
1010 *
1011 * @param call The {@code Call} invoking this method.
1012 * @param cannedTextResponses The text messages useable as responses.
1013 */
1014 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
1015
1016 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001017 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
1018 * character. This causes the post-dial signals to stop pending user confirmation. An
1019 * implementation should present this choice to the user and invoke
1020 * {@link #postDialContinue(boolean)} when the user makes the choice.
1021 *
1022 * @param call The {@code Call} invoking this method.
1023 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
1024 */
1025 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
1026
1027 /**
Andrew Lee50aca232014-07-22 16:41:54 -07001028 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -07001029 *
1030 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -07001031 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001032 */
Andrew Lee50aca232014-07-22 16:41:54 -07001033 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -07001034
1035 /**
1036 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
1037 * up their UI for the {@code Call} in response to state transitions. Specifically,
1038 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
1039 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
1040 * clients should wait for this method to be invoked.
1041 *
1042 * @param call The {@code Call} being destroyed.
1043 */
1044 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001045
1046 /**
1047 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
1048 * conferenced.
1049 *
1050 * @param call The {@code Call} being updated.
1051 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
1052 * conferenced.
1053 */
1054 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001055
1056 /**
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001057 * Invoked when a {@link Call} receives an event from its associated {@link Connection}.
1058 * <p>
1059 * Where possible, the Call should make an attempt to handle {@link Connection} events which
1060 * are part of the {@code android.telecom.*} namespace. The Call should ignore any events
1061 * it does not wish to handle. Unexpected events should be handled gracefully, as it is
1062 * possible that a {@link ConnectionService} has defined its own Connection events which a
1063 * Call is not aware of.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001064 * <p>
1065 * See {@link Connection#sendConnectionEvent(String, Bundle)}.
1066 *
1067 * @param call The {@code Call} receiving the event.
1068 * @param event The event.
1069 * @param extras Extras associated with the connection event.
1070 */
1071 public void onConnectionEvent(Call call, String event, Bundle extras) {}
Hall Liu95d55872017-01-25 17:12:49 -08001072
1073 /**
1074 * Invoked when the RTT mode changes for this call.
1075 * @param call The call whose RTT mode has changed.
1076 * @param mode the new RTT mode, one of
1077 * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
1078 * or {@link RttCall#RTT_MODE_VCO}
1079 */
1080 public void onRttModeChanged(Call call, int mode) {}
1081
1082 /**
1083 * Invoked when the call's RTT status changes, either from off to on or from on to off.
1084 * @param call The call whose RTT status has changed.
1085 * @param enabled whether RTT is now enabled or disabled
1086 * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
1087 * on, null otherwise.
1088 */
1089 public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
1090
1091 /**
1092 * Invoked when the remote end of the connection has requested that an RTT communication
1093 * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
1094 * with the same ID that this method is invoked with.
1095 * @param call The call which the RTT request was placed on
1096 * @param id The ID of the request.
1097 */
1098 public void onRttRequest(Call call, int id) {}
Hall Liu57006aa2017-02-06 10:49:48 -08001099
1100 /**
1101 * Invoked when the RTT session failed to initiate for some reason, including rejection
1102 * by the remote party.
1103 * @param call The call which the RTT initiation failure occurred on.
1104 * @param reason One of the status codes defined in
1105 * {@link android.telecom.Connection.RttModifyStatus}, with the exception of
1106 * {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
1107 */
1108 public void onRttInitiationFailure(Call call, int reason) {}
Sanket Padawea8eddd42017-11-03 11:07:35 -07001109
1110 /**
1111 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1112 * has completed successfully.
Tyler Gunn3a09dc12018-03-07 21:09:48 +00001113 * <p>
1114 * For a full discussion of the handover process and the APIs involved, see
1115 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1116 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001117 * @param call The call which had initiated handover.
1118 */
1119 public void onHandoverComplete(Call call) {}
1120
1121 /**
1122 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1123 * has failed.
Tyler Gunn3a09dc12018-03-07 21:09:48 +00001124 * <p>
1125 * For a full discussion of the handover process and the APIs involved, see
1126 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1127 *
Sanket Padawea8eddd42017-11-03 11:07:35 -07001128 * @param call The call which had initiated handover.
Tyler Gunn3a09dc12018-03-07 21:09:48 +00001129 * @param failureReason Error reason for failure.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001130 */
1131 public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
Hall Liu95d55872017-01-25 17:12:49 -08001132 }
1133
1134 /**
1135 * A class that holds the state that describes the state of the RTT channel to the remote
1136 * party, if it is active.
1137 */
1138 public static final class RttCall {
Hall Liu07094df2017-02-28 15:17:44 -08001139 /** @hide */
Hall Liu95d55872017-01-25 17:12:49 -08001140 @Retention(RetentionPolicy.SOURCE)
1141 @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
1142 public @interface RttAudioMode {}
1143
1144 /**
1145 * For metrics use. Default value in the proto.
1146 * @hide
1147 */
1148 public static final int RTT_MODE_INVALID = 0;
1149
1150 /**
1151 * Indicates that there should be a bidirectional audio stream between the two parties
1152 * on the call.
1153 */
1154 public static final int RTT_MODE_FULL = 1;
1155
1156 /**
1157 * Indicates that the local user should be able to hear the audio stream from the remote
1158 * user, but not vice versa. Equivalent to muting the microphone.
1159 */
1160 public static final int RTT_MODE_HCO = 2;
1161
1162 /**
1163 * Indicates that the remote user should be able to hear the audio stream from the local
1164 * user, but not vice versa. Equivalent to setting the volume to zero.
1165 */
1166 public static final int RTT_MODE_VCO = 3;
1167
1168 private static final int READ_BUFFER_SIZE = 1000;
1169
1170 private InputStreamReader mReceiveStream;
1171 private OutputStreamWriter mTransmitStream;
1172 private int mRttMode;
1173 private final InCallAdapter mInCallAdapter;
Hall Liu57006aa2017-02-06 10:49:48 -08001174 private final String mTelecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001175 private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
1176
1177 /**
1178 * @hide
1179 */
Hall Liu57006aa2017-02-06 10:49:48 -08001180 public RttCall(String telecomCallId, InputStreamReader receiveStream,
1181 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
1182 mTelecomCallId = telecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001183 mReceiveStream = receiveStream;
1184 mTransmitStream = transmitStream;
1185 mRttMode = mode;
1186 mInCallAdapter = inCallAdapter;
1187 }
1188
1189 /**
1190 * Returns the current RTT audio mode.
1191 * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
1192 * {@link #RTT_MODE_HCO}.
1193 */
1194 public int getRttAudioMode() {
1195 return mRttMode;
1196 }
1197
1198 /**
1199 * Sets the RTT audio mode. The requested mode change will be communicated through
1200 * {@link Callback#onRttModeChanged(Call, int)}.
1201 * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
1202 * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
1203 */
1204 public void setRttMode(@RttAudioMode int mode) {
Hall Liu57006aa2017-02-06 10:49:48 -08001205 mInCallAdapter.setRttMode(mTelecomCallId, mode);
Hall Liu95d55872017-01-25 17:12:49 -08001206 }
1207
1208 /**
1209 * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
1210 * RTT transmits text in real-time, this method should be called once for each character
1211 * the user enters into the device.
1212 *
1213 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1214 * lead to interleaved text.
1215 * @param input The message to send to the remote user.
1216 */
1217 public void write(String input) throws IOException {
1218 mTransmitStream.write(input);
1219 mTransmitStream.flush();
1220 }
1221
1222 /**
1223 * Reads a string from the remote user, blocking if there is no data available. Returns
1224 * {@code null} if the RTT conversation has been terminated and there is no further data
1225 * to read.
1226 *
1227 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1228 * lead to interleaved text.
1229 * @return A string containing text sent by the remote user, or {@code null} if the
1230 * conversation has been terminated or if there was an error while reading.
1231 */
Hall Liub1c8a772017-07-17 17:04:41 -07001232 public String read() {
1233 try {
1234 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1235 if (numRead < 0) {
1236 return null;
1237 }
1238 return new String(mReadBuffer, 0, numRead);
1239 } catch (IOException e) {
1240 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
Jeff Sharkey90396362017-06-12 16:26:53 -06001241 return null;
Hall Liuffa4a812017-03-02 16:11:00 -08001242 }
Hall Liuffa4a812017-03-02 16:11:00 -08001243 }
1244
1245 /**
1246 * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
1247 * be read.
1248 * @return A string containing text entered by the user, or {@code null} if the user has
1249 * not entered any new text yet.
1250 */
1251 public String readImmediately() throws IOException {
1252 if (mReceiveStream.ready()) {
Hall Liub1c8a772017-07-17 17:04:41 -07001253 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1254 if (numRead < 0) {
1255 return null;
1256 }
1257 return new String(mReadBuffer, 0, numRead);
Hall Liuffa4a812017-03-02 16:11:00 -08001258 } else {
Hall Liu95d55872017-01-25 17:12:49 -08001259 return null;
1260 }
1261 }
Hall Liua549fed2018-02-09 16:40:03 -08001262
1263 /**
1264 * Closes the underlying file descriptors
1265 * @hide
1266 */
1267 public void close() {
1268 try {
1269 mReceiveStream.close();
1270 } catch (IOException e) {
1271 // ignore
1272 }
1273 try {
1274 mTransmitStream.close();
1275 } catch (IOException e) {
1276 // ignore
1277 }
1278 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001279 }
1280
Andrew Leeda80c872015-04-15 14:09:50 -07001281 /**
1282 * @deprecated Use {@code Call.Callback} instead.
1283 * @hide
1284 */
1285 @Deprecated
1286 @SystemApi
1287 public static abstract class Listener extends Callback { }
1288
Ihab Awade63fadb2014-07-09 21:52:04 -07001289 private final Phone mPhone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001290 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001291 private final InCallAdapter mInCallAdapter;
Santos Cordon823fd3c2014-08-07 18:35:18 -07001292 private final List<String> mChildrenIds = new ArrayList<>();
Ihab Awade63fadb2014-07-09 21:52:04 -07001293 private final List<Call> mChildren = new ArrayList<>();
1294 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Andrew Lee011728f2015-04-23 15:47:06 -07001295 private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001296 private final List<Call> mConferenceableCalls = new ArrayList<>();
1297 private final List<Call> mUnmodifiableConferenceableCalls =
1298 Collections.unmodifiableList(mConferenceableCalls);
1299
Santos Cordon823fd3c2014-08-07 18:35:18 -07001300 private boolean mChildrenCached;
1301 private String mParentId = null;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001302 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -07001303 private List<String> mCannedTextResponses = null;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001304 private String mCallingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001305 private int mTargetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07001306 private String mRemainingPostDialSequence;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001307 private VideoCallImpl mVideoCallImpl;
Hall Liu95d55872017-01-25 17:12:49 -08001308 private RttCall mRttCall;
Ihab Awade63fadb2014-07-09 21:52:04 -07001309 private Details mDetails;
Tyler Gunndee56a82016-03-23 16:06:34 -07001310 private Bundle mExtras;
Ihab Awade63fadb2014-07-09 21:52:04 -07001311
1312 /**
1313 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
1314 *
1315 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
1316 * remaining or this {@code Call} is not in a post-dial state.
1317 */
1318 public String getRemainingPostDialSequence() {
1319 return mRemainingPostDialSequence;
1320 }
1321
1322 /**
1323 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001324 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -07001325 */
Tyler Gunn3a09dc12018-03-07 21:09:48 +00001326 public void answer(@VideoProfile.VideoState int videoState) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001327 mInCallAdapter.answerCall(mTelecomCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -07001328 }
1329
1330 /**
Pooja Jaind34698d2017-12-28 14:15:31 +05301331 * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
1332 *
1333 * @param address The address to which the call will be deflected.
1334 */
1335 public void deflect(Uri address) {
1336 mInCallAdapter.deflectCall(mTelecomCallId, address);
1337 }
1338
1339 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001340 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
1341 *
1342 * @param rejectWithMessage Whether to reject with a text message.
1343 * @param textMessage An optional text message with which to respond.
1344 */
1345 public void reject(boolean rejectWithMessage, String textMessage) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001346 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
Ihab Awade63fadb2014-07-09 21:52:04 -07001347 }
1348
1349 /**
1350 * Instructs this {@code Call} to disconnect.
1351 */
1352 public void disconnect() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001353 mInCallAdapter.disconnectCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001354 }
1355
1356 /**
1357 * Instructs this {@code Call} to go on hold.
1358 */
1359 public void hold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001360 mInCallAdapter.holdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001361 }
1362
1363 /**
1364 * Instructs this {@link #STATE_HOLDING} call to release from hold.
1365 */
1366 public void unhold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001367 mInCallAdapter.unholdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001368 }
1369
1370 /**
1371 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
1372 *
1373 * Any other currently playing DTMF tone in the specified call is immediately stopped.
1374 *
1375 * @param digit A character representing the DTMF digit for which to play the tone. This
1376 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
1377 */
1378 public void playDtmfTone(char digit) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001379 mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
Ihab Awade63fadb2014-07-09 21:52:04 -07001380 }
1381
1382 /**
1383 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
1384 * currently playing.
1385 *
1386 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
1387 * currently playing, this method will do nothing.
1388 */
1389 public void stopDtmfTone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001390 mInCallAdapter.stopDtmfTone(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001391 }
1392
1393 /**
1394 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
1395 *
1396 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
1397 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -07001398 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001399 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -07001400 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
1401 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001402 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
Andrew Leeda80c872015-04-15 14:09:50 -07001403 * {@code Call} will pause playing the tones and notify callbacks via
1404 * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
Ihab Awade63fadb2014-07-09 21:52:04 -07001405 * should display to the user an indication of this state and an affordance to continue
1406 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
1407 * app should invoke the {@link #postDialContinue(boolean)} method.
1408 *
1409 * @param proceed Whether or not to continue with the post-dial sequence.
1410 */
1411 public void postDialContinue(boolean proceed) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001412 mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
Ihab Awade63fadb2014-07-09 21:52:04 -07001413 }
1414
1415 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -07001416 * Notifies this {@code Call} that an account has been selected and to proceed with placing
Nancy Chen36c62f32014-10-21 18:36:39 -07001417 * an outgoing call. Optionally sets this account as the default account.
Nancy Chen5da0fd52014-07-08 14:16:17 -07001418 */
Nancy Chen36c62f32014-10-21 18:36:39 -07001419 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
1420 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
Nancy Chen5da0fd52014-07-08 14:16:17 -07001421
1422 }
1423
1424 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001425 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001426 *
1427 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -07001428 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001429 public void conference(Call callToConferenceWith) {
1430 if (callToConferenceWith != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001431 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001432 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001433 }
1434
1435 /**
1436 * Instructs this {@code Call} to split from any conference call with which it may be
1437 * connected.
1438 */
1439 public void splitFromConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001440 mInCallAdapter.splitFromConference(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001441 }
1442
1443 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001444 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001445 */
1446 public void mergeConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001447 mInCallAdapter.mergeConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001448 }
1449
1450 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001451 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001452 */
1453 public void swapConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001454 mInCallAdapter.swapConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001455 }
1456
1457 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001458 * Initiates a request to the {@link ConnectionService} to pull an external call to the local
1459 * device.
1460 * <p>
1461 * Calls to this method are ignored if the call does not have the
1462 * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
1463 * <p>
1464 * An {@link InCallService} will only see calls which support this method if it has the
1465 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
1466 * in its manifest.
1467 */
1468 public void pullExternalCall() {
1469 // If this isn't an external call, ignore the request.
1470 if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
1471 return;
1472 }
1473
1474 mInCallAdapter.pullExternalCall(mTelecomCallId);
1475 }
1476
1477 /**
1478 * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
1479 * the {@link ConnectionService}.
1480 * <p>
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001481 * Call events are used to communicate point in time information from an {@link InCallService}
1482 * to a {@link ConnectionService}. A {@link ConnectionService} implementation could define
1483 * events which enable the {@link InCallService}, for example, toggle a unique feature of the
1484 * {@link ConnectionService}.
1485 * <p>
1486 * A {@link ConnectionService} can communicate to the {@link InCallService} using
1487 * {@link Connection#sendConnectionEvent(String, Bundle)}.
1488 * <p>
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001489 * Events are exposed to {@link ConnectionService} implementations via
1490 * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
1491 * <p>
1492 * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001493 * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
1494 * ignore some events altogether.
1495 * <p>
1496 * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
1497 * conflicts between {@link InCallService} implementations. Further, {@link InCallService}
1498 * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
1499 * they define their own event types in this namespace. When defining a custom event type,
1500 * ensure the contents of the extras {@link Bundle} is clearly defined. Extra keys for this
1501 * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
1502 * <p>
1503 * When defining events and the associated extras, it is important to keep their behavior
1504 * consistent when the associated {@link InCallService} is updated. Support for deprecated
1505 * events/extras should me maintained to ensure backwards compatibility with older
1506 * {@link ConnectionService} implementations which were built to support the older behavior.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001507 *
1508 * @param event The connection event.
1509 * @param extras Bundle containing extra information associated with the event.
1510 */
1511 public void sendCallEvent(String event, Bundle extras) {
Sanket Padawef6a9e5b2018-01-05 14:26:16 -08001512 mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001513 }
1514
1515 /**
Hall Liu95d55872017-01-25 17:12:49 -08001516 * Sends an RTT upgrade request to the remote end of the connection. Success is not
1517 * guaranteed, and notification of success will be via the
1518 * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1519 */
1520 public void sendRttRequest() {
Hall Liu57006aa2017-02-06 10:49:48 -08001521 mInCallAdapter.sendRttRequest(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001522 }
1523
1524 /**
1525 * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
1526 * callback.
1527 * The ID used here should be the same as the ID that was received via the callback.
1528 * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
1529 * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
1530 */
1531 public void respondToRttRequest(int id, boolean accept) {
Hall Liu57006aa2017-02-06 10:49:48 -08001532 mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
Hall Liu95d55872017-01-25 17:12:49 -08001533 }
1534
1535 /**
Sanket Padawea8eddd42017-11-03 11:07:35 -07001536 * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
1537 * by {@code toHandle}. The videoState specified indicates the desired video state after the
1538 * handover.
1539 * <p>
Tyler Gunn3a09dc12018-03-07 21:09:48 +00001540 * A call handover is the process where an ongoing call is transferred from one app (i.e.
1541 * {@link ConnectionService} to another app. The user could, for example, choose to continue a
1542 * mobile network call in a video calling app. The mobile network call via the Telephony stack
1543 * is referred to as the source of the handover, and the video calling app is referred to as the
1544 * destination.
1545 * <p>
1546 * When considering a handover scenario the device this method is called on is considered the
1547 * <em>initiating</em> device (since the user initiates the handover from this device), and the
1548 * other device is considered the <em>receiving</em> device.
1549 * <p>
1550 * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
1551 * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
1552 * and invoke
1553 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1554 * ConnectionRequest)} to inform the destination app that a request has been made to handover a
1555 * call to it. The app returns an instance of {@link Connection} to represent the handover call
1556 * At this point the app should display UI to indicate to the user that a call
1557 * handover is in process.
1558 * <p>
1559 * The destination app is responsible for communicating the handover request from the
1560 * <em>initiating</em> device to the <em>receiving</em> device.
1561 * <p>
1562 * When the app on the <em>receiving</em> device receives the handover request, it calls
1563 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
1564 * process from the <em>initiating</em> device to the <em>receiving</em> device. At this point
1565 * the destination app on the <em>receiving</em> device should show UI to allow the user to
1566 * choose whether they want to continue their call in the destination app.
1567 * <p>
1568 * When the destination app on the <em>receiving</em> device calls
1569 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
1570 * {@link ConnectionService} and call
1571 * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
1572 * ConnectionRequest)} to inform it of the handover request. The app returns an instance of
1573 * {@link Connection} to represent the handover call.
1574 * <p>
1575 * If the user of the <em>receiving</em> device accepts the handover, the app calls
1576 * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
1577 * original call. If the user rejects the handover, the app calls
1578 * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
1579 * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
1580 * <p>
1581 * Telecom will only allow handovers from {@link PhoneAccount}s which declare
1582 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}. Similarly, the {@link PhoneAccount}
1583 * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
1584 * <p>
1585 * Errors in the handover process are reported to the {@link InCallService} via
1586 * {@link Callback#onHandoverFailed(Call, int)}. Errors in the handover process are reported to
1587 * the involved {@link ConnectionService}s via
1588 * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
Sanket Padawea8eddd42017-11-03 11:07:35 -07001589 *
1590 * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
1591 * this call to.
Tyler Gunn3a09dc12018-03-07 21:09:48 +00001592 * @param videoState Indicates the video state desired after the handover (see the
1593 * {@code STATE_*} constants defined in {@link VideoProfile}).
Sanket Padawea8eddd42017-11-03 11:07:35 -07001594 * @param extras Bundle containing extra information to be passed to the
1595 * {@link ConnectionService}
1596 */
Tyler Gunn3a09dc12018-03-07 21:09:48 +00001597 public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
1598 Bundle extras) {
Sanket Padawea8eddd42017-11-03 11:07:35 -07001599 mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
1600 }
1601
1602 /**
Hall Liu95d55872017-01-25 17:12:49 -08001603 * Terminate the RTT session on this call. The resulting state change will be notified via
1604 * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1605 */
1606 public void stopRtt() {
Hall Liu57006aa2017-02-06 10:49:48 -08001607 mInCallAdapter.stopRtt(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001608 }
1609
1610 /**
Tyler Gunndee56a82016-03-23 16:06:34 -07001611 * Adds some extras to this {@link Call}. Existing keys are replaced and new ones are
1612 * added.
1613 * <p>
1614 * No assumptions should be made as to how an In-Call UI or service will handle these
1615 * extras. Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
1616 *
1617 * @param extras The extras to add.
1618 */
1619 public final void putExtras(Bundle extras) {
1620 if (extras == null) {
1621 return;
1622 }
1623
1624 if (mExtras == null) {
1625 mExtras = new Bundle();
1626 }
1627 mExtras.putAll(extras);
1628 mInCallAdapter.putExtras(mTelecomCallId, extras);
1629 }
1630
1631 /**
1632 * Adds a boolean extra to this {@link Call}.
1633 *
1634 * @param key The extra key.
1635 * @param value The value.
1636 * @hide
1637 */
1638 public final void putExtra(String key, boolean value) {
1639 if (mExtras == null) {
1640 mExtras = new Bundle();
1641 }
1642 mExtras.putBoolean(key, value);
1643 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1644 }
1645
1646 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001647 * Adds an integer extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001648 *
1649 * @param key The extra key.
1650 * @param value The value.
1651 * @hide
1652 */
1653 public final void putExtra(String key, int value) {
1654 if (mExtras == null) {
1655 mExtras = new Bundle();
1656 }
1657 mExtras.putInt(key, value);
1658 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1659 }
1660
1661 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001662 * Adds a string extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001663 *
1664 * @param key The extra key.
1665 * @param value The value.
1666 * @hide
1667 */
1668 public final void putExtra(String key, String value) {
1669 if (mExtras == null) {
1670 mExtras = new Bundle();
1671 }
1672 mExtras.putString(key, value);
1673 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1674 }
1675
1676 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001677 * Removes extras from this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001678 *
1679 * @param keys The keys of the extras to remove.
1680 */
1681 public final void removeExtras(List<String> keys) {
1682 if (mExtras != null) {
1683 for (String key : keys) {
1684 mExtras.remove(key);
1685 }
1686 if (mExtras.size() == 0) {
1687 mExtras = null;
1688 }
1689 }
1690 mInCallAdapter.removeExtras(mTelecomCallId, keys);
1691 }
1692
1693 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001694 * Removes extras from this {@link Call}.
1695 *
1696 * @param keys The keys of the extras to remove.
1697 */
1698 public final void removeExtras(String ... keys) {
1699 removeExtras(Arrays.asList(keys));
1700 }
1701
1702 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001703 * Obtains the parent of this {@code Call} in a conference, if any.
1704 *
1705 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
1706 * child of any conference {@code Call}s.
1707 */
1708 public Call getParent() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001709 if (mParentId != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001710 return mPhone.internalGetCallByTelecomId(mParentId);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001711 }
1712 return null;
Ihab Awade63fadb2014-07-09 21:52:04 -07001713 }
1714
1715 /**
1716 * Obtains the children of this conference {@code Call}, if any.
1717 *
1718 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
1719 * {@code List} otherwise.
1720 */
1721 public List<Call> getChildren() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001722 if (!mChildrenCached) {
1723 mChildrenCached = true;
1724 mChildren.clear();
1725
1726 for(String id : mChildrenIds) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001727 Call call = mPhone.internalGetCallByTelecomId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001728 if (call == null) {
1729 // At least one child was still not found, so do not save true for "cached"
1730 mChildrenCached = false;
1731 } else {
1732 mChildren.add(call);
1733 }
1734 }
1735 }
1736
Ihab Awade63fadb2014-07-09 21:52:04 -07001737 return mUnmodifiableChildren;
1738 }
1739
1740 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001741 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
1742 *
1743 * @return The list of conferenceable {@code Call}s.
1744 */
1745 public List<Call> getConferenceableCalls() {
1746 return mUnmodifiableConferenceableCalls;
1747 }
1748
1749 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001750 * Obtains the state of this {@code Call}.
1751 *
1752 * @return A state value, chosen from the {@code STATE_*} constants.
1753 */
1754 public int getState() {
1755 return mState;
1756 }
1757
1758 /**
1759 * Obtains a list of canned, pre-configured message responses to present to the user as
1760 * ways of rejecting this {@code Call} using via a text message.
1761 *
1762 * @see #reject(boolean, String)
1763 *
1764 * @return A list of canned text message responses.
1765 */
1766 public List<String> getCannedTextResponses() {
1767 return mCannedTextResponses;
1768 }
1769
1770 /**
1771 * Obtains an object that can be used to display video from this {@code Call}.
1772 *
Andrew Lee50aca232014-07-22 16:41:54 -07001773 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001774 */
Andrew Lee50aca232014-07-22 16:41:54 -07001775 public InCallService.VideoCall getVideoCall() {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001776 return mVideoCallImpl;
Ihab Awade63fadb2014-07-09 21:52:04 -07001777 }
1778
1779 /**
1780 * Obtains an object containing call details.
1781 *
1782 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
1783 * result may be {@code null}.
1784 */
1785 public Details getDetails() {
1786 return mDetails;
1787 }
1788
1789 /**
Hall Liu95d55872017-01-25 17:12:49 -08001790 * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
1791 * receive RTT text data, as well as to change the RTT mode.
1792 * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
1793 */
1794 public @Nullable RttCall getRttCall() {
1795 return mRttCall;
1796 }
1797
1798 /**
1799 * Returns whether this call has an active RTT connection.
1800 * @return true if there is a connection, false otherwise.
1801 */
1802 public boolean isRttActive() {
Hall Liua549fed2018-02-09 16:40:03 -08001803 return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
Hall Liu95d55872017-01-25 17:12:49 -08001804 }
1805
1806 /**
Andrew Leeda80c872015-04-15 14:09:50 -07001807 * Registers a callback to this {@code Call}.
1808 *
1809 * @param callback A {@code Callback}.
1810 */
1811 public void registerCallback(Callback callback) {
Andrew Lee011728f2015-04-23 15:47:06 -07001812 registerCallback(callback, new Handler());
1813 }
1814
1815 /**
1816 * Registers a callback to this {@code Call}.
1817 *
1818 * @param callback A {@code Callback}.
1819 * @param handler A handler which command and status changes will be delivered to.
1820 */
1821 public void registerCallback(Callback callback, Handler handler) {
1822 unregisterCallback(callback);
Roshan Pius1ca62072015-07-07 17:34:51 -07001823 // Don't allow new callback registration if the call is already being destroyed.
1824 if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07001825 mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
1826 }
Andrew Leeda80c872015-04-15 14:09:50 -07001827 }
1828
1829 /**
1830 * Unregisters a callback from this {@code Call}.
1831 *
1832 * @param callback A {@code Callback}.
1833 */
1834 public void unregisterCallback(Callback callback) {
Roshan Pius1ca62072015-07-07 17:34:51 -07001835 // Don't allow callback deregistration if the call is already being destroyed.
1836 if (callback != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07001837 for (CallbackRecord<Callback> record : mCallbackRecords) {
1838 if (record.getCallback() == callback) {
1839 mCallbackRecords.remove(record);
1840 break;
1841 }
1842 }
Andrew Leeda80c872015-04-15 14:09:50 -07001843 }
1844 }
1845
Santos Cordon3c20d632016-02-25 16:12:35 -08001846 @Override
1847 public String toString() {
1848 return new StringBuilder().
1849 append("Call [id: ").
1850 append(mTelecomCallId).
1851 append(", state: ").
1852 append(stateToString(mState)).
1853 append(", details: ").
1854 append(mDetails).
1855 append("]").toString();
1856 }
1857
1858 /**
1859 * @param state An integer value of a {@code STATE_*} constant.
1860 * @return A string representation of the value.
1861 */
1862 private static String stateToString(int state) {
1863 switch (state) {
1864 case STATE_NEW:
1865 return "NEW";
1866 case STATE_RINGING:
1867 return "RINGING";
1868 case STATE_DIALING:
1869 return "DIALING";
1870 case STATE_ACTIVE:
1871 return "ACTIVE";
1872 case STATE_HOLDING:
1873 return "HOLDING";
1874 case STATE_DISCONNECTED:
1875 return "DISCONNECTED";
1876 case STATE_CONNECTING:
1877 return "CONNECTING";
1878 case STATE_DISCONNECTING:
1879 return "DISCONNECTING";
1880 case STATE_SELECT_PHONE_ACCOUNT:
1881 return "SELECT_PHONE_ACCOUNT";
1882 default:
1883 Log.w(Call.class, "Unknown state %d", state);
1884 return "UNKNOWN";
1885 }
1886 }
1887
Andrew Leeda80c872015-04-15 14:09:50 -07001888 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001889 * Adds a listener to this {@code Call}.
1890 *
1891 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07001892 * @deprecated Use {@link #registerCallback} instead.
1893 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07001894 */
Andrew Leeda80c872015-04-15 14:09:50 -07001895 @Deprecated
1896 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07001897 public void addListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07001898 registerCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07001899 }
1900
1901 /**
1902 * Removes a listener from this {@code Call}.
1903 *
1904 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07001905 * @deprecated Use {@link #unregisterCallback} instead.
1906 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07001907 */
Andrew Leeda80c872015-04-15 14:09:50 -07001908 @Deprecated
1909 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07001910 public void removeListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07001911 unregisterCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07001912 }
1913
1914 /** {@hide} */
Tyler Gunn159f35c2017-03-02 09:28:37 -08001915 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
1916 int targetSdkVersion) {
Ihab Awade63fadb2014-07-09 21:52:04 -07001917 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001918 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001919 mInCallAdapter = inCallAdapter;
1920 mState = STATE_NEW;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001921 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001922 mTargetSdkVersion = targetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07001923 }
1924
1925 /** {@hide} */
Tyler Gunnb88b3112016-11-09 10:19:23 -08001926 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
Tyler Gunn159f35c2017-03-02 09:28:37 -08001927 String callingPackage, int targetSdkVersion) {
Shriram Ganeshddf570e2015-05-31 09:18:48 -07001928 mPhone = phone;
1929 mTelecomCallId = telecomCallId;
1930 mInCallAdapter = inCallAdapter;
1931 mState = state;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001932 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001933 mTargetSdkVersion = targetSdkVersion;
Shriram Ganeshddf570e2015-05-31 09:18:48 -07001934 }
1935
1936 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07001937 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001938 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001939 }
1940
1941 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001942 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Tyler Gunnb88b3112016-11-09 10:19:23 -08001943
Ihab Awade63fadb2014-07-09 21:52:04 -07001944 // First, we update the internal state as far as possible before firing any updates.
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001945 Details details = Details.createFromParcelableCall(parcelableCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07001946 boolean detailsChanged = !Objects.equals(mDetails, details);
1947 if (detailsChanged) {
1948 mDetails = details;
1949 }
1950
1951 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -07001952 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
1953 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
1954 mCannedTextResponses =
1955 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Yorke Leee886f632015-08-04 13:43:31 -07001956 cannedTextResponsesChanged = true;
Ihab Awade63fadb2014-07-09 21:52:04 -07001957 }
1958
Tyler Gunn159f35c2017-03-02 09:28:37 -08001959 VideoCallImpl newVideoCallImpl = parcelableCall.getVideoCallImpl(mCallingPackage,
1960 mTargetSdkVersion);
Tyler Gunn75958422015-04-15 14:23:42 -07001961 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() &&
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001962 !Objects.equals(mVideoCallImpl, newVideoCallImpl);
Andrew Lee50aca232014-07-22 16:41:54 -07001963 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001964 mVideoCallImpl = newVideoCallImpl;
1965 }
1966 if (mVideoCallImpl != null) {
1967 mVideoCallImpl.setVideoState(getDetails().getVideoState());
Ihab Awade63fadb2014-07-09 21:52:04 -07001968 }
1969
Santos Cordone3c507b2015-04-23 14:44:19 -07001970 int state = parcelableCall.getState();
Ihab Awade63fadb2014-07-09 21:52:04 -07001971 boolean stateChanged = mState != state;
1972 if (stateChanged) {
1973 mState = state;
1974 }
1975
Santos Cordon823fd3c2014-08-07 18:35:18 -07001976 String parentId = parcelableCall.getParentCallId();
1977 boolean parentChanged = !Objects.equals(mParentId, parentId);
1978 if (parentChanged) {
1979 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001980 }
1981
Santos Cordon823fd3c2014-08-07 18:35:18 -07001982 List<String> childCallIds = parcelableCall.getChildCallIds();
1983 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
1984 if (childrenChanged) {
1985 mChildrenIds.clear();
1986 mChildrenIds.addAll(parcelableCall.getChildCallIds());
1987 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -07001988 }
1989
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001990 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
1991 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
1992 for (String otherId : conferenceableCallIds) {
1993 if (callIdMap.containsKey(otherId)) {
1994 conferenceableCalls.add(callIdMap.get(otherId));
1995 }
1996 }
1997
1998 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
1999 mConferenceableCalls.clear();
2000 mConferenceableCalls.addAll(conferenceableCalls);
2001 fireConferenceableCallsChanged();
2002 }
2003
Hall Liu95d55872017-01-25 17:12:49 -08002004 boolean isRttChanged = false;
2005 boolean rttModeChanged = false;
Hall Liua549fed2018-02-09 16:40:03 -08002006 if (parcelableCall.getIsRttCallChanged()
2007 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
Hall Liu95d55872017-01-25 17:12:49 -08002008 ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
2009 InputStreamReader receiveStream = new InputStreamReader(
2010 new ParcelFileDescriptor.AutoCloseInputStream(
2011 parcelableRttCall.getReceiveStream()),
2012 StandardCharsets.UTF_8);
2013 OutputStreamWriter transmitStream = new OutputStreamWriter(
2014 new ParcelFileDescriptor.AutoCloseOutputStream(
2015 parcelableRttCall.getTransmitStream()),
2016 StandardCharsets.UTF_8);
Hall Liu57006aa2017-02-06 10:49:48 -08002017 RttCall newRttCall = new Call.RttCall(mTelecomCallId,
Hall Liu95d55872017-01-25 17:12:49 -08002018 receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
2019 if (mRttCall == null) {
2020 isRttChanged = true;
2021 } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
2022 rttModeChanged = true;
2023 }
2024 mRttCall = newRttCall;
2025 } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
2026 && parcelableCall.getIsRttCallChanged()) {
2027 isRttChanged = true;
2028 mRttCall = null;
2029 }
2030
Ihab Awade63fadb2014-07-09 21:52:04 -07002031 // Now we fire updates, ensuring that any client who listens to any of these notifications
2032 // gets the most up-to-date state.
2033
2034 if (stateChanged) {
2035 fireStateChanged(mState);
2036 }
2037 if (detailsChanged) {
2038 fireDetailsChanged(mDetails);
2039 }
2040 if (cannedTextResponsesChanged) {
2041 fireCannedTextResponsesLoaded(mCannedTextResponses);
2042 }
Andrew Lee50aca232014-07-22 16:41:54 -07002043 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08002044 fireVideoCallChanged(mVideoCallImpl);
Ihab Awade63fadb2014-07-09 21:52:04 -07002045 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07002046 if (parentChanged) {
2047 fireParentChanged(getParent());
2048 }
2049 if (childrenChanged) {
2050 fireChildrenChanged(getChildren());
2051 }
Hall Liu95d55872017-01-25 17:12:49 -08002052 if (isRttChanged) {
2053 fireOnIsRttChanged(mRttCall != null, mRttCall);
2054 }
2055 if (rttModeChanged) {
2056 fireOnRttModeChanged(mRttCall.getRttAudioMode());
2057 }
Ihab Awade63fadb2014-07-09 21:52:04 -07002058
2059 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
2060 // remove ourselves from the Phone. Note that we do this after completing all state updates
2061 // so a client can cleanly transition all their UI to the state appropriate for a
2062 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
2063 if (mState == STATE_DISCONNECTED) {
2064 fireCallDestroyed();
Ihab Awade63fadb2014-07-09 21:52:04 -07002065 }
2066 }
2067
2068 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07002069 final void internalSetPostDialWait(String remaining) {
2070 mRemainingPostDialSequence = remaining;
2071 firePostDialWait(mRemainingPostDialSequence);
2072 }
2073
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07002074 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -07002075 final void internalSetDisconnected() {
2076 if (mState != Call.STATE_DISCONNECTED) {
2077 mState = Call.STATE_DISCONNECTED;
2078 fireStateChanged(mState);
2079 fireCallDestroyed();
Santos Cordonf30d7e92014-08-26 09:54:33 -07002080 }
2081 }
2082
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002083 /** {@hide} */
2084 final void internalOnConnectionEvent(String event, Bundle extras) {
2085 fireOnConnectionEvent(event, extras);
2086 }
2087
Hall Liu95d55872017-01-25 17:12:49 -08002088 /** {@hide} */
2089 final void internalOnRttUpgradeRequest(final int requestId) {
2090 for (CallbackRecord<Callback> record : mCallbackRecords) {
2091 final Call call = this;
2092 final Callback callback = record.getCallback();
2093 record.getHandler().post(() -> callback.onRttRequest(call, requestId));
2094 }
2095 }
2096
Hall Liu57006aa2017-02-06 10:49:48 -08002097 /** @hide */
2098 final void internalOnRttInitiationFailure(int reason) {
2099 for (CallbackRecord<Callback> record : mCallbackRecords) {
2100 final Call call = this;
2101 final Callback callback = record.getCallback();
2102 record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
2103 }
2104 }
2105
Sanket Padawe85291f62017-12-01 13:59:27 -08002106 /** {@hide} */
2107 final void internalOnHandoverFailed(int error) {
2108 for (CallbackRecord<Callback> record : mCallbackRecords) {
2109 final Call call = this;
2110 final Callback callback = record.getCallback();
2111 record.getHandler().post(() -> callback.onHandoverFailed(call, error));
2112 }
2113 }
2114
Tyler Gunn79bc1ec2018-01-22 15:17:54 -08002115 /** {@hide} */
2116 final void internalOnHandoverComplete() {
2117 for (CallbackRecord<Callback> record : mCallbackRecords) {
2118 final Call call = this;
2119 final Callback callback = record.getCallback();
2120 record.getHandler().post(() -> callback.onHandoverComplete(call));
2121 }
2122 }
2123
Andrew Lee011728f2015-04-23 15:47:06 -07002124 private void fireStateChanged(final int newState) {
2125 for (CallbackRecord<Callback> record : mCallbackRecords) {
2126 final Call call = this;
2127 final Callback callback = record.getCallback();
2128 record.getHandler().post(new Runnable() {
2129 @Override
2130 public void run() {
2131 callback.onStateChanged(call, newState);
2132 }
2133 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002134 }
2135 }
2136
Andrew Lee011728f2015-04-23 15:47:06 -07002137 private void fireParentChanged(final Call newParent) {
2138 for (CallbackRecord<Callback> record : mCallbackRecords) {
2139 final Call call = this;
2140 final Callback callback = record.getCallback();
2141 record.getHandler().post(new Runnable() {
2142 @Override
2143 public void run() {
2144 callback.onParentChanged(call, newParent);
2145 }
2146 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002147 }
2148 }
2149
Andrew Lee011728f2015-04-23 15:47:06 -07002150 private void fireChildrenChanged(final List<Call> children) {
2151 for (CallbackRecord<Callback> record : mCallbackRecords) {
2152 final Call call = this;
2153 final Callback callback = record.getCallback();
2154 record.getHandler().post(new Runnable() {
2155 @Override
2156 public void run() {
2157 callback.onChildrenChanged(call, children);
2158 }
2159 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002160 }
2161 }
2162
Andrew Lee011728f2015-04-23 15:47:06 -07002163 private void fireDetailsChanged(final Details details) {
2164 for (CallbackRecord<Callback> record : mCallbackRecords) {
2165 final Call call = this;
2166 final Callback callback = record.getCallback();
2167 record.getHandler().post(new Runnable() {
2168 @Override
2169 public void run() {
2170 callback.onDetailsChanged(call, details);
2171 }
2172 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002173 }
2174 }
2175
Andrew Lee011728f2015-04-23 15:47:06 -07002176 private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
2177 for (CallbackRecord<Callback> record : mCallbackRecords) {
2178 final Call call = this;
2179 final Callback callback = record.getCallback();
2180 record.getHandler().post(new Runnable() {
2181 @Override
2182 public void run() {
2183 callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
2184 }
2185 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002186 }
2187 }
2188
Andrew Lee011728f2015-04-23 15:47:06 -07002189 private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
2190 for (CallbackRecord<Callback> record : mCallbackRecords) {
2191 final Call call = this;
2192 final Callback callback = record.getCallback();
2193 record.getHandler().post(new Runnable() {
2194 @Override
2195 public void run() {
2196 callback.onVideoCallChanged(call, videoCall);
2197 }
2198 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002199 }
2200 }
2201
Andrew Lee011728f2015-04-23 15:47:06 -07002202 private void firePostDialWait(final String remainingPostDialSequence) {
2203 for (CallbackRecord<Callback> record : mCallbackRecords) {
2204 final Call call = this;
2205 final Callback callback = record.getCallback();
2206 record.getHandler().post(new Runnable() {
2207 @Override
2208 public void run() {
2209 callback.onPostDialWait(call, remainingPostDialSequence);
2210 }
2211 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002212 }
2213 }
2214
2215 private void fireCallDestroyed() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002216 /**
2217 * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
2218 * onCallRemoved callback, we remove this call from the Phone's record
2219 * only once all of the registered onCallDestroyed callbacks are executed.
2220 * All the callbacks get removed from our records as a part of this operation
2221 * since onCallDestroyed is the final callback.
2222 */
2223 final Call call = this;
2224 if (mCallbackRecords.isEmpty()) {
2225 // No callbacks registered, remove the call from Phone's record.
2226 mPhone.internalRemoveCall(call);
2227 }
2228 for (final CallbackRecord<Callback> record : mCallbackRecords) {
Andrew Lee011728f2015-04-23 15:47:06 -07002229 final Callback callback = record.getCallback();
2230 record.getHandler().post(new Runnable() {
2231 @Override
2232 public void run() {
Roshan Pius1ca62072015-07-07 17:34:51 -07002233 boolean isFinalRemoval = false;
2234 RuntimeException toThrow = null;
2235 try {
2236 callback.onCallDestroyed(call);
2237 } catch (RuntimeException e) {
2238 toThrow = e;
2239 }
2240 synchronized(Call.this) {
2241 mCallbackRecords.remove(record);
2242 if (mCallbackRecords.isEmpty()) {
2243 isFinalRemoval = true;
2244 }
2245 }
2246 if (isFinalRemoval) {
2247 mPhone.internalRemoveCall(call);
2248 }
2249 if (toThrow != null) {
2250 throw toThrow;
2251 }
Andrew Lee011728f2015-04-23 15:47:06 -07002252 }
2253 });
Ihab Awade63fadb2014-07-09 21:52:04 -07002254 }
2255 }
2256
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002257 private void fireConferenceableCallsChanged() {
Andrew Lee011728f2015-04-23 15:47:06 -07002258 for (CallbackRecord<Callback> record : mCallbackRecords) {
2259 final Call call = this;
2260 final Callback callback = record.getCallback();
2261 record.getHandler().post(new Runnable() {
2262 @Override
2263 public void run() {
2264 callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
2265 }
2266 });
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002267 }
2268 }
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002269
2270 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07002271 * Notifies listeners of an incoming connection event.
2272 * <p>
2273 * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
2274 *
2275 * @param event
2276 * @param extras
2277 */
2278 private void fireOnConnectionEvent(final String event, final Bundle extras) {
2279 for (CallbackRecord<Callback> record : mCallbackRecords) {
2280 final Call call = this;
2281 final Callback callback = record.getCallback();
2282 record.getHandler().post(new Runnable() {
2283 @Override
2284 public void run() {
2285 callback.onConnectionEvent(call, event, extras);
2286 }
2287 });
2288 }
2289 }
2290
2291 /**
Hall Liu95d55872017-01-25 17:12:49 -08002292 * Notifies listeners of an RTT on/off change
2293 *
2294 * @param enabled True if RTT is now enabled, false otherwise
2295 */
2296 private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
2297 for (CallbackRecord<Callback> record : mCallbackRecords) {
2298 final Call call = this;
2299 final Callback callback = record.getCallback();
2300 record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
2301 }
2302 }
2303
2304 /**
2305 * Notifies listeners of a RTT mode change
2306 *
2307 * @param mode The new RTT mode
2308 */
2309 private void fireOnRttModeChanged(final int mode) {
2310 for (CallbackRecord<Callback> record : mCallbackRecords) {
2311 final Call call = this;
2312 final Callback callback = record.getCallback();
2313 record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
2314 }
2315 }
2316
2317 /**
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002318 * Determines if two bundles are equal.
2319 *
2320 * @param bundle The original bundle.
2321 * @param newBundle The bundle to compare with.
2322 * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
2323 */
2324 private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
2325 if (bundle == null || newBundle == null) {
2326 return bundle == newBundle;
2327 }
2328
2329 if (bundle.size() != newBundle.size()) {
2330 return false;
2331 }
2332
2333 for(String key : bundle.keySet()) {
2334 if (key != null) {
2335 final Object value = bundle.get(key);
2336 final Object newValue = newBundle.get(key);
2337 if (!Objects.equals(value, newValue)) {
2338 return false;
2339 }
2340 }
2341 }
2342 return true;
2343 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002344}