blob: 43ca153bc15a982d6bb63b271d80cef5a248b276 [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
19import android.net.Uri;
Nancy Chen10798dc2014-08-08 14:00:25 -070020import android.os.Bundle;
Ihab Awade63fadb2014-07-09 21:52:04 -070021
Andrew Lee50aca232014-07-22 16:41:54 -070022import java.lang.String;
Ihab Awade63fadb2014-07-09 21:52:04 -070023import java.util.ArrayList;
24import java.util.Collections;
25import java.util.List;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070026import java.util.Map;
Ihab Awade63fadb2014-07-09 21:52:04 -070027import java.util.Objects;
Jay Shrauner229e3822014-08-15 09:23:07 -070028import java.util.concurrent.CopyOnWriteArrayList;
Ihab Awade63fadb2014-07-09 21:52:04 -070029
30/**
31 * Represents an ongoing phone call that the in-call app should present to the user.
32 */
33public final class Call {
34 /**
35 * The state of a {@code Call} when newly created.
36 */
37 public static final int STATE_NEW = 0;
38
39 /**
40 * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
41 */
42 public static final int STATE_DIALING = 1;
43
44 /**
45 * The state of an incoming {@code Call} when ringing locally, but not yet connected.
46 */
47 public static final int STATE_RINGING = 2;
48
49 /**
50 * The state of a {@code Call} when in a holding state.
51 */
52 public static final int STATE_HOLDING = 3;
53
54 /**
55 * The state of a {@code Call} when actively supporting conversation.
56 */
57 public static final int STATE_ACTIVE = 4;
58
59 /**
60 * The state of a {@code Call} when no further voice or other communication is being
61 * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
62 * is no longer active, and the local data transport has or inevitably will release resources
63 * associated with this {@code Call}.
64 */
65 public static final int STATE_DISCONNECTED = 7;
66
Nancy Chen5da0fd52014-07-08 14:16:17 -070067 /**
68 * The state of an outgoing {@code Call}, but waiting for user input before proceeding.
69 */
70 public static final int STATE_PRE_DIAL_WAIT = 8;
71
Nancy Chene20930f2014-08-07 16:17:21 -070072 /**
Nancy Chene9b7a8e2014-08-08 14:26:27 -070073 * The initial state of an outgoing {@code Call}.
74 * Common transitions are to {@link #STATE_DIALING} state for a successful call or
75 * {@link #STATE_DISCONNECTED} if it failed.
Nancy Chene20930f2014-08-07 16:17:21 -070076 */
77 public static final int STATE_CONNECTING = 9;
78
Nancy Chen513c8922014-09-17 14:47:20 -070079 /**
Tyler Gunn4afc6af2014-10-07 10:14:55 -070080 * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
81 * call has not yet been disconnected by the underlying {@code ConnectionService}. The next
82 * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
83 */
84 public static final int STATE_DISCONNECTING = 10;
85
86 /**
Nancy Chen513c8922014-09-17 14:47:20 -070087 * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
88 * extras. Used to pass the phone accounts to display on the front end to the user in order to
89 * select phone accounts to (for example) place a call.
Nancy Chen513c8922014-09-17 14:47:20 -070090 */
91 public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
92
Ihab Awade63fadb2014-07-09 21:52:04 -070093 public static class Details {
Ihab Awad5c9c86e2014-11-12 13:41:16 -080094
95 /** Call can currently be put on hold or unheld. */
96 public static final int CAPABILITY_HOLD = 0x00000001;
97
98 /** Call supports the hold feature. */
99 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
100
101 /**
102 * Calls within a conference can be merged. A {@link ConnectionService} has the option to
103 * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
104 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
105 * capability allows a merge button to be shown while the conference call is in the foreground
106 * of the in-call UI.
107 * <p>
108 * This is only intended for use by a {@link Conference}.
109 */
110 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
111
112 /**
113 * Calls within a conference can be swapped between foreground and background.
114 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
115 * <p>
116 * This is only intended for use by a {@link Conference}.
117 */
118 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
119
120 /**
121 * @hide
122 */
123 public static final int CAPABILITY_UNUSED = 0x00000010;
124
125 /** Call supports responding via text option. */
126 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
127
128 /** Call can be muted. */
129 public static final int CAPABILITY_MUTE = 0x00000040;
130
131 /**
132 * Call supports conference call management. This capability only applies to {@link Conference}
133 * calls which can have {@link Connection}s as children.
134 */
135 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
136
137 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700138 * Local device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800139 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700140 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800141
142 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700143 * Local device supports transmitting video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800144 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700145 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800146
147 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700148 * Local device supports bidirectional video calling.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800149 */
Andrew Leee268f4c2015-04-15 12:23:42 -0700150 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700151 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800152
153 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700154 * Remote device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800155 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700156 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
157
158 /**
159 * Remote device supports transmitting video.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700160 */
161 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
162
163 /**
164 * Remote device supports bidirectional video calling.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700165 */
Andrew Leee268f4c2015-04-15 12:23:42 -0700166 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700167 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800168
169 /**
170 * Call is able to be separated from its parent {@code Conference}, if any.
171 */
172 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
173
174 /**
175 * Call is able to be individually disconnected when in a {@code Conference}.
176 */
177 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
Andrew Leee268f4c2015-04-15 12:23:42 -0700178
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800179 /**
180 * Whether the call is a generic conference, where we do not know the precise state of
181 * participants in the conference (eg. on CDMA).
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800182 */
183 public static final int CAPABILITY_GENERIC_CONFERENCE = 0x00004000;
184
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700185 /**
186 * Call is using high definition audio.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700187 */
188 public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00008000;
189
190 /**
191 * Call is using WIFI.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700192 */
193 public static final int CAPABILITY_WIFI = 0x00010000;
194
Tyler Gunn068085b2015-02-06 13:56:52 -0800195 /**
196 * Indicates that the current device callback number should be shown.
Tyler Gunn068085b2015-02-06 13:56:52 -0800197 */
Tyler Gunnd11a3152015-03-18 13:09:14 -0700198 public static final int CAPABILITY_SHOW_CALLBACK_NUMBER = 0x00020000;
199
200 /**
Dong Zhou89f41eb2015-03-15 11:59:49 -0500201 * Speed up audio setup for MT call.
202 * @hide
203 */
Tyler Gunnd11a3152015-03-18 13:09:14 -0700204 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
205
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700206 /**
207 * Call can be upgraded to a video call.
Rekha Kumar07366812015-03-24 16:42:31 -0700208 * @hide
209 */
210 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
211
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700212 /**
213 * For video calls, indicates whether the outgoing video for the call can be paused using
214 * the {@link android.telecom.VideoProfile.VideoState#PAUSED} VideoState.
215 * @hide
216 */
217 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
218
Tyler Gunnd11a3152015-03-18 13:09:14 -0700219 //******************************************************************************************
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700220 // Next CAPABILITY value: 0x00200000
Tyler Gunnd11a3152015-03-18 13:09:14 -0700221 //******************************************************************************************
Tyler Gunn068085b2015-02-06 13:56:52 -0800222
Ihab Awade63fadb2014-07-09 21:52:04 -0700223 private final Uri mHandle;
224 private final int mHandlePresentation;
225 private final String mCallerDisplayName;
226 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700227 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700228 private final int mCallCapabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700229 private final int mCallProperties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700230 private final DisconnectCause mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700231 private final long mConnectTimeMillis;
232 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700233 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700234 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700235 private final Bundle mExtras;
Ihab Awade63fadb2014-07-09 21:52:04 -0700236
237 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800238 * Whether the supplied capabilities supports the specified capability.
239 *
240 * @param capabilities A bit field of capabilities.
241 * @param capability The capability to check capabilities for.
242 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800243 */
244 public static boolean can(int capabilities, int capability) {
245 return (capabilities & capability) != 0;
246 }
247
248 /**
249 * Whether the capabilities of this {@code Details} supports the specified capability.
250 *
251 * @param capability The capability to check capabilities for.
252 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800253 */
254 public boolean can(int capability) {
255 return can(mCallCapabilities, capability);
256 }
257
258 /**
259 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
260 *
261 * @param capabilities A capability bit field.
262 * @return A human readable string representation.
263 */
264 public static String capabilitiesToString(int capabilities) {
265 StringBuilder builder = new StringBuilder();
266 builder.append("[Capabilities:");
267 if (can(capabilities, CAPABILITY_HOLD)) {
268 builder.append(" CAPABILITY_HOLD");
269 }
270 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
271 builder.append(" CAPABILITY_SUPPORT_HOLD");
272 }
273 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
274 builder.append(" CAPABILITY_MERGE_CONFERENCE");
275 }
276 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
277 builder.append(" CAPABILITY_SWAP_CONFERENCE");
278 }
279 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
280 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
281 }
282 if (can(capabilities, CAPABILITY_MUTE)) {
283 builder.append(" CAPABILITY_MUTE");
284 }
285 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
286 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
287 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700288 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
289 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
290 }
291 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
292 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
293 }
Andrew Leee268f4c2015-04-15 12:23:42 -0700294 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
295 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800296 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700297 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
298 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
299 }
300 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
301 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
302 }
Andrew Leee268f4c2015-04-15 12:23:42 -0700303 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
304 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800305 }
Andrew Lee80fff3c2014-11-25 17:36:51 -0800306 if (can(capabilities, CAPABILITY_HIGH_DEF_AUDIO)) {
307 builder.append(" CAPABILITY_HIGH_DEF_AUDIO");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800308 }
Andrew Lee1a8ae3e2015-02-02 13:42:38 -0800309 if (can(capabilities, CAPABILITY_WIFI)) {
310 builder.append(" CAPABILITY_WIFI");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800311 }
312 if (can(capabilities, CAPABILITY_GENERIC_CONFERENCE)) {
313 builder.append(" CAPABILITY_GENERIC_CONFERENCE");
314 }
Tyler Gunn068085b2015-02-06 13:56:52 -0800315 if (can(capabilities, CAPABILITY_SHOW_CALLBACK_NUMBER)) {
316 builder.append(" CAPABILITY_SHOW_CALLBACK_NUMBER");
317 }
Dong Zhou89f41eb2015-03-15 11:59:49 -0500318 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
Tyler Gunnd11a3152015-03-18 13:09:14 -0700319 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
Dong Zhou89f41eb2015-03-15 11:59:49 -0500320 }
Rekha Kumar07366812015-03-24 16:42:31 -0700321 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
322 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
323 }
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700324 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
325 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
326 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800327 builder.append("]");
328 return builder.toString();
329 }
330
331 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700332 * @return The handle (e.g., phone number) to which the {@code Call} is currently
333 * connected.
334 */
335 public Uri getHandle() {
336 return mHandle;
337 }
338
339 /**
340 * @return The presentation requirements for the handle. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700341 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700342 */
343 public int getHandlePresentation() {
344 return mHandlePresentation;
345 }
346
347 /**
348 * @return The display name for the caller.
349 */
350 public String getCallerDisplayName() {
351 return mCallerDisplayName;
352 }
353
354 /**
355 * @return The presentation requirements for the caller display name. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700356 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700357 */
358 public int getCallerDisplayNamePresentation() {
359 return mCallerDisplayNamePresentation;
360 }
361
362 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700363 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
364 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700365 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700366 public PhoneAccountHandle getAccountHandle() {
367 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -0700368 }
369
370 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800371 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
372 * {@code CAPABILITY_*} constants in this class.
Ihab Awade63fadb2014-07-09 21:52:04 -0700373 */
Ihab Awad5d0410f2014-07-30 10:07:40 -0700374 public int getCallCapabilities() {
375 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700376 }
377
378 /**
Andrew Lee223ad142014-08-27 16:33:08 -0700379 * @return A bitmask of the properties of the {@code Call}, as defined in
380 * {@link CallProperties}.
381 */
382 public int getCallProperties() {
383 return mCallProperties;
384 }
385
386 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700387 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
Nancy Chenf4cf77c2014-09-19 10:53:21 -0700388 * by {@link android.telecom.DisconnectCause}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700389 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700390 public DisconnectCause getDisconnectCause() {
391 return mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700392 }
393
394 /**
395 * @return The time the {@code Call} has been connected. This information is updated
396 * periodically, but user interfaces should not rely on this to display any "call time
397 * clock".
398 */
Jay Shrauner193de662015-04-14 18:16:10 -0700399 public final long getConnectTimeMillis() {
Ihab Awade63fadb2014-07-09 21:52:04 -0700400 return mConnectTimeMillis;
401 }
402
403 /**
404 * @return Information about any calling gateway the {@code Call} may be using.
405 */
406 public GatewayInfo getGatewayInfo() {
407 return mGatewayInfo;
408 }
409
Andrew Lee7a341382014-07-15 17:05:08 -0700410 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -0700411 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -0700412 */
413 public int getVideoState() {
414 return mVideoState;
415 }
416
Ihab Awad5d0410f2014-07-30 10:07:40 -0700417 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700418 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
Ihab Awad5d0410f2014-07-30 10:07:40 -0700419 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -0700420 */
421 public StatusHints getStatusHints() {
422 return mStatusHints;
423 }
424
Nancy Chen10798dc2014-08-08 14:00:25 -0700425 /**
426 * @return A bundle extras to pass with the call
427 */
428 public Bundle getExtras() {
429 return mExtras;
430 }
431
Ihab Awade63fadb2014-07-09 21:52:04 -0700432 @Override
433 public boolean equals(Object o) {
434 if (o instanceof Details) {
435 Details d = (Details) o;
436 return
437 Objects.equals(mHandle, d.mHandle) &&
438 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
439 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
440 Objects.equals(mCallerDisplayNamePresentation,
441 d.mCallerDisplayNamePresentation) &&
Evan Charlton8c8a0622014-07-20 12:31:00 -0700442 Objects.equals(mAccountHandle, d.mAccountHandle) &&
Ihab Awad5d0410f2014-07-30 10:07:40 -0700443 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Andrew Lee223ad142014-08-27 16:33:08 -0700444 Objects.equals(mCallProperties, d.mCallProperties) &&
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700445 Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
Ihab Awade63fadb2014-07-09 21:52:04 -0700446 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Andrew Lee85f5d422014-07-11 17:22:03 -0700447 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Evan Charlton5b49ade2014-07-15 17:03:20 -0700448 Objects.equals(mVideoState, d.mVideoState) &&
Nancy Chen10798dc2014-08-08 14:00:25 -0700449 Objects.equals(mStatusHints, d.mStatusHints) &&
Jay Shrauner6f20a6a2015-04-16 12:52:19 -0700450 Objects.equals(mExtras, d.mExtras);
Ihab Awade63fadb2014-07-09 21:52:04 -0700451 }
452 return false;
453 }
454
455 @Override
456 public int hashCode() {
457 return
458 Objects.hashCode(mHandle) +
459 Objects.hashCode(mHandlePresentation) +
460 Objects.hashCode(mCallerDisplayName) +
461 Objects.hashCode(mCallerDisplayNamePresentation) +
Evan Charlton8c8a0622014-07-20 12:31:00 -0700462 Objects.hashCode(mAccountHandle) +
Ihab Awad5d0410f2014-07-30 10:07:40 -0700463 Objects.hashCode(mCallCapabilities) +
Andrew Lee223ad142014-08-27 16:33:08 -0700464 Objects.hashCode(mCallProperties) +
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700465 Objects.hashCode(mDisconnectCause) +
Ihab Awade63fadb2014-07-09 21:52:04 -0700466 Objects.hashCode(mConnectTimeMillis) +
Andrew Lee85f5d422014-07-11 17:22:03 -0700467 Objects.hashCode(mGatewayInfo) +
Evan Charlton5b49ade2014-07-15 17:03:20 -0700468 Objects.hashCode(mVideoState) +
Nancy Chen10798dc2014-08-08 14:00:25 -0700469 Objects.hashCode(mStatusHints) +
Jay Shrauner6f20a6a2015-04-16 12:52:19 -0700470 Objects.hashCode(mExtras);
Ihab Awade63fadb2014-07-09 21:52:04 -0700471 }
472
473 /** {@hide} */
474 public Details(
475 Uri handle,
476 int handlePresentation,
477 String callerDisplayName,
478 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -0700479 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -0700480 int capabilities,
Andrew Lee223ad142014-08-27 16:33:08 -0700481 int properties,
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700482 DisconnectCause disconnectCause,
Ihab Awade63fadb2014-07-09 21:52:04 -0700483 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -0700484 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -0700485 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -0700486 StatusHints statusHints,
Jay Shrauner6f20a6a2015-04-16 12:52:19 -0700487 Bundle extras) {
Ihab Awade63fadb2014-07-09 21:52:04 -0700488 mHandle = handle;
489 mHandlePresentation = handlePresentation;
490 mCallerDisplayName = callerDisplayName;
491 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700492 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700493 mCallCapabilities = capabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700494 mCallProperties = properties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700495 mDisconnectCause = disconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700496 mConnectTimeMillis = connectTimeMillis;
497 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700498 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700499 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700500 mExtras = extras;
Ihab Awade63fadb2014-07-09 21:52:04 -0700501 }
502 }
503
504 public static abstract class Listener {
505 /**
506 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
507 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700508 * @param call The {@code Call} invoking this method.
509 * @param state The new state of the {@code Call}.
510 */
511 public void onStateChanged(Call call, int state) {}
512
513 /**
514 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
515 *
516 * @param call The {@code Call} invoking this method.
517 * @param parent The new parent of the {@code Call}.
518 */
519 public void onParentChanged(Call call, Call parent) {}
520
521 /**
522 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
523 *
524 * @param call The {@code Call} invoking this method.
525 * @param children The new children of the {@code Call}.
526 */
527 public void onChildrenChanged(Call call, List<Call> children) {}
528
529 /**
530 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
531 *
532 * @param call The {@code Call} invoking this method.
533 * @param details A {@code Details} object describing the {@code Call}.
534 */
535 public void onDetailsChanged(Call call, Details details) {}
536
537 /**
538 * Invoked when the text messages that can be used as responses to the incoming
539 * {@code Call} are loaded from the relevant database.
540 * See {@link #getCannedTextResponses()}.
541 *
542 * @param call The {@code Call} invoking this method.
543 * @param cannedTextResponses The text messages useable as responses.
544 */
545 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
546
547 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700548 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
549 * character. This causes the post-dial signals to stop pending user confirmation. An
550 * implementation should present this choice to the user and invoke
551 * {@link #postDialContinue(boolean)} when the user makes the choice.
552 *
553 * @param call The {@code Call} invoking this method.
554 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
555 */
556 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
557
558 /**
Andrew Lee50aca232014-07-22 16:41:54 -0700559 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700560 *
561 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -0700562 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700563 */
Andrew Lee50aca232014-07-22 16:41:54 -0700564 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -0700565
566 /**
567 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
568 * up their UI for the {@code Call} in response to state transitions. Specifically,
569 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
570 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
571 * clients should wait for this method to be invoked.
572 *
573 * @param call The {@code Call} being destroyed.
574 */
575 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700576
577 /**
578 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
579 * conferenced.
580 *
581 * @param call The {@code Call} being updated.
582 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
583 * conferenced.
584 */
585 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Ihab Awade63fadb2014-07-09 21:52:04 -0700586 }
587
588 private final Phone mPhone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700589 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700590 private final InCallAdapter mInCallAdapter;
Santos Cordon823fd3c2014-08-07 18:35:18 -0700591 private final List<String> mChildrenIds = new ArrayList<>();
Ihab Awade63fadb2014-07-09 21:52:04 -0700592 private final List<Call> mChildren = new ArrayList<>();
593 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Jay Shrauner229e3822014-08-15 09:23:07 -0700594 private final List<Listener> mListeners = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700595 private final List<Call> mConferenceableCalls = new ArrayList<>();
596 private final List<Call> mUnmodifiableConferenceableCalls =
597 Collections.unmodifiableList(mConferenceableCalls);
598
Santos Cordon823fd3c2014-08-07 18:35:18 -0700599 private boolean mChildrenCached;
600 private String mParentId = null;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700601 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -0700602 private List<String> mCannedTextResponses = null;
603 private String mRemainingPostDialSequence;
Andrew Lee50aca232014-07-22 16:41:54 -0700604 private InCallService.VideoCall mVideoCall;
Ihab Awade63fadb2014-07-09 21:52:04 -0700605 private Details mDetails;
Ihab Awade63fadb2014-07-09 21:52:04 -0700606
607 /**
608 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
609 *
610 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
611 * remaining or this {@code Call} is not in a post-dial state.
612 */
613 public String getRemainingPostDialSequence() {
614 return mRemainingPostDialSequence;
615 }
616
617 /**
618 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700619 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -0700620 */
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700621 public void answer(int videoState) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700622 mInCallAdapter.answerCall(mTelecomCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -0700623 }
624
625 /**
626 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
627 *
628 * @param rejectWithMessage Whether to reject with a text message.
629 * @param textMessage An optional text message with which to respond.
630 */
631 public void reject(boolean rejectWithMessage, String textMessage) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700632 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
Ihab Awade63fadb2014-07-09 21:52:04 -0700633 }
634
635 /**
636 * Instructs this {@code Call} to disconnect.
637 */
638 public void disconnect() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700639 mInCallAdapter.disconnectCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700640 }
641
642 /**
643 * Instructs this {@code Call} to go on hold.
644 */
645 public void hold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700646 mInCallAdapter.holdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700647 }
648
649 /**
650 * Instructs this {@link #STATE_HOLDING} call to release from hold.
651 */
652 public void unhold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700653 mInCallAdapter.unholdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700654 }
655
656 /**
657 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
658 *
659 * Any other currently playing DTMF tone in the specified call is immediately stopped.
660 *
661 * @param digit A character representing the DTMF digit for which to play the tone. This
662 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
663 */
664 public void playDtmfTone(char digit) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700665 mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
Ihab Awade63fadb2014-07-09 21:52:04 -0700666 }
667
668 /**
669 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
670 * currently playing.
671 *
672 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
673 * currently playing, this method will do nothing.
674 */
675 public void stopDtmfTone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700676 mInCallAdapter.stopDtmfTone(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700677 }
678
679 /**
680 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
681 *
682 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
683 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -0700684 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700685 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -0700686 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
687 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700688 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -0700689 * {@code Call} will pause playing the tones and notify listeners via
690 * {@link Listener#onPostDialWait(Call, String)}. At this point, the in-call app
691 * should display to the user an indication of this state and an affordance to continue
692 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
693 * app should invoke the {@link #postDialContinue(boolean)} method.
694 *
695 * @param proceed Whether or not to continue with the post-dial sequence.
696 */
697 public void postDialContinue(boolean proceed) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700698 mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
Ihab Awade63fadb2014-07-09 21:52:04 -0700699 }
700
701 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -0700702 * Notifies this {@code Call} that an account has been selected and to proceed with placing
Nancy Chen36c62f32014-10-21 18:36:39 -0700703 * an outgoing call. Optionally sets this account as the default account.
Nancy Chen5da0fd52014-07-08 14:16:17 -0700704 */
Nancy Chen36c62f32014-10-21 18:36:39 -0700705 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
706 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
Nancy Chen5da0fd52014-07-08 14:16:17 -0700707
708 }
709
710 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700711 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700712 *
713 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -0700714 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700715 public void conference(Call callToConferenceWith) {
716 if (callToConferenceWith != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700717 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700718 }
Ihab Awade63fadb2014-07-09 21:52:04 -0700719 }
720
721 /**
722 * Instructs this {@code Call} to split from any conference call with which it may be
723 * connected.
724 */
725 public void splitFromConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700726 mInCallAdapter.splitFromConference(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700727 }
728
729 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800730 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -0700731 */
732 public void mergeConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700733 mInCallAdapter.mergeConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -0700734 }
735
736 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800737 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -0700738 */
739 public void swapConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700740 mInCallAdapter.swapConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -0700741 }
742
743 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700744 * Obtains the parent of this {@code Call} in a conference, if any.
745 *
746 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
747 * child of any conference {@code Call}s.
748 */
749 public Call getParent() {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700750 if (mParentId != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700751 return mPhone.internalGetCallByTelecomId(mParentId);
Santos Cordon823fd3c2014-08-07 18:35:18 -0700752 }
753 return null;
Ihab Awade63fadb2014-07-09 21:52:04 -0700754 }
755
756 /**
757 * Obtains the children of this conference {@code Call}, if any.
758 *
759 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
760 * {@code List} otherwise.
761 */
762 public List<Call> getChildren() {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700763 if (!mChildrenCached) {
764 mChildrenCached = true;
765 mChildren.clear();
766
767 for(String id : mChildrenIds) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700768 Call call = mPhone.internalGetCallByTelecomId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -0700769 if (call == null) {
770 // At least one child was still not found, so do not save true for "cached"
771 mChildrenCached = false;
772 } else {
773 mChildren.add(call);
774 }
775 }
776 }
777
Ihab Awade63fadb2014-07-09 21:52:04 -0700778 return mUnmodifiableChildren;
779 }
780
781 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700782 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
783 *
784 * @return The list of conferenceable {@code Call}s.
785 */
786 public List<Call> getConferenceableCalls() {
787 return mUnmodifiableConferenceableCalls;
788 }
789
790 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700791 * Obtains the state of this {@code Call}.
792 *
793 * @return A state value, chosen from the {@code STATE_*} constants.
794 */
795 public int getState() {
796 return mState;
797 }
798
799 /**
800 * Obtains a list of canned, pre-configured message responses to present to the user as
801 * ways of rejecting this {@code Call} using via a text message.
802 *
803 * @see #reject(boolean, String)
804 *
805 * @return A list of canned text message responses.
806 */
807 public List<String> getCannedTextResponses() {
808 return mCannedTextResponses;
809 }
810
811 /**
812 * Obtains an object that can be used to display video from this {@code Call}.
813 *
Andrew Lee50aca232014-07-22 16:41:54 -0700814 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700815 */
Andrew Lee50aca232014-07-22 16:41:54 -0700816 public InCallService.VideoCall getVideoCall() {
817 return mVideoCall;
Ihab Awade63fadb2014-07-09 21:52:04 -0700818 }
819
820 /**
821 * Obtains an object containing call details.
822 *
823 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
824 * result may be {@code null}.
825 */
826 public Details getDetails() {
827 return mDetails;
828 }
829
830 /**
831 * Adds a listener to this {@code Call}.
832 *
833 * @param listener A {@code Listener}.
834 */
835 public void addListener(Listener listener) {
836 mListeners.add(listener);
837 }
838
839 /**
840 * Removes a listener from this {@code Call}.
841 *
842 * @param listener A {@code Listener}.
843 */
844 public void removeListener(Listener listener) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700845 if (listener != null) {
846 mListeners.remove(listener);
847 }
Ihab Awade63fadb2014-07-09 21:52:04 -0700848 }
849
850 /** {@hide} */
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700851 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter) {
Ihab Awade63fadb2014-07-09 21:52:04 -0700852 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700853 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700854 mInCallAdapter = inCallAdapter;
855 mState = STATE_NEW;
856 }
857
858 /** {@hide} */
859 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700860 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700861 }
862
863 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700864 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Ihab Awade63fadb2014-07-09 21:52:04 -0700865 // First, we update the internal state as far as possible before firing any updates.
Ihab Awade63fadb2014-07-09 21:52:04 -0700866 Details details = new Details(
Santos Cordon88b771d2014-07-19 13:10:40 -0700867 parcelableCall.getHandle(),
868 parcelableCall.getHandlePresentation(),
869 parcelableCall.getCallerDisplayName(),
870 parcelableCall.getCallerDisplayNamePresentation(),
871 parcelableCall.getAccountHandle(),
872 parcelableCall.getCapabilities(),
Andrew Lee223ad142014-08-27 16:33:08 -0700873 parcelableCall.getProperties(),
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700874 parcelableCall.getDisconnectCause(),
Santos Cordon88b771d2014-07-19 13:10:40 -0700875 parcelableCall.getConnectTimeMillis(),
876 parcelableCall.getGatewayInfo(),
877 parcelableCall.getVideoState(),
Nancy Chen10798dc2014-08-08 14:00:25 -0700878 parcelableCall.getStatusHints(),
Jay Shrauner6f20a6a2015-04-16 12:52:19 -0700879 parcelableCall.getExtras());
Ihab Awade63fadb2014-07-09 21:52:04 -0700880 boolean detailsChanged = !Objects.equals(mDetails, details);
881 if (detailsChanged) {
882 mDetails = details;
883 }
884
885 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -0700886 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
887 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
888 mCannedTextResponses =
889 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Ihab Awade63fadb2014-07-09 21:52:04 -0700890 }
891
Tyler Gunn75958422015-04-15 14:23:42 -0700892 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() &&
893 !Objects.equals(mVideoCall, parcelableCall.getVideoCall());
Andrew Lee50aca232014-07-22 16:41:54 -0700894 if (videoCallChanged) {
895 mVideoCall = parcelableCall.getVideoCall();
Ihab Awade63fadb2014-07-09 21:52:04 -0700896 }
897
Santos Cordon88b771d2014-07-19 13:10:40 -0700898 int state = stateFromParcelableCallState(parcelableCall.getState());
Ihab Awade63fadb2014-07-09 21:52:04 -0700899 boolean stateChanged = mState != state;
900 if (stateChanged) {
901 mState = state;
902 }
903
Santos Cordon823fd3c2014-08-07 18:35:18 -0700904 String parentId = parcelableCall.getParentCallId();
905 boolean parentChanged = !Objects.equals(mParentId, parentId);
906 if (parentChanged) {
907 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700908 }
909
Santos Cordon823fd3c2014-08-07 18:35:18 -0700910 List<String> childCallIds = parcelableCall.getChildCallIds();
911 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
912 if (childrenChanged) {
913 mChildrenIds.clear();
914 mChildrenIds.addAll(parcelableCall.getChildCallIds());
915 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -0700916 }
917
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700918 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
919 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
920 for (String otherId : conferenceableCallIds) {
921 if (callIdMap.containsKey(otherId)) {
922 conferenceableCalls.add(callIdMap.get(otherId));
923 }
924 }
925
926 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
927 mConferenceableCalls.clear();
928 mConferenceableCalls.addAll(conferenceableCalls);
929 fireConferenceableCallsChanged();
930 }
931
Ihab Awade63fadb2014-07-09 21:52:04 -0700932 // Now we fire updates, ensuring that any client who listens to any of these notifications
933 // gets the most up-to-date state.
934
935 if (stateChanged) {
936 fireStateChanged(mState);
937 }
938 if (detailsChanged) {
939 fireDetailsChanged(mDetails);
940 }
941 if (cannedTextResponsesChanged) {
942 fireCannedTextResponsesLoaded(mCannedTextResponses);
943 }
Andrew Lee50aca232014-07-22 16:41:54 -0700944 if (videoCallChanged) {
945 fireVideoCallChanged(mVideoCall);
Ihab Awade63fadb2014-07-09 21:52:04 -0700946 }
Santos Cordon823fd3c2014-08-07 18:35:18 -0700947 if (parentChanged) {
948 fireParentChanged(getParent());
949 }
950 if (childrenChanged) {
951 fireChildrenChanged(getChildren());
952 }
Ihab Awade63fadb2014-07-09 21:52:04 -0700953
954 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
955 // remove ourselves from the Phone. Note that we do this after completing all state updates
956 // so a client can cleanly transition all their UI to the state appropriate for a
957 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
958 if (mState == STATE_DISCONNECTED) {
959 fireCallDestroyed();
960 mPhone.internalRemoveCall(this);
961 }
962 }
963
964 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -0700965 final void internalSetPostDialWait(String remaining) {
966 mRemainingPostDialSequence = remaining;
967 firePostDialWait(mRemainingPostDialSequence);
968 }
969
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -0700970 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -0700971 final void internalSetDisconnected() {
972 if (mState != Call.STATE_DISCONNECTED) {
973 mState = Call.STATE_DISCONNECTED;
974 fireStateChanged(mState);
975 fireCallDestroyed();
976 mPhone.internalRemoveCall(this);
977 }
978 }
979
Ihab Awade63fadb2014-07-09 21:52:04 -0700980 private void fireStateChanged(int newState) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700981 for (Listener listener : mListeners) {
982 listener.onStateChanged(this, newState);
Ihab Awade63fadb2014-07-09 21:52:04 -0700983 }
984 }
985
986 private void fireParentChanged(Call newParent) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700987 for (Listener listener : mListeners) {
988 listener.onParentChanged(this, newParent);
Ihab Awade63fadb2014-07-09 21:52:04 -0700989 }
990 }
991
992 private void fireChildrenChanged(List<Call> children) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700993 for (Listener listener : mListeners) {
994 listener.onChildrenChanged(this, children);
Ihab Awade63fadb2014-07-09 21:52:04 -0700995 }
996 }
997
998 private void fireDetailsChanged(Details details) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700999 for (Listener listener : mListeners) {
1000 listener.onDetailsChanged(this, details);
Ihab Awade63fadb2014-07-09 21:52:04 -07001001 }
1002 }
1003
1004 private void fireCannedTextResponsesLoaded(List<String> cannedTextResponses) {
Jay Shrauner229e3822014-08-15 09:23:07 -07001005 for (Listener listener : mListeners) {
1006 listener.onCannedTextResponsesLoaded(this, cannedTextResponses);
Ihab Awade63fadb2014-07-09 21:52:04 -07001007 }
1008 }
1009
Andrew Lee50aca232014-07-22 16:41:54 -07001010 private void fireVideoCallChanged(InCallService.VideoCall videoCall) {
Jay Shrauner229e3822014-08-15 09:23:07 -07001011 for (Listener listener : mListeners) {
1012 listener.onVideoCallChanged(this, videoCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07001013 }
1014 }
1015
Ihab Awade63fadb2014-07-09 21:52:04 -07001016 private void firePostDialWait(String remainingPostDialSequence) {
Jay Shrauner229e3822014-08-15 09:23:07 -07001017 for (Listener listener : mListeners) {
1018 listener.onPostDialWait(this, remainingPostDialSequence);
Ihab Awade63fadb2014-07-09 21:52:04 -07001019 }
1020 }
1021
1022 private void fireCallDestroyed() {
Jay Shrauner229e3822014-08-15 09:23:07 -07001023 for (Listener listener : mListeners) {
1024 listener.onCallDestroyed(this);
Ihab Awade63fadb2014-07-09 21:52:04 -07001025 }
1026 }
1027
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001028 private void fireConferenceableCallsChanged() {
Jay Shrauner229e3822014-08-15 09:23:07 -07001029 for (Listener listener : mListeners) {
1030 listener.onConferenceableCallsChanged(this, mUnmodifiableConferenceableCalls);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001031 }
1032 }
1033
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001034 private int stateFromParcelableCallState(int parcelableCallState) {
Santos Cordon88b771d2014-07-19 13:10:40 -07001035 switch (parcelableCallState) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001036 case CallState.NEW:
Ihab Awade63fadb2014-07-09 21:52:04 -07001037 return STATE_NEW;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001038 case CallState.CONNECTING:
Nancy Chene20930f2014-08-07 16:17:21 -07001039 return STATE_CONNECTING;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001040 case CallState.PRE_DIAL_WAIT:
Nancy Chen5da0fd52014-07-08 14:16:17 -07001041 return STATE_PRE_DIAL_WAIT;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001042 case CallState.DIALING:
Ihab Awade63fadb2014-07-09 21:52:04 -07001043 return STATE_DIALING;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001044 case CallState.RINGING:
Ihab Awade63fadb2014-07-09 21:52:04 -07001045 return STATE_RINGING;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001046 case CallState.ACTIVE:
Ihab Awade63fadb2014-07-09 21:52:04 -07001047 return STATE_ACTIVE;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001048 case CallState.ON_HOLD:
Ihab Awade63fadb2014-07-09 21:52:04 -07001049 return STATE_HOLDING;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001050 case CallState.DISCONNECTED:
Ihab Awade63fadb2014-07-09 21:52:04 -07001051 return STATE_DISCONNECTED;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001052 case CallState.ABORTED:
Ihab Awade63fadb2014-07-09 21:52:04 -07001053 return STATE_DISCONNECTED;
Tyler Gunn4afc6af2014-10-07 10:14:55 -07001054 case CallState.DISCONNECTING:
1055 return STATE_DISCONNECTING;
Ihab Awade63fadb2014-07-09 21:52:04 -07001056 default:
Santos Cordon88b771d2014-07-19 13:10:40 -07001057 Log.wtf(this, "Unrecognized CallState %s", parcelableCallState);
Ihab Awade63fadb2014-07-09 21:52:04 -07001058 return STATE_NEW;
1059 }
1060 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001061}