blob: c1475784a9ac3352bc6d83a3641967f46c7642a2 [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;
Ihab Awade63fadb2014-07-09 21:52:04 -070022import android.net.Uri;
Nancy Chen10798dc2014-08-08 14:00:25 -070023import android.os.Bundle;
Andrew Lee011728f2015-04-23 15:47:06 -070024import android.os.Handler;
Hall Liu95d55872017-01-25 17:12:49 -080025import android.os.ParcelFileDescriptor;
Ihab Awade63fadb2014-07-09 21:52:04 -070026
Hall Liu95d55872017-01-25 17:12:49 -080027import java.io.IOException;
28import java.io.InputStreamReader;
29import java.io.OutputStreamWriter;
Andrew Lee50aca232014-07-22 16:41:54 -070030import java.lang.String;
Hall Liu95d55872017-01-25 17:12:49 -080031import java.lang.annotation.Retention;
32import java.lang.annotation.RetentionPolicy;
33import java.nio.charset.StandardCharsets;
Ihab Awade63fadb2014-07-09 21:52:04 -070034import java.util.ArrayList;
Tyler Gunn071be6f2016-05-10 14:52:33 -070035import java.util.Arrays;
Ihab Awade63fadb2014-07-09 21:52:04 -070036import java.util.Collections;
37import java.util.List;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070038import java.util.Map;
Ihab Awade63fadb2014-07-09 21:52:04 -070039import java.util.Objects;
Jay Shrauner229e3822014-08-15 09:23:07 -070040import java.util.concurrent.CopyOnWriteArrayList;
Ihab Awade63fadb2014-07-09 21:52:04 -070041
42/**
43 * Represents an ongoing phone call that the in-call app should present to the user.
44 */
45public final class Call {
46 /**
47 * The state of a {@code Call} when newly created.
48 */
49 public static final int STATE_NEW = 0;
50
51 /**
52 * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
53 */
54 public static final int STATE_DIALING = 1;
55
56 /**
57 * The state of an incoming {@code Call} when ringing locally, but not yet connected.
58 */
59 public static final int STATE_RINGING = 2;
60
61 /**
62 * The state of a {@code Call} when in a holding state.
63 */
64 public static final int STATE_HOLDING = 3;
65
66 /**
67 * The state of a {@code Call} when actively supporting conversation.
68 */
69 public static final int STATE_ACTIVE = 4;
70
71 /**
72 * The state of a {@code Call} when no further voice or other communication is being
73 * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
74 * is no longer active, and the local data transport has or inevitably will release resources
75 * associated with this {@code Call}.
76 */
77 public static final int STATE_DISCONNECTED = 7;
78
Nancy Chen5da0fd52014-07-08 14:16:17 -070079 /**
Santos Cordone3c507b2015-04-23 14:44:19 -070080 * The state of an outgoing {@code Call} when waiting on user to select a
81 * {@link PhoneAccount} through which to place the call.
Nancy Chen5da0fd52014-07-08 14:16:17 -070082 */
Santos Cordone3c507b2015-04-23 14:44:19 -070083 public static final int STATE_SELECT_PHONE_ACCOUNT = 8;
84
85 /**
86 * @hide
87 * @deprecated use STATE_SELECT_PHONE_ACCOUNT.
88 */
89 @Deprecated
90 @SystemApi
91 public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT;
Nancy Chen5da0fd52014-07-08 14:16:17 -070092
Nancy Chene20930f2014-08-07 16:17:21 -070093 /**
Nancy Chene9b7a8e2014-08-08 14:26:27 -070094 * The initial state of an outgoing {@code Call}.
95 * Common transitions are to {@link #STATE_DIALING} state for a successful call or
96 * {@link #STATE_DISCONNECTED} if it failed.
Nancy Chene20930f2014-08-07 16:17:21 -070097 */
98 public static final int STATE_CONNECTING = 9;
99
Nancy Chen513c8922014-09-17 14:47:20 -0700100 /**
Tyler Gunn4afc6af2014-10-07 10:14:55 -0700101 * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
102 * call has not yet been disconnected by the underlying {@code ConnectionService}. The next
103 * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
104 */
105 public static final int STATE_DISCONNECTING = 10;
106
107 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700108 * The state of an external call which is in the process of being pulled from a remote device to
109 * the local device.
110 * <p>
111 * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
112 * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
113 * <p>
114 * An {@link InCallService} will only see this state if it has the
115 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
116 * manifest.
117 */
118 public static final int STATE_PULLING_CALL = 11;
119
120 /**
Nancy Chen513c8922014-09-17 14:47:20 -0700121 * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
122 * extras. Used to pass the phone accounts to display on the front end to the user in order to
123 * select phone accounts to (for example) place a call.
Nancy Chen513c8922014-09-17 14:47:20 -0700124 */
125 public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
126
mike dooley4af561f2016-12-20 08:55:17 -0800127 /**
mike dooley91217422017-03-09 12:58:42 -0800128 * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC)
129 * when the last outgoing emergency call was made. This is used to identify potential emergency
130 * callbacks.
mike dooley4af561f2016-12-20 08:55:17 -0800131 */
132 public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
133 "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
134
Tyler Gunn8bf76572017-04-06 15:30:08 -0700135 /**
136 * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
137 * Telecom that the user has requested that the current {@link Call} should be handed over
138 * to another {@link ConnectionService}.
139 * <p>
140 * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
141 * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
142 * @hide
143 */
144 public static final String EVENT_REQUEST_HANDOVER =
145 "android.telecom.event.REQUEST_HANDOVER";
146
147 /**
148 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
149 * {@link PhoneAccountHandle} to which a call should be handed over to.
150 * @hide
151 */
152 public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
153 "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
154
155 /**
156 * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
157 * video state of the call when it is handed over to the new {@link PhoneAccount}.
158 * <p>
159 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
160 * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
161 * {@link VideoProfile#STATE_TX_ENABLED}.
162 * @hide
163 */
164 public static final String EXTRA_HANDOVER_VIDEO_STATE =
165 "android.telecom.extra.HANDOVER_VIDEO_STATE";
166
167 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700168 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Used by the
169 * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra
170 * information to the handover {@link ConnectionService} specified by
171 * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}.
172 * <p>
173 * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the
174 * {@link ConnectionService} via the request extras when
175 * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
176 * is called to initate the handover.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700177 * @hide
178 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700179 public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700180
181 /**
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700182 * Call event sent from Telecom to the handover {@link ConnectionService} via
183 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
184 * to the {@link ConnectionService} has completed successfully.
185 * <p>
186 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
Tyler Gunn8bf76572017-04-06 15:30:08 -0700187 * @hide
188 */
Tyler Gunn9f6f0472017-04-17 18:25:22 -0700189 public static final String EVENT_HANDOVER_COMPLETE =
190 "android.telecom.event.HANDOVER_COMPLETE";
191 /**
192 * Call event sent from Telecom to the handover {@link ConnectionService} via
193 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
194 * to the {@link ConnectionService} has failed.
195 * <p>
196 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
197 * @hide
198 */
199 public static final String EVENT_HANDOVER_FAILED =
200 "android.telecom.event.HANDOVER_FAILED";
Tyler Gunn8bf76572017-04-06 15:30:08 -0700201
Ihab Awade63fadb2014-07-09 21:52:04 -0700202 public static class Details {
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800203
204 /** Call can currently be put on hold or unheld. */
205 public static final int CAPABILITY_HOLD = 0x00000001;
206
207 /** Call supports the hold feature. */
208 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
209
210 /**
211 * Calls within a conference can be merged. A {@link ConnectionService} has the option to
212 * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
213 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
214 * capability allows a merge button to be shown while the conference call is in the foreground
215 * of the in-call UI.
216 * <p>
217 * This is only intended for use by a {@link Conference}.
218 */
219 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
220
221 /**
222 * Calls within a conference can be swapped between foreground and background.
223 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
224 * <p>
225 * This is only intended for use by a {@link Conference}.
226 */
227 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
228
229 /**
230 * @hide
231 */
Andrew Lee2378ea72015-04-29 14:38:11 -0700232 public static final int CAPABILITY_UNUSED_1 = 0x00000010;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800233
234 /** Call supports responding via text option. */
235 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
236
237 /** Call can be muted. */
238 public static final int CAPABILITY_MUTE = 0x00000040;
239
240 /**
241 * Call supports conference call management. This capability only applies to {@link Conference}
242 * calls which can have {@link Connection}s as children.
243 */
244 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
245
246 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700247 * Local device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800248 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700249 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800250
251 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700252 * Local device supports transmitting video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800253 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700254 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800255
256 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700257 * Local device supports bidirectional video calling.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800258 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700259 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700260 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800261
262 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700263 * Remote device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800264 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700265 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
266
267 /**
268 * Remote device supports transmitting video.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700269 */
270 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
271
272 /**
273 * Remote device supports bidirectional video calling.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700274 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700275 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700276 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800277
278 /**
279 * Call is able to be separated from its parent {@code Conference}, if any.
280 */
281 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
282
283 /**
284 * Call is able to be individually disconnected when in a {@code Conference}.
285 */
286 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
287
288 /**
Dong Zhou89f41eb2015-03-15 11:59:49 -0500289 * Speed up audio setup for MT call.
290 * @hide
291 */
Tyler Gunn96d6c402015-03-18 12:39:23 -0700292 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
293
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700294 /**
295 * Call can be upgraded to a video call.
Rekha Kumar07366812015-03-24 16:42:31 -0700296 * @hide
297 */
298 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
299
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700300 /**
301 * For video calls, indicates whether the outgoing video for the call can be paused using
Yorke Lee32f24732015-05-12 16:18:03 -0700302 * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700303 */
304 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
305
Bryce Lee81901682015-08-28 16:38:02 -0700306 /**
307 * Call sends responses through connection.
308 * @hide
309 */
Tyler Gunnf97a0092016-01-19 15:59:34 -0800310 public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;
311
312 /**
313 * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
314 * <p>
315 * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
316 * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
317 * downgraded from a video call back to a VideoState of
318 * {@link VideoProfile#STATE_AUDIO_ONLY}.
319 * <p>
320 * Intuitively, a call which can be downgraded to audio should also have local and remote
321 * video
322 * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
323 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
324 */
325 public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
Bryce Lee81901682015-08-28 16:38:02 -0700326
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700327 /**
328 * When set for an external call, indicates that this {@code Call} can be pulled from a
329 * remote device to the current device.
330 * <p>
331 * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
332 * <p>
333 * An {@link InCallService} will only see calls with this capability if it has the
334 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
335 * in its manifest.
336 * <p>
337 * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
Tyler Gunn720c6642016-03-22 09:02:47 -0700338 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700339 */
340 public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
341
Tyler Gunnd11a3152015-03-18 13:09:14 -0700342 //******************************************************************************************
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700343 // Next CAPABILITY value: 0x01000000
Andrew Lee2378ea72015-04-29 14:38:11 -0700344 //******************************************************************************************
345
346 /**
347 * Whether the call is currently a conference.
348 */
349 public static final int PROPERTY_CONFERENCE = 0x00000001;
350
351 /**
352 * Whether the call is a generic conference, where we do not know the precise state of
353 * participants in the conference (eg. on CDMA).
354 */
355 public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
356
357 /**
358 * Whether the call is made while the device is in emergency callback mode.
359 */
360 public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
361
362 /**
363 * Connection is using WIFI.
364 */
365 public static final int PROPERTY_WIFI = 0x00000008;
366
367 /**
368 * Call is using high definition audio.
369 */
370 public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
371
Tony Maka68dcce2015-12-17 09:31:18 +0000372 /**
Tony Mak53b5df42016-05-19 13:40:38 +0100373 * Whether the call is associated with the work profile.
374 */
375 public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;
376
377 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700378 * When set, indicates that this {@code Call} does not actually exist locally for the
379 * {@link ConnectionService}.
380 * <p>
381 * Consider, for example, a scenario where a user has two phones with the same phone number.
382 * When a user places a call on one device, the telephony stack can represent that call on
383 * the other device by adding it to the {@link ConnectionService} with the
Tyler Gunn720c6642016-03-22 09:02:47 -0700384 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700385 * <p>
386 * An {@link InCallService} will only see calls with this property if it has the
387 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
388 * in its manifest.
389 * <p>
Tyler Gunn720c6642016-03-22 09:02:47 -0700390 * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700391 */
392 public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
393
Brad Ebinger15847072016-05-18 11:08:36 -0700394 /**
395 * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
396 */
397 public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
398
Tyler Gunn24e18332017-02-10 09:42:49 -0800399 /**
400 * Indicates that the call is from a self-managed {@link ConnectionService}.
401 * <p>
402 * See also {@link Connection#PROPERTY_SELF_MANAGED}
403 */
404 public static final int PROPERTY_SELF_MANAGED = 0x00000100;
405
Andrew Lee2378ea72015-04-29 14:38:11 -0700406 //******************************************************************************************
Tyler Gunn24e18332017-02-10 09:42:49 -0800407 // Next PROPERTY value: 0x00000200
Tyler Gunnd11a3152015-03-18 13:09:14 -0700408 //******************************************************************************************
Tyler Gunn068085b2015-02-06 13:56:52 -0800409
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800410 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700411 private final Uri mHandle;
412 private final int mHandlePresentation;
413 private final String mCallerDisplayName;
414 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700415 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700416 private final int mCallCapabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700417 private final int mCallProperties;
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800418 private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700419 private final DisconnectCause mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700420 private final long mConnectTimeMillis;
421 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700422 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700423 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700424 private final Bundle mExtras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700425 private final Bundle mIntentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700426 private final long mCreationTimeMillis;
Ihab Awade63fadb2014-07-09 21:52:04 -0700427
428 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800429 * Whether the supplied capabilities supports the specified capability.
430 *
431 * @param capabilities A bit field of capabilities.
432 * @param capability The capability to check capabilities for.
433 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800434 */
435 public static boolean can(int capabilities, int capability) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800436 return (capabilities & capability) == capability;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800437 }
438
439 /**
440 * Whether the capabilities of this {@code Details} supports the specified capability.
441 *
442 * @param capability The capability to check capabilities for.
443 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800444 */
445 public boolean can(int capability) {
446 return can(mCallCapabilities, capability);
447 }
448
449 /**
450 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
451 *
452 * @param capabilities A capability bit field.
453 * @return A human readable string representation.
454 */
455 public static String capabilitiesToString(int capabilities) {
456 StringBuilder builder = new StringBuilder();
457 builder.append("[Capabilities:");
458 if (can(capabilities, CAPABILITY_HOLD)) {
459 builder.append(" CAPABILITY_HOLD");
460 }
461 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
462 builder.append(" CAPABILITY_SUPPORT_HOLD");
463 }
464 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
465 builder.append(" CAPABILITY_MERGE_CONFERENCE");
466 }
467 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
468 builder.append(" CAPABILITY_SWAP_CONFERENCE");
469 }
470 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
471 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
472 }
473 if (can(capabilities, CAPABILITY_MUTE)) {
474 builder.append(" CAPABILITY_MUTE");
475 }
476 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
477 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
478 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700479 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
480 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
481 }
482 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
483 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
484 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700485 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
486 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800487 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700488 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
489 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
490 }
491 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
492 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
493 }
Tyler Gunnf97a0092016-01-19 15:59:34 -0800494 if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
495 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
496 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700497 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
498 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800499 }
Dong Zhou89f41eb2015-03-15 11:59:49 -0500500 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
Tyler Gunnd11a3152015-03-18 13:09:14 -0700501 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
Dong Zhou89f41eb2015-03-15 11:59:49 -0500502 }
Rekha Kumar07366812015-03-24 16:42:31 -0700503 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
504 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
505 }
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700506 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
507 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
508 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700509 if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
510 builder.append(" CAPABILITY_CAN_PULL_CALL");
511 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800512 builder.append("]");
513 return builder.toString();
514 }
515
516 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700517 * Whether the supplied properties includes the specified property.
518 *
519 * @param properties A bit field of properties.
520 * @param property The property to check properties for.
521 * @return Whether the specified property is supported.
522 */
523 public static boolean hasProperty(int properties, int property) {
Tyler Gunn014c7112015-12-18 14:33:57 -0800524 return (properties & property) == property;
Andrew Lee2378ea72015-04-29 14:38:11 -0700525 }
526
527 /**
528 * Whether the properties of this {@code Details} includes the specified property.
529 *
530 * @param property The property to check properties for.
531 * @return Whether the specified property is supported.
532 */
533 public boolean hasProperty(int property) {
534 return hasProperty(mCallProperties, property);
535 }
536
537 /**
538 * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
539 *
540 * @param properties A property bit field.
541 * @return A human readable string representation.
542 */
543 public static String propertiesToString(int properties) {
544 StringBuilder builder = new StringBuilder();
545 builder.append("[Properties:");
546 if (hasProperty(properties, PROPERTY_CONFERENCE)) {
547 builder.append(" PROPERTY_CONFERENCE");
548 }
549 if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
550 builder.append(" PROPERTY_GENERIC_CONFERENCE");
551 }
552 if (hasProperty(properties, PROPERTY_WIFI)) {
553 builder.append(" PROPERTY_WIFI");
554 }
555 if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
556 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
557 }
558 if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
Yorke Leebe2a4a22015-06-12 10:10:55 -0700559 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
Andrew Lee2378ea72015-04-29 14:38:11 -0700560 }
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700561 if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
562 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
563 }
Brad Ebinger15847072016-05-18 11:08:36 -0700564 if(hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
565 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
566 }
Andrew Lee2378ea72015-04-29 14:38:11 -0700567 builder.append("]");
568 return builder.toString();
569 }
570
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800571 /** {@hide} */
572 public String getTelecomCallId() {
573 return mTelecomCallId;
574 }
575
Andrew Lee2378ea72015-04-29 14:38:11 -0700576 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700577 * @return The handle (e.g., phone number) to which the {@code Call} is currently
578 * connected.
579 */
580 public Uri getHandle() {
581 return mHandle;
582 }
583
584 /**
585 * @return The presentation requirements for the handle. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700586 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700587 */
588 public int getHandlePresentation() {
589 return mHandlePresentation;
590 }
591
592 /**
593 * @return The display name for the caller.
594 */
595 public String getCallerDisplayName() {
596 return mCallerDisplayName;
597 }
598
599 /**
600 * @return The presentation requirements for the caller display name. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700601 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700602 */
603 public int getCallerDisplayNamePresentation() {
604 return mCallerDisplayNamePresentation;
605 }
606
607 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700608 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
609 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700610 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700611 public PhoneAccountHandle getAccountHandle() {
612 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -0700613 }
614
615 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800616 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
617 * {@code CAPABILITY_*} constants in this class.
Ihab Awade63fadb2014-07-09 21:52:04 -0700618 */
Ihab Awad5d0410f2014-07-30 10:07:40 -0700619 public int getCallCapabilities() {
620 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700621 }
622
623 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700624 * @return A bitmask of the properties of the {@code Call}, as defined by the various
625 * {@code PROPERTY_*} constants in this class.
Andrew Lee223ad142014-08-27 16:33:08 -0700626 */
627 public int getCallProperties() {
628 return mCallProperties;
629 }
630
631 /**
Christine Hallstrom4e22d6d2016-11-30 16:06:42 -0800632 * @return a bitmask of the audio routes available for the call.
633 *
634 * @hide
635 */
636 public int getSupportedAudioRoutes() {
637 return mSupportedAudioRoutes;
638 }
639
640 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700641 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
Nancy Chenf4cf77c2014-09-19 10:53:21 -0700642 * by {@link android.telecom.DisconnectCause}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700643 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700644 public DisconnectCause getDisconnectCause() {
645 return mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700646 }
647
648 /**
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700649 * Returns the time the {@link Call} connected (i.e. became active). This information is
650 * updated periodically, but user interfaces should not rely on this to display the "call
651 * time clock". For the time when the call was first added to Telecom, see
652 * {@link #getCreationTimeMillis()}.
653 *
654 * @return The time the {@link Call} connected in milliseconds since the epoch.
Ihab Awade63fadb2014-07-09 21:52:04 -0700655 */
Jay Shrauner164a0ac2015-04-14 18:16:10 -0700656 public final long getConnectTimeMillis() {
Ihab Awade63fadb2014-07-09 21:52:04 -0700657 return mConnectTimeMillis;
658 }
659
660 /**
661 * @return Information about any calling gateway the {@code Call} may be using.
662 */
663 public GatewayInfo getGatewayInfo() {
664 return mGatewayInfo;
665 }
666
Andrew Lee7a341382014-07-15 17:05:08 -0700667 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -0700668 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -0700669 */
670 public int getVideoState() {
671 return mVideoState;
672 }
673
Ihab Awad5d0410f2014-07-30 10:07:40 -0700674 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700675 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
Ihab Awad5d0410f2014-07-30 10:07:40 -0700676 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -0700677 */
678 public StatusHints getStatusHints() {
679 return mStatusHints;
680 }
681
Nancy Chen10798dc2014-08-08 14:00:25 -0700682 /**
Santos Cordon6b7f9552015-05-27 17:21:45 -0700683 * @return The extras associated with this call.
Nancy Chen10798dc2014-08-08 14:00:25 -0700684 */
685 public Bundle getExtras() {
686 return mExtras;
687 }
688
Santos Cordon6b7f9552015-05-27 17:21:45 -0700689 /**
690 * @return The extras used with the original intent to place this call.
691 */
692 public Bundle getIntentExtras() {
693 return mIntentExtras;
694 }
695
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700696 /**
697 * Returns the time when the call was first created and added to Telecom. This is the same
698 * time that is logged as the start time in the Call Log (see
699 * {@link android.provider.CallLog.Calls#DATE}). To determine when the call was connected
700 * (became active), see {@link #getConnectTimeMillis()}.
701 *
702 * @return The creation time of the call, in millis since the epoch.
703 */
704 public long getCreationTimeMillis() {
705 return mCreationTimeMillis;
706 }
707
Ihab Awade63fadb2014-07-09 21:52:04 -0700708 @Override
709 public boolean equals(Object o) {
710 if (o instanceof Details) {
711 Details d = (Details) o;
712 return
713 Objects.equals(mHandle, d.mHandle) &&
714 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
715 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
716 Objects.equals(mCallerDisplayNamePresentation,
717 d.mCallerDisplayNamePresentation) &&
Evan Charlton8c8a0622014-07-20 12:31:00 -0700718 Objects.equals(mAccountHandle, d.mAccountHandle) &&
Ihab Awad5d0410f2014-07-30 10:07:40 -0700719 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Andrew Lee223ad142014-08-27 16:33:08 -0700720 Objects.equals(mCallProperties, d.mCallProperties) &&
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700721 Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
Ihab Awade63fadb2014-07-09 21:52:04 -0700722 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Andrew Lee85f5d422014-07-11 17:22:03 -0700723 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Evan Charlton5b49ade2014-07-15 17:03:20 -0700724 Objects.equals(mVideoState, d.mVideoState) &&
Nancy Chen10798dc2014-08-08 14:00:25 -0700725 Objects.equals(mStatusHints, d.mStatusHints) &&
Tyler Gunn1e9bfc62015-08-19 11:18:58 -0700726 areBundlesEqual(mExtras, d.mExtras) &&
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700727 areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
728 Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis);
Ihab Awade63fadb2014-07-09 21:52:04 -0700729 }
730 return false;
731 }
732
733 @Override
734 public int hashCode() {
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700735 return Objects.hash(mHandle,
736 mHandlePresentation,
737 mCallerDisplayName,
738 mCallerDisplayNamePresentation,
739 mAccountHandle,
740 mCallCapabilities,
741 mCallProperties,
742 mDisconnectCause,
743 mConnectTimeMillis,
744 mGatewayInfo,
745 mVideoState,
746 mStatusHints,
747 mExtras,
748 mIntentExtras,
749 mCreationTimeMillis);
Ihab Awade63fadb2014-07-09 21:52:04 -0700750 }
751
752 /** {@hide} */
753 public Details(
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800754 String telecomCallId,
Ihab Awade63fadb2014-07-09 21:52:04 -0700755 Uri handle,
756 int handlePresentation,
757 String callerDisplayName,
758 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -0700759 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -0700760 int capabilities,
Andrew Lee223ad142014-08-27 16:33:08 -0700761 int properties,
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700762 DisconnectCause disconnectCause,
Ihab Awade63fadb2014-07-09 21:52:04 -0700763 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -0700764 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -0700765 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -0700766 StatusHints statusHints,
Santos Cordon6b7f9552015-05-27 17:21:45 -0700767 Bundle extras,
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700768 Bundle intentExtras,
769 long creationTimeMillis) {
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800770 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700771 mHandle = handle;
772 mHandlePresentation = handlePresentation;
773 mCallerDisplayName = callerDisplayName;
774 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700775 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700776 mCallCapabilities = capabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700777 mCallProperties = properties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700778 mDisconnectCause = disconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700779 mConnectTimeMillis = connectTimeMillis;
780 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700781 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700782 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700783 mExtras = extras;
Santos Cordon6b7f9552015-05-27 17:21:45 -0700784 mIntentExtras = intentExtras;
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700785 mCreationTimeMillis = creationTimeMillis;
Ihab Awade63fadb2014-07-09 21:52:04 -0700786 }
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800787
788 /** {@hide} */
789 public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
790 return new Details(
791 parcelableCall.getId(),
792 parcelableCall.getHandle(),
793 parcelableCall.getHandlePresentation(),
794 parcelableCall.getCallerDisplayName(),
795 parcelableCall.getCallerDisplayNamePresentation(),
796 parcelableCall.getAccountHandle(),
797 parcelableCall.getCapabilities(),
798 parcelableCall.getProperties(),
799 parcelableCall.getDisconnectCause(),
800 parcelableCall.getConnectTimeMillis(),
801 parcelableCall.getGatewayInfo(),
802 parcelableCall.getVideoState(),
803 parcelableCall.getStatusHints(),
804 parcelableCall.getExtras(),
Tyler Gunnc0bf6de2017-03-17 11:27:09 -0700805 parcelableCall.getIntentExtras(),
806 parcelableCall.getCreationTimeMillis());
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800807 }
Santos Cordon3c20d632016-02-25 16:12:35 -0800808
809 @Override
810 public String toString() {
811 StringBuilder sb = new StringBuilder();
812 sb.append("[pa: ");
813 sb.append(mAccountHandle);
814 sb.append(", hdl: ");
815 sb.append(Log.pii(mHandle));
816 sb.append(", caps: ");
817 sb.append(capabilitiesToString(mCallCapabilities));
818 sb.append(", props: ");
Tyler Gunn720c6642016-03-22 09:02:47 -0700819 sb.append(propertiesToString(mCallProperties));
Santos Cordon3c20d632016-02-25 16:12:35 -0800820 sb.append("]");
821 return sb.toString();
822 }
Ihab Awade63fadb2014-07-09 21:52:04 -0700823 }
824
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -0700825 /**
826 * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
827 * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
828 * implementation.
829 * <p>
830 * You can handle these callbacks by extending the {@link Callback} class and overriding the
831 * callbacks that your {@link InCallService} is interested in. The callback methods include the
832 * {@link Call} for which the callback applies, allowing reuse of a single instance of your
833 * {@link Callback} implementation, if desired.
834 * <p>
835 * Use {@link Call#registerCallback(Callback)} to register your callback(s). Ensure
836 * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
837 * (typically in {@link InCallService#onCallRemoved(Call)}).
838 * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
839 * reach your implementation of {@link Callback}, so it is important to register your callback
840 * as soon as your {@link InCallService} is notified of a new call via
841 * {@link InCallService#onCallAdded(Call)}.
842 */
Andrew Leeda80c872015-04-15 14:09:50 -0700843 public static abstract class Callback {
Ihab Awade63fadb2014-07-09 21:52:04 -0700844 /**
845 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
846 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700847 * @param call The {@code Call} invoking this method.
848 * @param state The new state of the {@code Call}.
849 */
850 public void onStateChanged(Call call, int state) {}
851
852 /**
853 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
854 *
855 * @param call The {@code Call} invoking this method.
856 * @param parent The new parent of the {@code Call}.
857 */
858 public void onParentChanged(Call call, Call parent) {}
859
860 /**
861 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
862 *
863 * @param call The {@code Call} invoking this method.
864 * @param children The new children of the {@code Call}.
865 */
866 public void onChildrenChanged(Call call, List<Call> children) {}
867
868 /**
869 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
870 *
871 * @param call The {@code Call} invoking this method.
872 * @param details A {@code Details} object describing the {@code Call}.
873 */
874 public void onDetailsChanged(Call call, Details details) {}
875
876 /**
877 * Invoked when the text messages that can be used as responses to the incoming
878 * {@code Call} are loaded from the relevant database.
879 * See {@link #getCannedTextResponses()}.
880 *
881 * @param call The {@code Call} invoking this method.
882 * @param cannedTextResponses The text messages useable as responses.
883 */
884 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
885
886 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700887 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
888 * character. This causes the post-dial signals to stop pending user confirmation. An
889 * implementation should present this choice to the user and invoke
890 * {@link #postDialContinue(boolean)} when the user makes the choice.
891 *
892 * @param call The {@code Call} invoking this method.
893 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
894 */
895 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
896
897 /**
Andrew Lee50aca232014-07-22 16:41:54 -0700898 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700899 *
900 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -0700901 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700902 */
Andrew Lee50aca232014-07-22 16:41:54 -0700903 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -0700904
905 /**
906 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
907 * up their UI for the {@code Call} in response to state transitions. Specifically,
908 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
909 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
910 * clients should wait for this method to be invoked.
911 *
912 * @param call The {@code Call} being destroyed.
913 */
914 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700915
916 /**
917 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
918 * conferenced.
919 *
920 * @param call The {@code Call} being updated.
921 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
922 * conferenced.
923 */
924 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700925
926 /**
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -0700927 * Invoked when a {@link Call} receives an event from its associated {@link Connection}.
928 * <p>
929 * Where possible, the Call should make an attempt to handle {@link Connection} events which
930 * are part of the {@code android.telecom.*} namespace. The Call should ignore any events
931 * it does not wish to handle. Unexpected events should be handled gracefully, as it is
932 * possible that a {@link ConnectionService} has defined its own Connection events which a
933 * Call is not aware of.
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700934 * <p>
935 * See {@link Connection#sendConnectionEvent(String, Bundle)}.
936 *
937 * @param call The {@code Call} receiving the event.
938 * @param event The event.
939 * @param extras Extras associated with the connection event.
940 */
941 public void onConnectionEvent(Call call, String event, Bundle extras) {}
Hall Liu95d55872017-01-25 17:12:49 -0800942
943 /**
944 * Invoked when the RTT mode changes for this call.
945 * @param call The call whose RTT mode has changed.
946 * @param mode the new RTT mode, one of
947 * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
948 * or {@link RttCall#RTT_MODE_VCO}
949 */
950 public void onRttModeChanged(Call call, int mode) {}
951
952 /**
953 * Invoked when the call's RTT status changes, either from off to on or from on to off.
954 * @param call The call whose RTT status has changed.
955 * @param enabled whether RTT is now enabled or disabled
956 * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
957 * on, null otherwise.
958 */
959 public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
960
961 /**
962 * Invoked when the remote end of the connection has requested that an RTT communication
963 * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
964 * with the same ID that this method is invoked with.
965 * @param call The call which the RTT request was placed on
966 * @param id The ID of the request.
967 */
968 public void onRttRequest(Call call, int id) {}
Hall Liu57006aa2017-02-06 10:49:48 -0800969
970 /**
971 * Invoked when the RTT session failed to initiate for some reason, including rejection
972 * by the remote party.
973 * @param call The call which the RTT initiation failure occurred on.
974 * @param reason One of the status codes defined in
975 * {@link android.telecom.Connection.RttModifyStatus}, with the exception of
976 * {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
977 */
978 public void onRttInitiationFailure(Call call, int reason) {}
Hall Liu95d55872017-01-25 17:12:49 -0800979 }
980
981 /**
982 * A class that holds the state that describes the state of the RTT channel to the remote
983 * party, if it is active.
984 */
985 public static final class RttCall {
Hall Liu07094df2017-02-28 15:17:44 -0800986 /** @hide */
Hall Liu95d55872017-01-25 17:12:49 -0800987 @Retention(RetentionPolicy.SOURCE)
988 @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
989 public @interface RttAudioMode {}
990
991 /**
992 * For metrics use. Default value in the proto.
993 * @hide
994 */
995 public static final int RTT_MODE_INVALID = 0;
996
997 /**
998 * Indicates that there should be a bidirectional audio stream between the two parties
999 * on the call.
1000 */
1001 public static final int RTT_MODE_FULL = 1;
1002
1003 /**
1004 * Indicates that the local user should be able to hear the audio stream from the remote
1005 * user, but not vice versa. Equivalent to muting the microphone.
1006 */
1007 public static final int RTT_MODE_HCO = 2;
1008
1009 /**
1010 * Indicates that the remote user should be able to hear the audio stream from the local
1011 * user, but not vice versa. Equivalent to setting the volume to zero.
1012 */
1013 public static final int RTT_MODE_VCO = 3;
1014
1015 private static final int READ_BUFFER_SIZE = 1000;
1016
1017 private InputStreamReader mReceiveStream;
1018 private OutputStreamWriter mTransmitStream;
1019 private int mRttMode;
1020 private final InCallAdapter mInCallAdapter;
Hall Liu57006aa2017-02-06 10:49:48 -08001021 private final String mTelecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001022 private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
1023
1024 /**
1025 * @hide
1026 */
Hall Liu57006aa2017-02-06 10:49:48 -08001027 public RttCall(String telecomCallId, InputStreamReader receiveStream,
1028 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
1029 mTelecomCallId = telecomCallId;
Hall Liu95d55872017-01-25 17:12:49 -08001030 mReceiveStream = receiveStream;
1031 mTransmitStream = transmitStream;
1032 mRttMode = mode;
1033 mInCallAdapter = inCallAdapter;
1034 }
1035
1036 /**
1037 * Returns the current RTT audio mode.
1038 * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
1039 * {@link #RTT_MODE_HCO}.
1040 */
1041 public int getRttAudioMode() {
1042 return mRttMode;
1043 }
1044
1045 /**
1046 * Sets the RTT audio mode. The requested mode change will be communicated through
1047 * {@link Callback#onRttModeChanged(Call, int)}.
1048 * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
1049 * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
1050 */
1051 public void setRttMode(@RttAudioMode int mode) {
Hall Liu57006aa2017-02-06 10:49:48 -08001052 mInCallAdapter.setRttMode(mTelecomCallId, mode);
Hall Liu95d55872017-01-25 17:12:49 -08001053 }
1054
1055 /**
1056 * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
1057 * RTT transmits text in real-time, this method should be called once for each character
1058 * the user enters into the device.
1059 *
1060 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1061 * lead to interleaved text.
1062 * @param input The message to send to the remote user.
1063 */
1064 public void write(String input) throws IOException {
1065 mTransmitStream.write(input);
1066 mTransmitStream.flush();
1067 }
1068
1069 /**
1070 * Reads a string from the remote user, blocking if there is no data available. Returns
1071 * {@code null} if the RTT conversation has been terminated and there is no further data
1072 * to read.
1073 *
1074 * This method is not thread-safe -- calling it from multiple threads simultaneously may
1075 * lead to interleaved text.
1076 * @return A string containing text sent by the remote user, or {@code null} if the
1077 * conversation has been terminated or if there was an error while reading.
1078 */
Jeff Sharkey90396362017-06-12 16:26:53 -06001079 public String read() throws IOException {
1080 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1081 if (numRead < 0) {
1082 return null;
Hall Liuffa4a812017-03-02 16:11:00 -08001083 }
Jeff Sharkey90396362017-06-12 16:26:53 -06001084 return new String(mReadBuffer, 0, numRead);
Hall Liuffa4a812017-03-02 16:11:00 -08001085 }
1086
1087 /**
1088 * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
1089 * be read.
1090 * @return A string containing text entered by the user, or {@code null} if the user has
1091 * not entered any new text yet.
1092 */
1093 public String readImmediately() throws IOException {
1094 if (mReceiveStream.ready()) {
1095 return read();
1096 } else {
Hall Liu95d55872017-01-25 17:12:49 -08001097 return null;
1098 }
1099 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001100 }
1101
Andrew Leeda80c872015-04-15 14:09:50 -07001102 /**
1103 * @deprecated Use {@code Call.Callback} instead.
1104 * @hide
1105 */
1106 @Deprecated
1107 @SystemApi
1108 public static abstract class Listener extends Callback { }
1109
Ihab Awade63fadb2014-07-09 21:52:04 -07001110 private final Phone mPhone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001111 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001112 private final InCallAdapter mInCallAdapter;
Santos Cordon823fd3c2014-08-07 18:35:18 -07001113 private final List<String> mChildrenIds = new ArrayList<>();
Ihab Awade63fadb2014-07-09 21:52:04 -07001114 private final List<Call> mChildren = new ArrayList<>();
1115 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Andrew Lee011728f2015-04-23 15:47:06 -07001116 private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001117 private final List<Call> mConferenceableCalls = new ArrayList<>();
1118 private final List<Call> mUnmodifiableConferenceableCalls =
1119 Collections.unmodifiableList(mConferenceableCalls);
1120
Santos Cordon823fd3c2014-08-07 18:35:18 -07001121 private boolean mChildrenCached;
1122 private String mParentId = null;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001123 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -07001124 private List<String> mCannedTextResponses = null;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001125 private String mCallingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001126 private int mTargetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07001127 private String mRemainingPostDialSequence;
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001128 private VideoCallImpl mVideoCallImpl;
Hall Liu95d55872017-01-25 17:12:49 -08001129 private RttCall mRttCall;
Ihab Awade63fadb2014-07-09 21:52:04 -07001130 private Details mDetails;
Tyler Gunndee56a82016-03-23 16:06:34 -07001131 private Bundle mExtras;
Ihab Awade63fadb2014-07-09 21:52:04 -07001132
1133 /**
1134 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
1135 *
1136 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
1137 * remaining or this {@code Call} is not in a post-dial state.
1138 */
1139 public String getRemainingPostDialSequence() {
1140 return mRemainingPostDialSequence;
1141 }
1142
1143 /**
1144 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001145 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -07001146 */
Andrew Lee8da4c3c2014-07-16 10:11:42 -07001147 public void answer(int videoState) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001148 mInCallAdapter.answerCall(mTelecomCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -07001149 }
1150
1151 /**
1152 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
1153 *
1154 * @param rejectWithMessage Whether to reject with a text message.
1155 * @param textMessage An optional text message with which to respond.
1156 */
1157 public void reject(boolean rejectWithMessage, String textMessage) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001158 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
Ihab Awade63fadb2014-07-09 21:52:04 -07001159 }
1160
1161 /**
1162 * Instructs this {@code Call} to disconnect.
1163 */
1164 public void disconnect() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001165 mInCallAdapter.disconnectCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001166 }
1167
1168 /**
1169 * Instructs this {@code Call} to go on hold.
1170 */
1171 public void hold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001172 mInCallAdapter.holdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001173 }
1174
1175 /**
1176 * Instructs this {@link #STATE_HOLDING} call to release from hold.
1177 */
1178 public void unhold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001179 mInCallAdapter.unholdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001180 }
1181
1182 /**
1183 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
1184 *
1185 * Any other currently playing DTMF tone in the specified call is immediately stopped.
1186 *
1187 * @param digit A character representing the DTMF digit for which to play the tone. This
1188 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
1189 */
1190 public void playDtmfTone(char digit) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001191 mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
Ihab Awade63fadb2014-07-09 21:52:04 -07001192 }
1193
1194 /**
1195 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
1196 * currently playing.
1197 *
1198 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
1199 * currently playing, this method will do nothing.
1200 */
1201 public void stopDtmfTone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001202 mInCallAdapter.stopDtmfTone(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001203 }
1204
1205 /**
1206 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
1207 *
1208 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
1209 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -07001210 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001211 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -07001212 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
1213 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001214 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
Andrew Leeda80c872015-04-15 14:09:50 -07001215 * {@code Call} will pause playing the tones and notify callbacks via
1216 * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
Ihab Awade63fadb2014-07-09 21:52:04 -07001217 * should display to the user an indication of this state and an affordance to continue
1218 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
1219 * app should invoke the {@link #postDialContinue(boolean)} method.
1220 *
1221 * @param proceed Whether or not to continue with the post-dial sequence.
1222 */
1223 public void postDialContinue(boolean proceed) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001224 mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
Ihab Awade63fadb2014-07-09 21:52:04 -07001225 }
1226
1227 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -07001228 * Notifies this {@code Call} that an account has been selected and to proceed with placing
Nancy Chen36c62f32014-10-21 18:36:39 -07001229 * an outgoing call. Optionally sets this account as the default account.
Nancy Chen5da0fd52014-07-08 14:16:17 -07001230 */
Nancy Chen36c62f32014-10-21 18:36:39 -07001231 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
1232 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
Nancy Chen5da0fd52014-07-08 14:16:17 -07001233
1234 }
1235
1236 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001237 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001238 *
1239 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -07001240 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001241 public void conference(Call callToConferenceWith) {
1242 if (callToConferenceWith != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001243 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001244 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001245 }
1246
1247 /**
1248 * Instructs this {@code Call} to split from any conference call with which it may be
1249 * connected.
1250 */
1251 public void splitFromConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001252 mInCallAdapter.splitFromConference(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -07001253 }
1254
1255 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001256 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001257 */
1258 public void mergeConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001259 mInCallAdapter.mergeConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001260 }
1261
1262 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -08001263 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -07001264 */
1265 public void swapConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001266 mInCallAdapter.swapConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -07001267 }
1268
1269 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001270 * Initiates a request to the {@link ConnectionService} to pull an external call to the local
1271 * device.
1272 * <p>
1273 * Calls to this method are ignored if the call does not have the
1274 * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
1275 * <p>
1276 * An {@link InCallService} will only see calls which support this method if it has the
1277 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
1278 * in its manifest.
1279 */
1280 public void pullExternalCall() {
1281 // If this isn't an external call, ignore the request.
1282 if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
1283 return;
1284 }
1285
1286 mInCallAdapter.pullExternalCall(mTelecomCallId);
1287 }
1288
1289 /**
1290 * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
1291 * the {@link ConnectionService}.
1292 * <p>
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001293 * Call events are used to communicate point in time information from an {@link InCallService}
1294 * to a {@link ConnectionService}. A {@link ConnectionService} implementation could define
1295 * events which enable the {@link InCallService}, for example, toggle a unique feature of the
1296 * {@link ConnectionService}.
1297 * <p>
1298 * A {@link ConnectionService} can communicate to the {@link InCallService} using
1299 * {@link Connection#sendConnectionEvent(String, Bundle)}.
1300 * <p>
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001301 * Events are exposed to {@link ConnectionService} implementations via
1302 * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
1303 * <p>
1304 * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
Tyler Gunn9c0eb0b2016-06-29 11:23:25 -07001305 * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
1306 * ignore some events altogether.
1307 * <p>
1308 * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
1309 * conflicts between {@link InCallService} implementations. Further, {@link InCallService}
1310 * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
1311 * they define their own event types in this namespace. When defining a custom event type,
1312 * ensure the contents of the extras {@link Bundle} is clearly defined. Extra keys for this
1313 * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
1314 * <p>
1315 * When defining events and the associated extras, it is important to keep their behavior
1316 * consistent when the associated {@link InCallService} is updated. Support for deprecated
1317 * events/extras should me maintained to ensure backwards compatibility with older
1318 * {@link ConnectionService} implementations which were built to support the older behavior.
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001319 *
1320 * @param event The connection event.
1321 * @param extras Bundle containing extra information associated with the event.
1322 */
1323 public void sendCallEvent(String event, Bundle extras) {
1324 mInCallAdapter.sendCallEvent(mTelecomCallId, event, extras);
1325 }
1326
1327 /**
Hall Liu95d55872017-01-25 17:12:49 -08001328 * Sends an RTT upgrade request to the remote end of the connection. Success is not
1329 * guaranteed, and notification of success will be via the
1330 * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1331 */
1332 public void sendRttRequest() {
Hall Liu57006aa2017-02-06 10:49:48 -08001333 mInCallAdapter.sendRttRequest(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001334 }
1335
1336 /**
1337 * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
1338 * callback.
1339 * The ID used here should be the same as the ID that was received via the callback.
1340 * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
1341 * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
1342 */
1343 public void respondToRttRequest(int id, boolean accept) {
Hall Liu57006aa2017-02-06 10:49:48 -08001344 mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
Hall Liu95d55872017-01-25 17:12:49 -08001345 }
1346
1347 /**
1348 * Terminate the RTT session on this call. The resulting state change will be notified via
1349 * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1350 */
1351 public void stopRtt() {
Hall Liu57006aa2017-02-06 10:49:48 -08001352 mInCallAdapter.stopRtt(mTelecomCallId);
Hall Liu95d55872017-01-25 17:12:49 -08001353 }
1354
1355 /**
Tyler Gunndee56a82016-03-23 16:06:34 -07001356 * Adds some extras to this {@link Call}. Existing keys are replaced and new ones are
1357 * added.
1358 * <p>
1359 * No assumptions should be made as to how an In-Call UI or service will handle these
1360 * extras. Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
1361 *
1362 * @param extras The extras to add.
1363 */
1364 public final void putExtras(Bundle extras) {
1365 if (extras == null) {
1366 return;
1367 }
1368
1369 if (mExtras == null) {
1370 mExtras = new Bundle();
1371 }
1372 mExtras.putAll(extras);
1373 mInCallAdapter.putExtras(mTelecomCallId, extras);
1374 }
1375
1376 /**
1377 * Adds a boolean extra to this {@link Call}.
1378 *
1379 * @param key The extra key.
1380 * @param value The value.
1381 * @hide
1382 */
1383 public final void putExtra(String key, boolean value) {
1384 if (mExtras == null) {
1385 mExtras = new Bundle();
1386 }
1387 mExtras.putBoolean(key, value);
1388 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1389 }
1390
1391 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001392 * Adds an integer extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001393 *
1394 * @param key The extra key.
1395 * @param value The value.
1396 * @hide
1397 */
1398 public final void putExtra(String key, int value) {
1399 if (mExtras == null) {
1400 mExtras = new Bundle();
1401 }
1402 mExtras.putInt(key, value);
1403 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1404 }
1405
1406 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001407 * Adds a string extra to this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001408 *
1409 * @param key The extra key.
1410 * @param value The value.
1411 * @hide
1412 */
1413 public final void putExtra(String key, String value) {
1414 if (mExtras == null) {
1415 mExtras = new Bundle();
1416 }
1417 mExtras.putString(key, value);
1418 mInCallAdapter.putExtra(mTelecomCallId, key, value);
1419 }
1420
1421 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001422 * Removes extras from this {@link Call}.
Tyler Gunndee56a82016-03-23 16:06:34 -07001423 *
1424 * @param keys The keys of the extras to remove.
1425 */
1426 public final void removeExtras(List<String> keys) {
1427 if (mExtras != null) {
1428 for (String key : keys) {
1429 mExtras.remove(key);
1430 }
1431 if (mExtras.size() == 0) {
1432 mExtras = null;
1433 }
1434 }
1435 mInCallAdapter.removeExtras(mTelecomCallId, keys);
1436 }
1437
1438 /**
Tyler Gunn071be6f2016-05-10 14:52:33 -07001439 * Removes extras from this {@link Call}.
1440 *
1441 * @param keys The keys of the extras to remove.
1442 */
1443 public final void removeExtras(String ... keys) {
1444 removeExtras(Arrays.asList(keys));
1445 }
1446
1447 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001448 * Obtains the parent of this {@code Call} in a conference, if any.
1449 *
1450 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
1451 * child of any conference {@code Call}s.
1452 */
1453 public Call getParent() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001454 if (mParentId != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001455 return mPhone.internalGetCallByTelecomId(mParentId);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001456 }
1457 return null;
Ihab Awade63fadb2014-07-09 21:52:04 -07001458 }
1459
1460 /**
1461 * Obtains the children of this conference {@code Call}, if any.
1462 *
1463 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
1464 * {@code List} otherwise.
1465 */
1466 public List<Call> getChildren() {
Santos Cordon823fd3c2014-08-07 18:35:18 -07001467 if (!mChildrenCached) {
1468 mChildrenCached = true;
1469 mChildren.clear();
1470
1471 for(String id : mChildrenIds) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001472 Call call = mPhone.internalGetCallByTelecomId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -07001473 if (call == null) {
1474 // At least one child was still not found, so do not save true for "cached"
1475 mChildrenCached = false;
1476 } else {
1477 mChildren.add(call);
1478 }
1479 }
1480 }
1481
Ihab Awade63fadb2014-07-09 21:52:04 -07001482 return mUnmodifiableChildren;
1483 }
1484
1485 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001486 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
1487 *
1488 * @return The list of conferenceable {@code Call}s.
1489 */
1490 public List<Call> getConferenceableCalls() {
1491 return mUnmodifiableConferenceableCalls;
1492 }
1493
1494 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001495 * Obtains the state of this {@code Call}.
1496 *
1497 * @return A state value, chosen from the {@code STATE_*} constants.
1498 */
1499 public int getState() {
1500 return mState;
1501 }
1502
1503 /**
1504 * Obtains a list of canned, pre-configured message responses to present to the user as
1505 * ways of rejecting this {@code Call} using via a text message.
1506 *
1507 * @see #reject(boolean, String)
1508 *
1509 * @return A list of canned text message responses.
1510 */
1511 public List<String> getCannedTextResponses() {
1512 return mCannedTextResponses;
1513 }
1514
1515 /**
1516 * Obtains an object that can be used to display video from this {@code Call}.
1517 *
Andrew Lee50aca232014-07-22 16:41:54 -07001518 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -07001519 */
Andrew Lee50aca232014-07-22 16:41:54 -07001520 public InCallService.VideoCall getVideoCall() {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001521 return mVideoCallImpl;
Ihab Awade63fadb2014-07-09 21:52:04 -07001522 }
1523
1524 /**
1525 * Obtains an object containing call details.
1526 *
1527 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
1528 * result may be {@code null}.
1529 */
1530 public Details getDetails() {
1531 return mDetails;
1532 }
1533
1534 /**
Hall Liu95d55872017-01-25 17:12:49 -08001535 * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
1536 * receive RTT text data, as well as to change the RTT mode.
1537 * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
1538 */
1539 public @Nullable RttCall getRttCall() {
1540 return mRttCall;
1541 }
1542
1543 /**
1544 * Returns whether this call has an active RTT connection.
1545 * @return true if there is a connection, false otherwise.
1546 */
1547 public boolean isRttActive() {
1548 return mRttCall != null;
1549 }
1550
1551 /**
Andrew Leeda80c872015-04-15 14:09:50 -07001552 * Registers a callback to this {@code Call}.
1553 *
1554 * @param callback A {@code Callback}.
1555 */
1556 public void registerCallback(Callback callback) {
Andrew Lee011728f2015-04-23 15:47:06 -07001557 registerCallback(callback, new Handler());
1558 }
1559
1560 /**
1561 * Registers a callback to this {@code Call}.
1562 *
1563 * @param callback A {@code Callback}.
1564 * @param handler A handler which command and status changes will be delivered to.
1565 */
1566 public void registerCallback(Callback callback, Handler handler) {
1567 unregisterCallback(callback);
Roshan Pius1ca62072015-07-07 17:34:51 -07001568 // Don't allow new callback registration if the call is already being destroyed.
1569 if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07001570 mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
1571 }
Andrew Leeda80c872015-04-15 14:09:50 -07001572 }
1573
1574 /**
1575 * Unregisters a callback from this {@code Call}.
1576 *
1577 * @param callback A {@code Callback}.
1578 */
1579 public void unregisterCallback(Callback callback) {
Roshan Pius1ca62072015-07-07 17:34:51 -07001580 // Don't allow callback deregistration if the call is already being destroyed.
1581 if (callback != null && mState != STATE_DISCONNECTED) {
Andrew Lee011728f2015-04-23 15:47:06 -07001582 for (CallbackRecord<Callback> record : mCallbackRecords) {
1583 if (record.getCallback() == callback) {
1584 mCallbackRecords.remove(record);
1585 break;
1586 }
1587 }
Andrew Leeda80c872015-04-15 14:09:50 -07001588 }
1589 }
1590
Santos Cordon3c20d632016-02-25 16:12:35 -08001591 @Override
1592 public String toString() {
1593 return new StringBuilder().
1594 append("Call [id: ").
1595 append(mTelecomCallId).
1596 append(", state: ").
1597 append(stateToString(mState)).
1598 append(", details: ").
1599 append(mDetails).
1600 append("]").toString();
1601 }
1602
1603 /**
1604 * @param state An integer value of a {@code STATE_*} constant.
1605 * @return A string representation of the value.
1606 */
1607 private static String stateToString(int state) {
1608 switch (state) {
1609 case STATE_NEW:
1610 return "NEW";
1611 case STATE_RINGING:
1612 return "RINGING";
1613 case STATE_DIALING:
1614 return "DIALING";
1615 case STATE_ACTIVE:
1616 return "ACTIVE";
1617 case STATE_HOLDING:
1618 return "HOLDING";
1619 case STATE_DISCONNECTED:
1620 return "DISCONNECTED";
1621 case STATE_CONNECTING:
1622 return "CONNECTING";
1623 case STATE_DISCONNECTING:
1624 return "DISCONNECTING";
1625 case STATE_SELECT_PHONE_ACCOUNT:
1626 return "SELECT_PHONE_ACCOUNT";
1627 default:
1628 Log.w(Call.class, "Unknown state %d", state);
1629 return "UNKNOWN";
1630 }
1631 }
1632
Andrew Leeda80c872015-04-15 14:09:50 -07001633 /**
Ihab Awade63fadb2014-07-09 21:52:04 -07001634 * Adds a listener to this {@code Call}.
1635 *
1636 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07001637 * @deprecated Use {@link #registerCallback} instead.
1638 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07001639 */
Andrew Leeda80c872015-04-15 14:09:50 -07001640 @Deprecated
1641 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07001642 public void addListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07001643 registerCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07001644 }
1645
1646 /**
1647 * Removes a listener from this {@code Call}.
1648 *
1649 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -07001650 * @deprecated Use {@link #unregisterCallback} instead.
1651 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -07001652 */
Andrew Leeda80c872015-04-15 14:09:50 -07001653 @Deprecated
1654 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -07001655 public void removeListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -07001656 unregisterCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -07001657 }
1658
1659 /** {@hide} */
Tyler Gunn159f35c2017-03-02 09:28:37 -08001660 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
1661 int targetSdkVersion) {
Ihab Awade63fadb2014-07-09 21:52:04 -07001662 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001663 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001664 mInCallAdapter = inCallAdapter;
1665 mState = STATE_NEW;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001666 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001667 mTargetSdkVersion = targetSdkVersion;
Ihab Awade63fadb2014-07-09 21:52:04 -07001668 }
1669
1670 /** {@hide} */
Tyler Gunnb88b3112016-11-09 10:19:23 -08001671 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
Tyler Gunn159f35c2017-03-02 09:28:37 -08001672 String callingPackage, int targetSdkVersion) {
Shriram Ganeshddf570e2015-05-31 09:18:48 -07001673 mPhone = phone;
1674 mTelecomCallId = telecomCallId;
1675 mInCallAdapter = inCallAdapter;
1676 mState = state;
Tyler Gunnb88b3112016-11-09 10:19:23 -08001677 mCallingPackage = callingPackage;
Tyler Gunn159f35c2017-03-02 09:28:37 -08001678 mTargetSdkVersion = targetSdkVersion;
Shriram Ganeshddf570e2015-05-31 09:18:48 -07001679 }
1680
1681 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07001682 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001683 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001684 }
1685
1686 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001687 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Tyler Gunnb88b3112016-11-09 10:19:23 -08001688
Ihab Awade63fadb2014-07-09 21:52:04 -07001689 // First, we update the internal state as far as possible before firing any updates.
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001690 Details details = Details.createFromParcelableCall(parcelableCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07001691 boolean detailsChanged = !Objects.equals(mDetails, details);
1692 if (detailsChanged) {
1693 mDetails = details;
1694 }
1695
1696 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -07001697 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
1698 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
1699 mCannedTextResponses =
1700 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Yorke Leee886f632015-08-04 13:43:31 -07001701 cannedTextResponsesChanged = true;
Ihab Awade63fadb2014-07-09 21:52:04 -07001702 }
1703
Tyler Gunn159f35c2017-03-02 09:28:37 -08001704 VideoCallImpl newVideoCallImpl = parcelableCall.getVideoCallImpl(mCallingPackage,
1705 mTargetSdkVersion);
Tyler Gunn75958422015-04-15 14:23:42 -07001706 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() &&
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001707 !Objects.equals(mVideoCallImpl, newVideoCallImpl);
Andrew Lee50aca232014-07-22 16:41:54 -07001708 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001709 mVideoCallImpl = newVideoCallImpl;
1710 }
1711 if (mVideoCallImpl != null) {
1712 mVideoCallImpl.setVideoState(getDetails().getVideoState());
Ihab Awade63fadb2014-07-09 21:52:04 -07001713 }
1714
Santos Cordone3c507b2015-04-23 14:44:19 -07001715 int state = parcelableCall.getState();
Ihab Awade63fadb2014-07-09 21:52:04 -07001716 boolean stateChanged = mState != state;
1717 if (stateChanged) {
1718 mState = state;
1719 }
1720
Santos Cordon823fd3c2014-08-07 18:35:18 -07001721 String parentId = parcelableCall.getParentCallId();
1722 boolean parentChanged = !Objects.equals(mParentId, parentId);
1723 if (parentChanged) {
1724 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001725 }
1726
Santos Cordon823fd3c2014-08-07 18:35:18 -07001727 List<String> childCallIds = parcelableCall.getChildCallIds();
1728 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
1729 if (childrenChanged) {
1730 mChildrenIds.clear();
1731 mChildrenIds.addAll(parcelableCall.getChildCallIds());
1732 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -07001733 }
1734
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001735 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
1736 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
1737 for (String otherId : conferenceableCallIds) {
1738 if (callIdMap.containsKey(otherId)) {
1739 conferenceableCalls.add(callIdMap.get(otherId));
1740 }
1741 }
1742
1743 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
1744 mConferenceableCalls.clear();
1745 mConferenceableCalls.addAll(conferenceableCalls);
1746 fireConferenceableCallsChanged();
1747 }
1748
Hall Liu95d55872017-01-25 17:12:49 -08001749 boolean isRttChanged = false;
1750 boolean rttModeChanged = false;
1751 if (parcelableCall.getParcelableRttCall() != null && parcelableCall.getIsRttCallChanged()) {
1752 ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
1753 InputStreamReader receiveStream = new InputStreamReader(
1754 new ParcelFileDescriptor.AutoCloseInputStream(
1755 parcelableRttCall.getReceiveStream()),
1756 StandardCharsets.UTF_8);
1757 OutputStreamWriter transmitStream = new OutputStreamWriter(
1758 new ParcelFileDescriptor.AutoCloseOutputStream(
1759 parcelableRttCall.getTransmitStream()),
1760 StandardCharsets.UTF_8);
Hall Liu57006aa2017-02-06 10:49:48 -08001761 RttCall newRttCall = new Call.RttCall(mTelecomCallId,
Hall Liu95d55872017-01-25 17:12:49 -08001762 receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
1763 if (mRttCall == null) {
1764 isRttChanged = true;
1765 } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
1766 rttModeChanged = true;
1767 }
1768 mRttCall = newRttCall;
1769 } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
1770 && parcelableCall.getIsRttCallChanged()) {
1771 isRttChanged = true;
1772 mRttCall = null;
1773 }
1774
Ihab Awade63fadb2014-07-09 21:52:04 -07001775 // Now we fire updates, ensuring that any client who listens to any of these notifications
1776 // gets the most up-to-date state.
1777
1778 if (stateChanged) {
1779 fireStateChanged(mState);
1780 }
1781 if (detailsChanged) {
1782 fireDetailsChanged(mDetails);
1783 }
1784 if (cannedTextResponsesChanged) {
1785 fireCannedTextResponsesLoaded(mCannedTextResponses);
1786 }
Andrew Lee50aca232014-07-22 16:41:54 -07001787 if (videoCallChanged) {
Tyler Gunn584ba6c2015-12-08 10:53:41 -08001788 fireVideoCallChanged(mVideoCallImpl);
Ihab Awade63fadb2014-07-09 21:52:04 -07001789 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07001790 if (parentChanged) {
1791 fireParentChanged(getParent());
1792 }
1793 if (childrenChanged) {
1794 fireChildrenChanged(getChildren());
1795 }
Hall Liu95d55872017-01-25 17:12:49 -08001796 if (isRttChanged) {
1797 fireOnIsRttChanged(mRttCall != null, mRttCall);
1798 }
1799 if (rttModeChanged) {
1800 fireOnRttModeChanged(mRttCall.getRttAudioMode());
1801 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001802
1803 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
1804 // remove ourselves from the Phone. Note that we do this after completing all state updates
1805 // so a client can cleanly transition all their UI to the state appropriate for a
1806 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
1807 if (mState == STATE_DISCONNECTED) {
1808 fireCallDestroyed();
Ihab Awade63fadb2014-07-09 21:52:04 -07001809 }
1810 }
1811
1812 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07001813 final void internalSetPostDialWait(String remaining) {
1814 mRemainingPostDialSequence = remaining;
1815 firePostDialWait(mRemainingPostDialSequence);
1816 }
1817
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07001818 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -07001819 final void internalSetDisconnected() {
1820 if (mState != Call.STATE_DISCONNECTED) {
1821 mState = Call.STATE_DISCONNECTED;
1822 fireStateChanged(mState);
1823 fireCallDestroyed();
Santos Cordonf30d7e92014-08-26 09:54:33 -07001824 }
1825 }
1826
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001827 /** {@hide} */
1828 final void internalOnConnectionEvent(String event, Bundle extras) {
1829 fireOnConnectionEvent(event, extras);
1830 }
1831
Hall Liu95d55872017-01-25 17:12:49 -08001832 /** {@hide} */
1833 final void internalOnRttUpgradeRequest(final int requestId) {
1834 for (CallbackRecord<Callback> record : mCallbackRecords) {
1835 final Call call = this;
1836 final Callback callback = record.getCallback();
1837 record.getHandler().post(() -> callback.onRttRequest(call, requestId));
1838 }
1839 }
1840
Hall Liu57006aa2017-02-06 10:49:48 -08001841 /** @hide */
1842 final void internalOnRttInitiationFailure(int reason) {
1843 for (CallbackRecord<Callback> record : mCallbackRecords) {
1844 final Call call = this;
1845 final Callback callback = record.getCallback();
1846 record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
1847 }
1848 }
1849
Andrew Lee011728f2015-04-23 15:47:06 -07001850 private void fireStateChanged(final int newState) {
1851 for (CallbackRecord<Callback> record : mCallbackRecords) {
1852 final Call call = this;
1853 final Callback callback = record.getCallback();
1854 record.getHandler().post(new Runnable() {
1855 @Override
1856 public void run() {
1857 callback.onStateChanged(call, newState);
1858 }
1859 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001860 }
1861 }
1862
Andrew Lee011728f2015-04-23 15:47:06 -07001863 private void fireParentChanged(final Call newParent) {
1864 for (CallbackRecord<Callback> record : mCallbackRecords) {
1865 final Call call = this;
1866 final Callback callback = record.getCallback();
1867 record.getHandler().post(new Runnable() {
1868 @Override
1869 public void run() {
1870 callback.onParentChanged(call, newParent);
1871 }
1872 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001873 }
1874 }
1875
Andrew Lee011728f2015-04-23 15:47:06 -07001876 private void fireChildrenChanged(final List<Call> children) {
1877 for (CallbackRecord<Callback> record : mCallbackRecords) {
1878 final Call call = this;
1879 final Callback callback = record.getCallback();
1880 record.getHandler().post(new Runnable() {
1881 @Override
1882 public void run() {
1883 callback.onChildrenChanged(call, children);
1884 }
1885 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001886 }
1887 }
1888
Andrew Lee011728f2015-04-23 15:47:06 -07001889 private void fireDetailsChanged(final Details details) {
1890 for (CallbackRecord<Callback> record : mCallbackRecords) {
1891 final Call call = this;
1892 final Callback callback = record.getCallback();
1893 record.getHandler().post(new Runnable() {
1894 @Override
1895 public void run() {
1896 callback.onDetailsChanged(call, details);
1897 }
1898 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001899 }
1900 }
1901
Andrew Lee011728f2015-04-23 15:47:06 -07001902 private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
1903 for (CallbackRecord<Callback> record : mCallbackRecords) {
1904 final Call call = this;
1905 final Callback callback = record.getCallback();
1906 record.getHandler().post(new Runnable() {
1907 @Override
1908 public void run() {
1909 callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
1910 }
1911 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001912 }
1913 }
1914
Andrew Lee011728f2015-04-23 15:47:06 -07001915 private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
1916 for (CallbackRecord<Callback> record : mCallbackRecords) {
1917 final Call call = this;
1918 final Callback callback = record.getCallback();
1919 record.getHandler().post(new Runnable() {
1920 @Override
1921 public void run() {
1922 callback.onVideoCallChanged(call, videoCall);
1923 }
1924 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001925 }
1926 }
1927
Andrew Lee011728f2015-04-23 15:47:06 -07001928 private void firePostDialWait(final String remainingPostDialSequence) {
1929 for (CallbackRecord<Callback> record : mCallbackRecords) {
1930 final Call call = this;
1931 final Callback callback = record.getCallback();
1932 record.getHandler().post(new Runnable() {
1933 @Override
1934 public void run() {
1935 callback.onPostDialWait(call, remainingPostDialSequence);
1936 }
1937 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001938 }
1939 }
1940
1941 private void fireCallDestroyed() {
Roshan Pius1ca62072015-07-07 17:34:51 -07001942 /**
1943 * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
1944 * onCallRemoved callback, we remove this call from the Phone's record
1945 * only once all of the registered onCallDestroyed callbacks are executed.
1946 * All the callbacks get removed from our records as a part of this operation
1947 * since onCallDestroyed is the final callback.
1948 */
1949 final Call call = this;
1950 if (mCallbackRecords.isEmpty()) {
1951 // No callbacks registered, remove the call from Phone's record.
1952 mPhone.internalRemoveCall(call);
1953 }
1954 for (final CallbackRecord<Callback> record : mCallbackRecords) {
Andrew Lee011728f2015-04-23 15:47:06 -07001955 final Callback callback = record.getCallback();
1956 record.getHandler().post(new Runnable() {
1957 @Override
1958 public void run() {
Roshan Pius1ca62072015-07-07 17:34:51 -07001959 boolean isFinalRemoval = false;
1960 RuntimeException toThrow = null;
1961 try {
1962 callback.onCallDestroyed(call);
1963 } catch (RuntimeException e) {
1964 toThrow = e;
1965 }
1966 synchronized(Call.this) {
1967 mCallbackRecords.remove(record);
1968 if (mCallbackRecords.isEmpty()) {
1969 isFinalRemoval = true;
1970 }
1971 }
1972 if (isFinalRemoval) {
1973 mPhone.internalRemoveCall(call);
1974 }
1975 if (toThrow != null) {
1976 throw toThrow;
1977 }
Andrew Lee011728f2015-04-23 15:47:06 -07001978 }
1979 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001980 }
1981 }
1982
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001983 private void fireConferenceableCallsChanged() {
Andrew Lee011728f2015-04-23 15:47:06 -07001984 for (CallbackRecord<Callback> record : mCallbackRecords) {
1985 final Call call = this;
1986 final Callback callback = record.getCallback();
1987 record.getHandler().post(new Runnable() {
1988 @Override
1989 public void run() {
1990 callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
1991 }
1992 });
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001993 }
1994 }
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07001995
1996 /**
Tyler Gunn876dbfb2016-03-14 15:18:07 -07001997 * Notifies listeners of an incoming connection event.
1998 * <p>
1999 * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
2000 *
2001 * @param event
2002 * @param extras
2003 */
2004 private void fireOnConnectionEvent(final String event, final Bundle extras) {
2005 for (CallbackRecord<Callback> record : mCallbackRecords) {
2006 final Call call = this;
2007 final Callback callback = record.getCallback();
2008 record.getHandler().post(new Runnable() {
2009 @Override
2010 public void run() {
2011 callback.onConnectionEvent(call, event, extras);
2012 }
2013 });
2014 }
2015 }
2016
2017 /**
Hall Liu95d55872017-01-25 17:12:49 -08002018 * Notifies listeners of an RTT on/off change
2019 *
2020 * @param enabled True if RTT is now enabled, false otherwise
2021 */
2022 private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
2023 for (CallbackRecord<Callback> record : mCallbackRecords) {
2024 final Call call = this;
2025 final Callback callback = record.getCallback();
2026 record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
2027 }
2028 }
2029
2030 /**
2031 * Notifies listeners of a RTT mode change
2032 *
2033 * @param mode The new RTT mode
2034 */
2035 private void fireOnRttModeChanged(final int mode) {
2036 for (CallbackRecord<Callback> record : mCallbackRecords) {
2037 final Call call = this;
2038 final Callback callback = record.getCallback();
2039 record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
2040 }
2041 }
2042
2043 /**
Tyler Gunn1e9bfc62015-08-19 11:18:58 -07002044 * Determines if two bundles are equal.
2045 *
2046 * @param bundle The original bundle.
2047 * @param newBundle The bundle to compare with.
2048 * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
2049 */
2050 private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
2051 if (bundle == null || newBundle == null) {
2052 return bundle == newBundle;
2053 }
2054
2055 if (bundle.size() != newBundle.size()) {
2056 return false;
2057 }
2058
2059 for(String key : bundle.keySet()) {
2060 if (key != null) {
2061 final Object value = bundle.get(key);
2062 final Object newValue = newBundle.get(key);
2063 if (!Objects.equals(value, newValue)) {
2064 return false;
2065 }
2066 }
2067 }
2068 return true;
2069 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07002070}