blob: 5c891dc2575bc25f14770858521bb9e159383e7e [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
Gabriel Pealb95f1692014-08-19 14:24:18 -070019import android.annotation.SystemApi;
Ihab Awade63fadb2014-07-09 21:52:04 -070020import android.net.Uri;
Nancy Chen10798dc2014-08-08 14:00:25 -070021import android.os.Bundle;
Ihab Awade63fadb2014-07-09 21:52:04 -070022
Andrew Lee50aca232014-07-22 16:41:54 -070023import java.lang.String;
Ihab Awade63fadb2014-07-09 21:52:04 -070024import java.util.ArrayList;
25import java.util.Collections;
26import java.util.List;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070027import java.util.Map;
Ihab Awade63fadb2014-07-09 21:52:04 -070028import java.util.Objects;
Jay Shrauner229e3822014-08-15 09:23:07 -070029import java.util.concurrent.CopyOnWriteArrayList;
Ihab Awade63fadb2014-07-09 21:52:04 -070030
31/**
32 * Represents an ongoing phone call that the in-call app should present to the user.
Ihab Awadb19a0bc2014-08-07 19:46:01 -070033 *
34 * {@hide}
Ihab Awade63fadb2014-07-09 21:52:04 -070035 */
Gabriel Pealb95f1692014-08-19 14:24:18 -070036@SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -070037public final class Call {
38 /**
39 * The state of a {@code Call} when newly created.
40 */
41 public static final int STATE_NEW = 0;
42
43 /**
44 * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
45 */
46 public static final int STATE_DIALING = 1;
47
48 /**
49 * The state of an incoming {@code Call} when ringing locally, but not yet connected.
50 */
51 public static final int STATE_RINGING = 2;
52
53 /**
54 * The state of a {@code Call} when in a holding state.
55 */
56 public static final int STATE_HOLDING = 3;
57
58 /**
59 * The state of a {@code Call} when actively supporting conversation.
60 */
61 public static final int STATE_ACTIVE = 4;
62
63 /**
64 * The state of a {@code Call} when no further voice or other communication is being
65 * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
66 * is no longer active, and the local data transport has or inevitably will release resources
67 * associated with this {@code Call}.
68 */
69 public static final int STATE_DISCONNECTED = 7;
70
Nancy Chen5da0fd52014-07-08 14:16:17 -070071 /**
72 * The state of an outgoing {@code Call}, but waiting for user input before proceeding.
73 */
74 public static final int STATE_PRE_DIAL_WAIT = 8;
75
Nancy Chene20930f2014-08-07 16:17:21 -070076 /**
Nancy Chene9b7a8e2014-08-08 14:26:27 -070077 * The initial state of an outgoing {@code Call}.
78 * Common transitions are to {@link #STATE_DIALING} state for a successful call or
79 * {@link #STATE_DISCONNECTED} if it failed.
Nancy Chene20930f2014-08-07 16:17:21 -070080 */
81 public static final int STATE_CONNECTING = 9;
82
Nancy Chen513c8922014-09-17 14:47:20 -070083 /**
Tyler Gunn4afc6af2014-10-07 10:14:55 -070084 * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
85 * call has not yet been disconnected by the underlying {@code ConnectionService}. The next
86 * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
87 */
88 public static final int STATE_DISCONNECTING = 10;
89
90 /**
Nancy Chen513c8922014-09-17 14:47:20 -070091 * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
92 * extras. Used to pass the phone accounts to display on the front end to the user in order to
93 * select phone accounts to (for example) place a call.
94 *
95 * @hide
96 */
97 public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
98
Ihab Awade63fadb2014-07-09 21:52:04 -070099 public static class Details {
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800100
101 /** Call can currently be put on hold or unheld. */
102 public static final int CAPABILITY_HOLD = 0x00000001;
103
104 /** Call supports the hold feature. */
105 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
106
107 /**
108 * Calls within a conference can be merged. A {@link ConnectionService} has the option to
109 * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
110 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
111 * capability allows a merge button to be shown while the conference call is in the foreground
112 * of the in-call UI.
113 * <p>
114 * This is only intended for use by a {@link Conference}.
115 */
116 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
117
118 /**
119 * Calls within a conference can be swapped between foreground and background.
120 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
121 * <p>
122 * This is only intended for use by a {@link Conference}.
123 */
124 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
125
126 /**
127 * @hide
128 */
129 public static final int CAPABILITY_UNUSED = 0x00000010;
130
131 /** Call supports responding via text option. */
132 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
133
134 /** Call can be muted. */
135 public static final int CAPABILITY_MUTE = 0x00000040;
136
137 /**
138 * Call supports conference call management. This capability only applies to {@link Conference}
139 * calls which can have {@link Connection}s as children.
140 */
141 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
142
143 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700144 * Local device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800145 * @hide
146 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700147 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800148
149 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700150 * Local device supports transmitting video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800151 * @hide
152 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700153 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800154
155 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700156 * Local device supports bidirectional video calling.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800157 * @hide
158 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700159 public static final int CAPABILITY_SUPPORTS_VT_LOCAL =
160 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800161
162 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700163 * Remote device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800164 * @hide
165 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700166 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
167
168 /**
169 * Remote device supports transmitting video.
170 * @hide
171 */
172 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
173
174 /**
175 * Remote device supports bidirectional video calling.
176 * @hide
177 */
178 public static final int CAPABILITY_SUPPORTS_VT_REMOTE =
179 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800180
181 /**
182 * Call is able to be separated from its parent {@code Conference}, if any.
183 */
184 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
185
186 /**
187 * Call is able to be individually disconnected when in a {@code Conference}.
188 */
189 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
Dong Zhou89f41eb2015-03-15 11:59:49 -0500190
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800191 /**
192 * Whether the call is a generic conference, where we do not know the precise state of
193 * participants in the conference (eg. on CDMA).
194 *
195 * @hide
196 */
197 public static final int CAPABILITY_GENERIC_CONFERENCE = 0x00004000;
198
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700199 /**
200 * Call is using high definition audio.
201 * @hide
202 */
203 public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00008000;
204
205 /**
206 * Call is using WIFI.
207 * @hide
208 */
209 public static final int CAPABILITY_WIFI = 0x00010000;
210
Tyler Gunn068085b2015-02-06 13:56:52 -0800211 /**
212 * Indicates that the current device callback number should be shown.
213 *
214 * @hide
215 */
Tyler Gunnd11a3152015-03-18 13:09:14 -0700216 public static final int CAPABILITY_SHOW_CALLBACK_NUMBER = 0x00020000;
217
218 /**
Dong Zhou89f41eb2015-03-15 11:59:49 -0500219 * Speed up audio setup for MT call.
220 * @hide
221 */
Tyler Gunnd11a3152015-03-18 13:09:14 -0700222 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
223
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700224 /**
225 * Call can be upgraded to a video call.
Rekha Kumar07366812015-03-24 16:42:31 -0700226 * @hide
227 */
228 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
229
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700230 /**
231 * For video calls, indicates whether the outgoing video for the call can be paused using
232 * the {@link android.telecom.VideoProfile.VideoState#PAUSED} VideoState.
233 * @hide
234 */
235 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
236
Tyler Gunnd11a3152015-03-18 13:09:14 -0700237 //******************************************************************************************
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700238 // Next CAPABILITY value: 0x00200000
Tyler Gunnd11a3152015-03-18 13:09:14 -0700239 //******************************************************************************************
Tyler Gunn068085b2015-02-06 13:56:52 -0800240
Ihab Awade63fadb2014-07-09 21:52:04 -0700241 private final Uri mHandle;
242 private final int mHandlePresentation;
243 private final String mCallerDisplayName;
244 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700245 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700246 private final int mCallCapabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700247 private final int mCallProperties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700248 private final DisconnectCause mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700249 private final long mConnectTimeMillis;
250 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700251 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700252 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700253 private final Bundle mExtras;
Rekha Kumar07366812015-03-24 16:42:31 -0700254 private final int mCallSubstate;
Ihab Awade63fadb2014-07-09 21:52:04 -0700255
256 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800257 * Whether the supplied capabilities supports the specified capability.
258 *
259 * @param capabilities A bit field of capabilities.
260 * @param capability The capability to check capabilities for.
261 * @return Whether the specified capability is supported.
262 * @hide
263 */
264 public static boolean can(int capabilities, int capability) {
265 return (capabilities & capability) != 0;
266 }
267
268 /**
269 * Whether the capabilities of this {@code Details} supports the specified capability.
270 *
271 * @param capability The capability to check capabilities for.
272 * @return Whether the specified capability is supported.
273 * @hide
274 */
275 public boolean can(int capability) {
276 return can(mCallCapabilities, capability);
277 }
278
279 /**
280 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
281 *
282 * @param capabilities A capability bit field.
283 * @return A human readable string representation.
284 */
285 public static String capabilitiesToString(int capabilities) {
286 StringBuilder builder = new StringBuilder();
287 builder.append("[Capabilities:");
288 if (can(capabilities, CAPABILITY_HOLD)) {
289 builder.append(" CAPABILITY_HOLD");
290 }
291 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
292 builder.append(" CAPABILITY_SUPPORT_HOLD");
293 }
294 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
295 builder.append(" CAPABILITY_MERGE_CONFERENCE");
296 }
297 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
298 builder.append(" CAPABILITY_SWAP_CONFERENCE");
299 }
300 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
301 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
302 }
303 if (can(capabilities, CAPABILITY_MUTE)) {
304 builder.append(" CAPABILITY_MUTE");
305 }
306 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
307 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
308 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700309 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
310 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
311 }
312 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
313 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
314 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800315 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL)) {
316 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL");
317 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700318 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
319 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
320 }
321 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
322 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
323 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800324 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE)) {
325 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE");
326 }
Andrew Lee80fff3c2014-11-25 17:36:51 -0800327 if (can(capabilities, CAPABILITY_HIGH_DEF_AUDIO)) {
328 builder.append(" CAPABILITY_HIGH_DEF_AUDIO");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800329 }
Andrew Lee1a8ae3e2015-02-02 13:42:38 -0800330 if (can(capabilities, CAPABILITY_WIFI)) {
331 builder.append(" CAPABILITY_WIFI");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800332 }
333 if (can(capabilities, CAPABILITY_GENERIC_CONFERENCE)) {
334 builder.append(" CAPABILITY_GENERIC_CONFERENCE");
335 }
Tyler Gunn068085b2015-02-06 13:56:52 -0800336 if (can(capabilities, CAPABILITY_SHOW_CALLBACK_NUMBER)) {
337 builder.append(" CAPABILITY_SHOW_CALLBACK_NUMBER");
338 }
Dong Zhou89f41eb2015-03-15 11:59:49 -0500339 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
Tyler Gunnd11a3152015-03-18 13:09:14 -0700340 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
Dong Zhou89f41eb2015-03-15 11:59:49 -0500341 }
Rekha Kumar07366812015-03-24 16:42:31 -0700342 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
343 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
344 }
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700345 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
346 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
347 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800348 builder.append("]");
349 return builder.toString();
350 }
351
352 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700353 * @return The handle (e.g., phone number) to which the {@code Call} is currently
354 * connected.
355 */
356 public Uri getHandle() {
357 return mHandle;
358 }
359
360 /**
361 * @return The presentation requirements for the handle. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700362 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700363 */
364 public int getHandlePresentation() {
365 return mHandlePresentation;
366 }
367
368 /**
369 * @return The display name for the caller.
370 */
371 public String getCallerDisplayName() {
372 return mCallerDisplayName;
373 }
374
375 /**
376 * @return The presentation requirements for the caller display name. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700377 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700378 */
379 public int getCallerDisplayNamePresentation() {
380 return mCallerDisplayNamePresentation;
381 }
382
383 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700384 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
385 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700386 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700387 public PhoneAccountHandle getAccountHandle() {
388 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -0700389 }
390
391 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800392 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
393 * {@code CAPABILITY_*} constants in this class.
Ihab Awade63fadb2014-07-09 21:52:04 -0700394 */
Ihab Awad5d0410f2014-07-30 10:07:40 -0700395 public int getCallCapabilities() {
396 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700397 }
398
399 /**
Andrew Lee223ad142014-08-27 16:33:08 -0700400 * @return A bitmask of the properties of the {@code Call}, as defined in
401 * {@link CallProperties}.
402 */
403 public int getCallProperties() {
404 return mCallProperties;
405 }
406
407 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700408 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
Nancy Chenf4cf77c2014-09-19 10:53:21 -0700409 * by {@link android.telecom.DisconnectCause}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700410 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700411 public DisconnectCause getDisconnectCause() {
412 return mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700413 }
414
415 /**
416 * @return The time the {@code Call} has been connected. This information is updated
417 * periodically, but user interfaces should not rely on this to display any "call time
418 * clock".
419 */
420 public long getConnectTimeMillis() {
421 return mConnectTimeMillis;
422 }
423
424 /**
425 * @return Information about any calling gateway the {@code Call} may be using.
426 */
427 public GatewayInfo getGatewayInfo() {
428 return mGatewayInfo;
429 }
430
Andrew Lee7a341382014-07-15 17:05:08 -0700431 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -0700432 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -0700433 */
434 public int getVideoState() {
435 return mVideoState;
436 }
437
Ihab Awad5d0410f2014-07-30 10:07:40 -0700438 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700439 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
Ihab Awad5d0410f2014-07-30 10:07:40 -0700440 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -0700441 */
442 public StatusHints getStatusHints() {
443 return mStatusHints;
444 }
445
Nancy Chen10798dc2014-08-08 14:00:25 -0700446 /**
447 * @return A bundle extras to pass with the call
448 */
449 public Bundle getExtras() {
450 return mExtras;
451 }
452
Rekha Kumar07366812015-03-24 16:42:31 -0700453 /**
454 * @return The substate of the {@code Call}.
455 * @hide
456 */
457 public int getCallSubstate() {
458 return mCallSubstate;
459 }
460
Ihab Awade63fadb2014-07-09 21:52:04 -0700461 @Override
462 public boolean equals(Object o) {
463 if (o instanceof Details) {
464 Details d = (Details) o;
465 return
466 Objects.equals(mHandle, d.mHandle) &&
467 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
468 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
469 Objects.equals(mCallerDisplayNamePresentation,
470 d.mCallerDisplayNamePresentation) &&
Evan Charlton8c8a0622014-07-20 12:31:00 -0700471 Objects.equals(mAccountHandle, d.mAccountHandle) &&
Ihab Awad5d0410f2014-07-30 10:07:40 -0700472 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Andrew Lee223ad142014-08-27 16:33:08 -0700473 Objects.equals(mCallProperties, d.mCallProperties) &&
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700474 Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
Ihab Awade63fadb2014-07-09 21:52:04 -0700475 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Andrew Lee85f5d422014-07-11 17:22:03 -0700476 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Evan Charlton5b49ade2014-07-15 17:03:20 -0700477 Objects.equals(mVideoState, d.mVideoState) &&
Nancy Chen10798dc2014-08-08 14:00:25 -0700478 Objects.equals(mStatusHints, d.mStatusHints) &&
Rekha Kumar07366812015-03-24 16:42:31 -0700479 Objects.equals(mExtras, d.mExtras) &&
480 Objects.equals(mCallSubstate, d.mCallSubstate);
Ihab Awade63fadb2014-07-09 21:52:04 -0700481 }
482 return false;
483 }
484
485 @Override
486 public int hashCode() {
487 return
488 Objects.hashCode(mHandle) +
489 Objects.hashCode(mHandlePresentation) +
490 Objects.hashCode(mCallerDisplayName) +
491 Objects.hashCode(mCallerDisplayNamePresentation) +
Evan Charlton8c8a0622014-07-20 12:31:00 -0700492 Objects.hashCode(mAccountHandle) +
Ihab Awad5d0410f2014-07-30 10:07:40 -0700493 Objects.hashCode(mCallCapabilities) +
Andrew Lee223ad142014-08-27 16:33:08 -0700494 Objects.hashCode(mCallProperties) +
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700495 Objects.hashCode(mDisconnectCause) +
Ihab Awade63fadb2014-07-09 21:52:04 -0700496 Objects.hashCode(mConnectTimeMillis) +
Andrew Lee85f5d422014-07-11 17:22:03 -0700497 Objects.hashCode(mGatewayInfo) +
Evan Charlton5b49ade2014-07-15 17:03:20 -0700498 Objects.hashCode(mVideoState) +
Nancy Chen10798dc2014-08-08 14:00:25 -0700499 Objects.hashCode(mStatusHints) +
Rekha Kumar07366812015-03-24 16:42:31 -0700500 Objects.hashCode(mExtras) +
501 Objects.hashCode(mCallSubstate);
Ihab Awade63fadb2014-07-09 21:52:04 -0700502 }
503
504 /** {@hide} */
505 public Details(
506 Uri handle,
507 int handlePresentation,
508 String callerDisplayName,
509 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -0700510 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -0700511 int capabilities,
Andrew Lee223ad142014-08-27 16:33:08 -0700512 int properties,
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700513 DisconnectCause disconnectCause,
Ihab Awade63fadb2014-07-09 21:52:04 -0700514 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -0700515 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -0700516 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -0700517 StatusHints statusHints,
Rekha Kumar07366812015-03-24 16:42:31 -0700518 Bundle extras,
519 int callSubstate) {
Ihab Awade63fadb2014-07-09 21:52:04 -0700520 mHandle = handle;
521 mHandlePresentation = handlePresentation;
522 mCallerDisplayName = callerDisplayName;
523 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700524 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700525 mCallCapabilities = capabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700526 mCallProperties = properties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700527 mDisconnectCause = disconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700528 mConnectTimeMillis = connectTimeMillis;
529 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700530 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700531 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700532 mExtras = extras;
Rekha Kumar07366812015-03-24 16:42:31 -0700533 mCallSubstate = callSubstate;
Ihab Awade63fadb2014-07-09 21:52:04 -0700534 }
535 }
536
537 public static abstract class Listener {
538 /**
539 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
540 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700541 * @param call The {@code Call} invoking this method.
542 * @param state The new state of the {@code Call}.
543 */
544 public void onStateChanged(Call call, int state) {}
545
546 /**
547 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
548 *
549 * @param call The {@code Call} invoking this method.
550 * @param parent The new parent of the {@code Call}.
551 */
552 public void onParentChanged(Call call, Call parent) {}
553
554 /**
555 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
556 *
557 * @param call The {@code Call} invoking this method.
558 * @param children The new children of the {@code Call}.
559 */
560 public void onChildrenChanged(Call call, List<Call> children) {}
561
562 /**
563 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
564 *
565 * @param call The {@code Call} invoking this method.
566 * @param details A {@code Details} object describing the {@code Call}.
567 */
568 public void onDetailsChanged(Call call, Details details) {}
569
570 /**
571 * Invoked when the text messages that can be used as responses to the incoming
572 * {@code Call} are loaded from the relevant database.
573 * See {@link #getCannedTextResponses()}.
574 *
575 * @param call The {@code Call} invoking this method.
576 * @param cannedTextResponses The text messages useable as responses.
577 */
578 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
579
580 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700581 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
582 * character. This causes the post-dial signals to stop pending user confirmation. An
583 * implementation should present this choice to the user and invoke
584 * {@link #postDialContinue(boolean)} when the user makes the choice.
585 *
586 * @param call The {@code Call} invoking this method.
587 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
588 */
589 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
590
591 /**
Andrew Lee50aca232014-07-22 16:41:54 -0700592 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700593 *
594 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -0700595 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Tyler Gunn75537ae2014-08-22 11:33:13 -0700596 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -0700597 */
Andrew Lee50aca232014-07-22 16:41:54 -0700598 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -0700599
600 /**
601 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
602 * up their UI for the {@code Call} in response to state transitions. Specifically,
603 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
604 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
605 * clients should wait for this method to be invoked.
606 *
607 * @param call The {@code Call} being destroyed.
608 */
609 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700610
611 /**
612 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
613 * conferenced.
614 *
615 * @param call The {@code Call} being updated.
616 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
617 * conferenced.
618 */
619 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Ihab Awade63fadb2014-07-09 21:52:04 -0700620 }
621
622 private final Phone mPhone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700623 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700624 private final InCallAdapter mInCallAdapter;
Santos Cordon823fd3c2014-08-07 18:35:18 -0700625 private final List<String> mChildrenIds = new ArrayList<>();
Ihab Awade63fadb2014-07-09 21:52:04 -0700626 private final List<Call> mChildren = new ArrayList<>();
627 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Jay Shrauner229e3822014-08-15 09:23:07 -0700628 private final List<Listener> mListeners = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700629 private final List<Call> mConferenceableCalls = new ArrayList<>();
630 private final List<Call> mUnmodifiableConferenceableCalls =
631 Collections.unmodifiableList(mConferenceableCalls);
632
Santos Cordon823fd3c2014-08-07 18:35:18 -0700633 private boolean mChildrenCached;
634 private String mParentId = null;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700635 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -0700636 private List<String> mCannedTextResponses = null;
637 private String mRemainingPostDialSequence;
Andrew Lee50aca232014-07-22 16:41:54 -0700638 private InCallService.VideoCall mVideoCall;
Ihab Awade63fadb2014-07-09 21:52:04 -0700639 private Details mDetails;
Ihab Awade63fadb2014-07-09 21:52:04 -0700640
641 /**
642 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
643 *
644 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
645 * remaining or this {@code Call} is not in a post-dial state.
646 */
647 public String getRemainingPostDialSequence() {
648 return mRemainingPostDialSequence;
649 }
650
651 /**
652 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700653 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -0700654 */
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700655 public void answer(int videoState) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700656 mInCallAdapter.answerCall(mTelecomCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -0700657 }
658
659 /**
660 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
661 *
662 * @param rejectWithMessage Whether to reject with a text message.
663 * @param textMessage An optional text message with which to respond.
664 */
665 public void reject(boolean rejectWithMessage, String textMessage) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700666 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
Ihab Awade63fadb2014-07-09 21:52:04 -0700667 }
668
669 /**
670 * Instructs this {@code Call} to disconnect.
671 */
672 public void disconnect() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700673 mInCallAdapter.disconnectCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700674 }
675
676 /**
677 * Instructs this {@code Call} to go on hold.
678 */
679 public void hold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700680 mInCallAdapter.holdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700681 }
682
683 /**
684 * Instructs this {@link #STATE_HOLDING} call to release from hold.
685 */
686 public void unhold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700687 mInCallAdapter.unholdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700688 }
689
690 /**
691 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
692 *
693 * Any other currently playing DTMF tone in the specified call is immediately stopped.
694 *
695 * @param digit A character representing the DTMF digit for which to play the tone. This
696 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
697 */
698 public void playDtmfTone(char digit) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700699 mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
Ihab Awade63fadb2014-07-09 21:52:04 -0700700 }
701
702 /**
703 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
704 * currently playing.
705 *
706 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
707 * currently playing, this method will do nothing.
708 */
709 public void stopDtmfTone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700710 mInCallAdapter.stopDtmfTone(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700711 }
712
713 /**
714 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
715 *
716 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
717 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -0700718 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700719 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -0700720 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
721 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700722 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -0700723 * {@code Call} will pause playing the tones and notify listeners via
724 * {@link Listener#onPostDialWait(Call, String)}. At this point, the in-call app
725 * should display to the user an indication of this state and an affordance to continue
726 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
727 * app should invoke the {@link #postDialContinue(boolean)} method.
728 *
729 * @param proceed Whether or not to continue with the post-dial sequence.
730 */
731 public void postDialContinue(boolean proceed) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700732 mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
Ihab Awade63fadb2014-07-09 21:52:04 -0700733 }
734
735 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -0700736 * Notifies this {@code Call} that an account has been selected and to proceed with placing
Nancy Chen36c62f32014-10-21 18:36:39 -0700737 * an outgoing call. Optionally sets this account as the default account.
Nancy Chen5da0fd52014-07-08 14:16:17 -0700738 */
Nancy Chen36c62f32014-10-21 18:36:39 -0700739 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
740 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
Nancy Chen5da0fd52014-07-08 14:16:17 -0700741
742 }
743
744 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700745 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700746 *
747 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -0700748 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700749 public void conference(Call callToConferenceWith) {
750 if (callToConferenceWith != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700751 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700752 }
Ihab Awade63fadb2014-07-09 21:52:04 -0700753 }
754
755 /**
756 * Instructs this {@code Call} to split from any conference call with which it may be
757 * connected.
758 */
759 public void splitFromConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700760 mInCallAdapter.splitFromConference(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700761 }
762
763 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800764 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -0700765 */
766 public void mergeConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700767 mInCallAdapter.mergeConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -0700768 }
769
770 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800771 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -0700772 */
773 public void swapConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700774 mInCallAdapter.swapConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -0700775 }
776
777 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700778 * Obtains the parent of this {@code Call} in a conference, if any.
779 *
780 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
781 * child of any conference {@code Call}s.
782 */
783 public Call getParent() {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700784 if (mParentId != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700785 return mPhone.internalGetCallByTelecomId(mParentId);
Santos Cordon823fd3c2014-08-07 18:35:18 -0700786 }
787 return null;
Ihab Awade63fadb2014-07-09 21:52:04 -0700788 }
789
790 /**
791 * Obtains the children of this conference {@code Call}, if any.
792 *
793 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
794 * {@code List} otherwise.
795 */
796 public List<Call> getChildren() {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700797 if (!mChildrenCached) {
798 mChildrenCached = true;
799 mChildren.clear();
800
801 for(String id : mChildrenIds) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700802 Call call = mPhone.internalGetCallByTelecomId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -0700803 if (call == null) {
804 // At least one child was still not found, so do not save true for "cached"
805 mChildrenCached = false;
806 } else {
807 mChildren.add(call);
808 }
809 }
810 }
811
Ihab Awade63fadb2014-07-09 21:52:04 -0700812 return mUnmodifiableChildren;
813 }
814
815 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700816 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
817 *
818 * @return The list of conferenceable {@code Call}s.
819 */
820 public List<Call> getConferenceableCalls() {
821 return mUnmodifiableConferenceableCalls;
822 }
823
824 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700825 * Obtains the state of this {@code Call}.
826 *
827 * @return A state value, chosen from the {@code STATE_*} constants.
828 */
829 public int getState() {
830 return mState;
831 }
832
833 /**
834 * Obtains a list of canned, pre-configured message responses to present to the user as
835 * ways of rejecting this {@code Call} using via a text message.
836 *
837 * @see #reject(boolean, String)
838 *
839 * @return A list of canned text message responses.
840 */
841 public List<String> getCannedTextResponses() {
842 return mCannedTextResponses;
843 }
844
845 /**
846 * Obtains an object that can be used to display video from this {@code Call}.
847 *
Andrew Lee50aca232014-07-22 16:41:54 -0700848 * @return An {@code Call.VideoCall}.
Tyler Gunn75537ae2014-08-22 11:33:13 -0700849 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -0700850 */
Andrew Lee50aca232014-07-22 16:41:54 -0700851 public InCallService.VideoCall getVideoCall() {
852 return mVideoCall;
Ihab Awade63fadb2014-07-09 21:52:04 -0700853 }
854
855 /**
856 * Obtains an object containing call details.
857 *
858 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
859 * result may be {@code null}.
860 */
861 public Details getDetails() {
862 return mDetails;
863 }
864
865 /**
866 * Adds a listener to this {@code Call}.
867 *
868 * @param listener A {@code Listener}.
869 */
870 public void addListener(Listener listener) {
871 mListeners.add(listener);
872 }
873
874 /**
875 * Removes a listener from this {@code Call}.
876 *
877 * @param listener A {@code Listener}.
878 */
879 public void removeListener(Listener listener) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700880 if (listener != null) {
881 mListeners.remove(listener);
882 }
Ihab Awade63fadb2014-07-09 21:52:04 -0700883 }
884
885 /** {@hide} */
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700886 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter) {
Ihab Awade63fadb2014-07-09 21:52:04 -0700887 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700888 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700889 mInCallAdapter = inCallAdapter;
890 mState = STATE_NEW;
891 }
892
893 /** {@hide} */
894 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700895 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700896 }
897
898 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700899 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Ihab Awade63fadb2014-07-09 21:52:04 -0700900 // First, we update the internal state as far as possible before firing any updates.
Ihab Awade63fadb2014-07-09 21:52:04 -0700901 Details details = new Details(
Santos Cordon88b771d2014-07-19 13:10:40 -0700902 parcelableCall.getHandle(),
903 parcelableCall.getHandlePresentation(),
904 parcelableCall.getCallerDisplayName(),
905 parcelableCall.getCallerDisplayNamePresentation(),
906 parcelableCall.getAccountHandle(),
907 parcelableCall.getCapabilities(),
Andrew Lee223ad142014-08-27 16:33:08 -0700908 parcelableCall.getProperties(),
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700909 parcelableCall.getDisconnectCause(),
Santos Cordon88b771d2014-07-19 13:10:40 -0700910 parcelableCall.getConnectTimeMillis(),
911 parcelableCall.getGatewayInfo(),
912 parcelableCall.getVideoState(),
Nancy Chen10798dc2014-08-08 14:00:25 -0700913 parcelableCall.getStatusHints(),
Rekha Kumar07366812015-03-24 16:42:31 -0700914 parcelableCall.getExtras(),
915 parcelableCall.getCallSubstate());
Ihab Awade63fadb2014-07-09 21:52:04 -0700916 boolean detailsChanged = !Objects.equals(mDetails, details);
917 if (detailsChanged) {
918 mDetails = details;
919 }
920
921 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -0700922 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
923 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
924 mCannedTextResponses =
925 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Ihab Awade63fadb2014-07-09 21:52:04 -0700926 }
927
Andrew Lee50aca232014-07-22 16:41:54 -0700928 boolean videoCallChanged = !Objects.equals(mVideoCall, parcelableCall.getVideoCall());
929 if (videoCallChanged) {
930 mVideoCall = parcelableCall.getVideoCall();
Ihab Awade63fadb2014-07-09 21:52:04 -0700931 }
932
Santos Cordon88b771d2014-07-19 13:10:40 -0700933 int state = stateFromParcelableCallState(parcelableCall.getState());
Ihab Awade63fadb2014-07-09 21:52:04 -0700934 boolean stateChanged = mState != state;
935 if (stateChanged) {
936 mState = state;
937 }
938
Santos Cordon823fd3c2014-08-07 18:35:18 -0700939 String parentId = parcelableCall.getParentCallId();
940 boolean parentChanged = !Objects.equals(mParentId, parentId);
941 if (parentChanged) {
942 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700943 }
944
Santos Cordon823fd3c2014-08-07 18:35:18 -0700945 List<String> childCallIds = parcelableCall.getChildCallIds();
946 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
947 if (childrenChanged) {
948 mChildrenIds.clear();
949 mChildrenIds.addAll(parcelableCall.getChildCallIds());
950 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -0700951 }
952
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700953 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
954 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
955 for (String otherId : conferenceableCallIds) {
956 if (callIdMap.containsKey(otherId)) {
957 conferenceableCalls.add(callIdMap.get(otherId));
958 }
959 }
960
961 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
962 mConferenceableCalls.clear();
963 mConferenceableCalls.addAll(conferenceableCalls);
964 fireConferenceableCallsChanged();
965 }
966
Ihab Awade63fadb2014-07-09 21:52:04 -0700967 // Now we fire updates, ensuring that any client who listens to any of these notifications
968 // gets the most up-to-date state.
969
970 if (stateChanged) {
971 fireStateChanged(mState);
972 }
973 if (detailsChanged) {
974 fireDetailsChanged(mDetails);
975 }
976 if (cannedTextResponsesChanged) {
977 fireCannedTextResponsesLoaded(mCannedTextResponses);
978 }
Andrew Lee50aca232014-07-22 16:41:54 -0700979 if (videoCallChanged) {
980 fireVideoCallChanged(mVideoCall);
Ihab Awade63fadb2014-07-09 21:52:04 -0700981 }
Santos Cordon823fd3c2014-08-07 18:35:18 -0700982 if (parentChanged) {
983 fireParentChanged(getParent());
984 }
985 if (childrenChanged) {
986 fireChildrenChanged(getChildren());
987 }
Ihab Awade63fadb2014-07-09 21:52:04 -0700988
989 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
990 // remove ourselves from the Phone. Note that we do this after completing all state updates
991 // so a client can cleanly transition all their UI to the state appropriate for a
992 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
993 if (mState == STATE_DISCONNECTED) {
994 fireCallDestroyed();
995 mPhone.internalRemoveCall(this);
996 }
997 }
998
999 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07001000 final void internalSetPostDialWait(String remaining) {
1001 mRemainingPostDialSequence = remaining;
1002 firePostDialWait(mRemainingPostDialSequence);
1003 }
1004
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07001005 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -07001006 final void internalSetDisconnected() {
1007 if (mState != Call.STATE_DISCONNECTED) {
1008 mState = Call.STATE_DISCONNECTED;
1009 fireStateChanged(mState);
1010 fireCallDestroyed();
1011 mPhone.internalRemoveCall(this);
1012 }
1013 }
1014
Ihab Awade63fadb2014-07-09 21:52:04 -07001015 private void fireStateChanged(int newState) {
Jay Shrauner229e3822014-08-15 09:23:07 -07001016 for (Listener listener : mListeners) {
1017 listener.onStateChanged(this, newState);
Ihab Awade63fadb2014-07-09 21:52:04 -07001018 }
1019 }
1020
1021 private void fireParentChanged(Call newParent) {
Jay Shrauner229e3822014-08-15 09:23:07 -07001022 for (Listener listener : mListeners) {
1023 listener.onParentChanged(this, newParent);
Ihab Awade63fadb2014-07-09 21:52:04 -07001024 }
1025 }
1026
1027 private void fireChildrenChanged(List<Call> children) {
Jay Shrauner229e3822014-08-15 09:23:07 -07001028 for (Listener listener : mListeners) {
1029 listener.onChildrenChanged(this, children);
Ihab Awade63fadb2014-07-09 21:52:04 -07001030 }
1031 }
1032
1033 private void fireDetailsChanged(Details details) {
Jay Shrauner229e3822014-08-15 09:23:07 -07001034 for (Listener listener : mListeners) {
1035 listener.onDetailsChanged(this, details);
Ihab Awade63fadb2014-07-09 21:52:04 -07001036 }
1037 }
1038
1039 private void fireCannedTextResponsesLoaded(List<String> cannedTextResponses) {
Jay Shrauner229e3822014-08-15 09:23:07 -07001040 for (Listener listener : mListeners) {
1041 listener.onCannedTextResponsesLoaded(this, cannedTextResponses);
Ihab Awade63fadb2014-07-09 21:52:04 -07001042 }
1043 }
1044
Andrew Lee50aca232014-07-22 16:41:54 -07001045 private void fireVideoCallChanged(InCallService.VideoCall videoCall) {
Jay Shrauner229e3822014-08-15 09:23:07 -07001046 for (Listener listener : mListeners) {
1047 listener.onVideoCallChanged(this, videoCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07001048 }
1049 }
1050
Ihab Awade63fadb2014-07-09 21:52:04 -07001051 private void firePostDialWait(String remainingPostDialSequence) {
Jay Shrauner229e3822014-08-15 09:23:07 -07001052 for (Listener listener : mListeners) {
1053 listener.onPostDialWait(this, remainingPostDialSequence);
Ihab Awade63fadb2014-07-09 21:52:04 -07001054 }
1055 }
1056
1057 private void fireCallDestroyed() {
Jay Shrauner229e3822014-08-15 09:23:07 -07001058 for (Listener listener : mListeners) {
1059 listener.onCallDestroyed(this);
Ihab Awade63fadb2014-07-09 21:52:04 -07001060 }
1061 }
1062
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001063 private void fireConferenceableCallsChanged() {
Jay Shrauner229e3822014-08-15 09:23:07 -07001064 for (Listener listener : mListeners) {
1065 listener.onConferenceableCallsChanged(this, mUnmodifiableConferenceableCalls);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001066 }
1067 }
1068
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001069 private int stateFromParcelableCallState(int parcelableCallState) {
Santos Cordon88b771d2014-07-19 13:10:40 -07001070 switch (parcelableCallState) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001071 case CallState.NEW:
Ihab Awade63fadb2014-07-09 21:52:04 -07001072 return STATE_NEW;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001073 case CallState.CONNECTING:
Nancy Chene20930f2014-08-07 16:17:21 -07001074 return STATE_CONNECTING;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001075 case CallState.PRE_DIAL_WAIT:
Nancy Chen5da0fd52014-07-08 14:16:17 -07001076 return STATE_PRE_DIAL_WAIT;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001077 case CallState.DIALING:
Ihab Awade63fadb2014-07-09 21:52:04 -07001078 return STATE_DIALING;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001079 case CallState.RINGING:
Ihab Awade63fadb2014-07-09 21:52:04 -07001080 return STATE_RINGING;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001081 case CallState.ACTIVE:
Ihab Awade63fadb2014-07-09 21:52:04 -07001082 return STATE_ACTIVE;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001083 case CallState.ON_HOLD:
Ihab Awade63fadb2014-07-09 21:52:04 -07001084 return STATE_HOLDING;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001085 case CallState.DISCONNECTED:
Ihab Awade63fadb2014-07-09 21:52:04 -07001086 return STATE_DISCONNECTED;
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001087 case CallState.ABORTED:
Ihab Awade63fadb2014-07-09 21:52:04 -07001088 return STATE_DISCONNECTED;
Tyler Gunn4afc6af2014-10-07 10:14:55 -07001089 case CallState.DISCONNECTING:
1090 return STATE_DISCONNECTING;
Ihab Awade63fadb2014-07-09 21:52:04 -07001091 default:
Santos Cordon88b771d2014-07-19 13:10:40 -07001092 Log.wtf(this, "Unrecognized CallState %s", parcelableCallState);
Ihab Awade63fadb2014-07-09 21:52:04 -07001093 return STATE_NEW;
1094 }
1095 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001096}