blob: fee64951e3e322c72562d7844e14e79dbcdda11a [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
Andrew Leeda80c872015-04-15 14:09:50 -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;
Andrew Lee011728f2015-04-23 15:47:06 -070022import android.os.Handler;
Ihab Awade63fadb2014-07-09 21:52:04 -070023
Andrew Lee50aca232014-07-22 16:41:54 -070024import java.lang.String;
Ihab Awade63fadb2014-07-09 21:52:04 -070025import java.util.ArrayList;
26import java.util.Collections;
Andrew Lee011728f2015-04-23 15:47:06 -070027import java.util.LinkedList;
Ihab Awade63fadb2014-07-09 21:52:04 -070028import java.util.List;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070029import java.util.Map;
Ihab Awade63fadb2014-07-09 21:52:04 -070030import java.util.Objects;
Jay Shrauner229e3822014-08-15 09:23:07 -070031import java.util.concurrent.CopyOnWriteArrayList;
Ihab Awade63fadb2014-07-09 21:52:04 -070032
33/**
34 * Represents an ongoing phone call that the in-call app should present to the user.
35 */
36public final class Call {
37 /**
38 * The state of a {@code Call} when newly created.
39 */
40 public static final int STATE_NEW = 0;
41
42 /**
43 * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
44 */
45 public static final int STATE_DIALING = 1;
46
47 /**
48 * The state of an incoming {@code Call} when ringing locally, but not yet connected.
49 */
50 public static final int STATE_RINGING = 2;
51
52 /**
53 * The state of a {@code Call} when in a holding state.
54 */
55 public static final int STATE_HOLDING = 3;
56
57 /**
58 * The state of a {@code Call} when actively supporting conversation.
59 */
60 public static final int STATE_ACTIVE = 4;
61
62 /**
63 * The state of a {@code Call} when no further voice or other communication is being
64 * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
65 * is no longer active, and the local data transport has or inevitably will release resources
66 * associated with this {@code Call}.
67 */
68 public static final int STATE_DISCONNECTED = 7;
69
Nancy Chen5da0fd52014-07-08 14:16:17 -070070 /**
Santos Cordone3c507b2015-04-23 14:44:19 -070071 * The state of an outgoing {@code Call} when waiting on user to select a
72 * {@link PhoneAccount} through which to place the call.
Nancy Chen5da0fd52014-07-08 14:16:17 -070073 */
Santos Cordone3c507b2015-04-23 14:44:19 -070074 public static final int STATE_SELECT_PHONE_ACCOUNT = 8;
75
76 /**
77 * @hide
78 * @deprecated use STATE_SELECT_PHONE_ACCOUNT.
79 */
80 @Deprecated
81 @SystemApi
82 public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT;
Nancy Chen5da0fd52014-07-08 14:16:17 -070083
Nancy Chene20930f2014-08-07 16:17:21 -070084 /**
Nancy Chene9b7a8e2014-08-08 14:26:27 -070085 * The initial state of an outgoing {@code Call}.
86 * Common transitions are to {@link #STATE_DIALING} state for a successful call or
87 * {@link #STATE_DISCONNECTED} if it failed.
Nancy Chene20930f2014-08-07 16:17:21 -070088 */
89 public static final int STATE_CONNECTING = 9;
90
Nancy Chen513c8922014-09-17 14:47:20 -070091 /**
Tyler Gunn4afc6af2014-10-07 10:14:55 -070092 * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
93 * call has not yet been disconnected by the underlying {@code ConnectionService}. The next
94 * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
95 */
96 public static final int STATE_DISCONNECTING = 10;
97
98 /**
Nancy Chen513c8922014-09-17 14:47:20 -070099 * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
100 * extras. Used to pass the phone accounts to display on the front end to the user in order to
101 * select phone accounts to (for example) place a call.
Nancy Chen513c8922014-09-17 14:47:20 -0700102 */
103 public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
104
Ihab Awade63fadb2014-07-09 21:52:04 -0700105 public static class Details {
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800106
107 /** Call can currently be put on hold or unheld. */
108 public static final int CAPABILITY_HOLD = 0x00000001;
109
110 /** Call supports the hold feature. */
111 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
112
113 /**
114 * Calls within a conference can be merged. A {@link ConnectionService} has the option to
115 * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
116 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
117 * capability allows a merge button to be shown while the conference call is in the foreground
118 * of the in-call UI.
119 * <p>
120 * This is only intended for use by a {@link Conference}.
121 */
122 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
123
124 /**
125 * Calls within a conference can be swapped between foreground and background.
126 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
127 * <p>
128 * This is only intended for use by a {@link Conference}.
129 */
130 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
131
132 /**
133 * @hide
134 */
Andrew Lee2378ea72015-04-29 14:38:11 -0700135 public static final int CAPABILITY_UNUSED_1 = 0x00000010;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800136
137 /** Call supports responding via text option. */
138 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
139
140 /** Call can be muted. */
141 public static final int CAPABILITY_MUTE = 0x00000040;
142
143 /**
144 * Call supports conference call management. This capability only applies to {@link Conference}
145 * calls which can have {@link Connection}s as children.
146 */
147 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
148
149 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700150 * Local device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800151 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700152 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800153
154 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700155 * Local device supports transmitting video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800156 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700157 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800158
159 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700160 * Local device supports bidirectional video calling.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800161 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700162 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700163 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800164
165 /**
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700166 * Remote device supports receiving video.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800167 */
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700168 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
169
170 /**
171 * Remote device supports transmitting video.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700172 */
173 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
174
175 /**
176 * Remote device supports bidirectional video calling.
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700177 */
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700178 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700179 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;
190
191 /**
Dong Zhou89f41eb2015-03-15 11:59:49 -0500192 * Speed up audio setup for MT call.
193 * @hide
194 */
Tyler Gunn96d6c402015-03-18 12:39:23 -0700195 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
196
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700197 /**
198 * Call can be upgraded to a video call.
Rekha Kumar07366812015-03-24 16:42:31 -0700199 * @hide
200 */
201 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
202
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700203 /**
204 * For video calls, indicates whether the outgoing video for the call can be paused using
205 * the {@link android.telecom.VideoProfile.VideoState#PAUSED} VideoState.
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700206 */
207 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
208
Tyler Gunnd11a3152015-03-18 13:09:14 -0700209 //******************************************************************************************
Andrew Lee2378ea72015-04-29 14:38:11 -0700210 // Next CAPABILITY value: 0x00004000
211 //******************************************************************************************
212
213 /**
214 * Whether the call is currently a conference.
215 */
216 public static final int PROPERTY_CONFERENCE = 0x00000001;
217
218 /**
219 * Whether the call is a generic conference, where we do not know the precise state of
220 * participants in the conference (eg. on CDMA).
221 */
222 public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
223
224 /**
225 * Whether the call is made while the device is in emergency callback mode.
226 */
227 public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
228
229 /**
230 * Connection is using WIFI.
231 */
232 public static final int PROPERTY_WIFI = 0x00000008;
233
234 /**
235 * Call is using high definition audio.
236 */
237 public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
238
239 //******************************************************************************************
240 // Next PROPERTY value: 0x00000020
Tyler Gunnd11a3152015-03-18 13:09:14 -0700241 //******************************************************************************************
Tyler Gunn068085b2015-02-06 13:56:52 -0800242
Ihab Awade63fadb2014-07-09 21:52:04 -0700243 private final Uri mHandle;
244 private final int mHandlePresentation;
245 private final String mCallerDisplayName;
246 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700247 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700248 private final int mCallCapabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700249 private final int mCallProperties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700250 private final DisconnectCause mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700251 private final long mConnectTimeMillis;
252 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700253 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700254 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700255 private final Bundle mExtras;
Ihab Awade63fadb2014-07-09 21:52:04 -0700256
257 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800258 * Whether the supplied capabilities supports the specified capability.
259 *
260 * @param capabilities A bit field of capabilities.
261 * @param capability The capability to check capabilities for.
262 * @return Whether the specified capability is supported.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800263 */
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.
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800273 */
274 public boolean can(int capability) {
275 return can(mCallCapabilities, capability);
276 }
277
278 /**
279 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
280 *
281 * @param capabilities A capability bit field.
282 * @return A human readable string representation.
283 */
284 public static String capabilitiesToString(int capabilities) {
285 StringBuilder builder = new StringBuilder();
286 builder.append("[Capabilities:");
287 if (can(capabilities, CAPABILITY_HOLD)) {
288 builder.append(" CAPABILITY_HOLD");
289 }
290 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
291 builder.append(" CAPABILITY_SUPPORT_HOLD");
292 }
293 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
294 builder.append(" CAPABILITY_MERGE_CONFERENCE");
295 }
296 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
297 builder.append(" CAPABILITY_SWAP_CONFERENCE");
298 }
299 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
300 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
301 }
302 if (can(capabilities, CAPABILITY_MUTE)) {
303 builder.append(" CAPABILITY_MUTE");
304 }
305 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
306 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
307 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700308 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
309 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
310 }
311 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
312 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
313 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700314 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
315 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800316 }
Andrew Lee5e9e8bb2015-03-10 13:58:24 -0700317 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
318 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
319 }
320 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
321 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
322 }
Andrew Lee9a8f9ce2015-04-10 18:09:46 -0700323 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
324 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800325 }
Dong Zhou89f41eb2015-03-15 11:59:49 -0500326 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
Tyler Gunnd11a3152015-03-18 13:09:14 -0700327 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
Dong Zhou89f41eb2015-03-15 11:59:49 -0500328 }
Rekha Kumar07366812015-03-24 16:42:31 -0700329 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
330 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
331 }
Tyler Gunnb5e0cfb2015-04-07 16:10:51 -0700332 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
333 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
334 }
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800335 builder.append("]");
336 return builder.toString();
337 }
338
339 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700340 * Whether the supplied properties includes the specified property.
341 *
342 * @param properties A bit field of properties.
343 * @param property The property to check properties for.
344 * @return Whether the specified property is supported.
345 */
346 public static boolean hasProperty(int properties, int property) {
347 return (properties & property) != 0;
348 }
349
350 /**
351 * Whether the properties of this {@code Details} includes the specified property.
352 *
353 * @param property The property to check properties for.
354 * @return Whether the specified property is supported.
355 */
356 public boolean hasProperty(int property) {
357 return hasProperty(mCallProperties, property);
358 }
359
360 /**
361 * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
362 *
363 * @param properties A property bit field.
364 * @return A human readable string representation.
365 */
366 public static String propertiesToString(int properties) {
367 StringBuilder builder = new StringBuilder();
368 builder.append("[Properties:");
369 if (hasProperty(properties, PROPERTY_CONFERENCE)) {
370 builder.append(" PROPERTY_CONFERENCE");
371 }
372 if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
373 builder.append(" PROPERTY_GENERIC_CONFERENCE");
374 }
375 if (hasProperty(properties, PROPERTY_WIFI)) {
376 builder.append(" PROPERTY_WIFI");
377 }
378 if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
379 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
380 }
381 if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
382 builder.append(" EMERGENCY_CALLBACK_MODE");
383 }
384 builder.append("]");
385 return builder.toString();
386 }
387
388 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700389 * @return The handle (e.g., phone number) to which the {@code Call} is currently
390 * connected.
391 */
392 public Uri getHandle() {
393 return mHandle;
394 }
395
396 /**
397 * @return The presentation requirements for the handle. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700398 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700399 */
400 public int getHandlePresentation() {
401 return mHandlePresentation;
402 }
403
404 /**
405 * @return The display name for the caller.
406 */
407 public String getCallerDisplayName() {
408 return mCallerDisplayName;
409 }
410
411 /**
412 * @return The presentation requirements for the caller display name. See
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700413 * {@link TelecomManager} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700414 */
415 public int getCallerDisplayNamePresentation() {
416 return mCallerDisplayNamePresentation;
417 }
418
419 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700420 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
421 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700422 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700423 public PhoneAccountHandle getAccountHandle() {
424 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -0700425 }
426
427 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800428 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
429 * {@code CAPABILITY_*} constants in this class.
Ihab Awade63fadb2014-07-09 21:52:04 -0700430 */
Ihab Awad5d0410f2014-07-30 10:07:40 -0700431 public int getCallCapabilities() {
432 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700433 }
434
435 /**
Andrew Lee2378ea72015-04-29 14:38:11 -0700436 * @return A bitmask of the properties of the {@code Call}, as defined by the various
437 * {@code PROPERTY_*} constants in this class.
Andrew Lee223ad142014-08-27 16:33:08 -0700438 */
439 public int getCallProperties() {
440 return mCallProperties;
441 }
442
443 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700444 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
Nancy Chenf4cf77c2014-09-19 10:53:21 -0700445 * by {@link android.telecom.DisconnectCause}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700446 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700447 public DisconnectCause getDisconnectCause() {
448 return mDisconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700449 }
450
451 /**
452 * @return The time the {@code Call} has been connected. This information is updated
453 * periodically, but user interfaces should not rely on this to display any "call time
454 * clock".
455 */
Jay Shrauner164a0ac2015-04-14 18:16:10 -0700456 public final long getConnectTimeMillis() {
Ihab Awade63fadb2014-07-09 21:52:04 -0700457 return mConnectTimeMillis;
458 }
459
460 /**
461 * @return Information about any calling gateway the {@code Call} may be using.
462 */
463 public GatewayInfo getGatewayInfo() {
464 return mGatewayInfo;
465 }
466
Andrew Lee7a341382014-07-15 17:05:08 -0700467 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -0700468 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -0700469 */
470 public int getVideoState() {
471 return mVideoState;
472 }
473
Ihab Awad5d0410f2014-07-30 10:07:40 -0700474 /**
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700475 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
Ihab Awad5d0410f2014-07-30 10:07:40 -0700476 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -0700477 */
478 public StatusHints getStatusHints() {
479 return mStatusHints;
480 }
481
Nancy Chen10798dc2014-08-08 14:00:25 -0700482 /**
483 * @return A bundle extras to pass with the call
484 */
485 public Bundle getExtras() {
486 return mExtras;
487 }
488
Ihab Awade63fadb2014-07-09 21:52:04 -0700489 @Override
490 public boolean equals(Object o) {
491 if (o instanceof Details) {
492 Details d = (Details) o;
493 return
494 Objects.equals(mHandle, d.mHandle) &&
495 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
496 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
497 Objects.equals(mCallerDisplayNamePresentation,
498 d.mCallerDisplayNamePresentation) &&
Evan Charlton8c8a0622014-07-20 12:31:00 -0700499 Objects.equals(mAccountHandle, d.mAccountHandle) &&
Ihab Awad5d0410f2014-07-30 10:07:40 -0700500 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Andrew Lee223ad142014-08-27 16:33:08 -0700501 Objects.equals(mCallProperties, d.mCallProperties) &&
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700502 Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
Ihab Awade63fadb2014-07-09 21:52:04 -0700503 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Andrew Lee85f5d422014-07-11 17:22:03 -0700504 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Evan Charlton5b49ade2014-07-15 17:03:20 -0700505 Objects.equals(mVideoState, d.mVideoState) &&
Nancy Chen10798dc2014-08-08 14:00:25 -0700506 Objects.equals(mStatusHints, d.mStatusHints) &&
Jay Shrauner8f988432015-04-16 12:52:19 -0700507 Objects.equals(mExtras, d.mExtras);
Ihab Awade63fadb2014-07-09 21:52:04 -0700508 }
509 return false;
510 }
511
512 @Override
513 public int hashCode() {
514 return
515 Objects.hashCode(mHandle) +
516 Objects.hashCode(mHandlePresentation) +
517 Objects.hashCode(mCallerDisplayName) +
518 Objects.hashCode(mCallerDisplayNamePresentation) +
Evan Charlton8c8a0622014-07-20 12:31:00 -0700519 Objects.hashCode(mAccountHandle) +
Ihab Awad5d0410f2014-07-30 10:07:40 -0700520 Objects.hashCode(mCallCapabilities) +
Andrew Lee223ad142014-08-27 16:33:08 -0700521 Objects.hashCode(mCallProperties) +
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700522 Objects.hashCode(mDisconnectCause) +
Ihab Awade63fadb2014-07-09 21:52:04 -0700523 Objects.hashCode(mConnectTimeMillis) +
Andrew Lee85f5d422014-07-11 17:22:03 -0700524 Objects.hashCode(mGatewayInfo) +
Evan Charlton5b49ade2014-07-15 17:03:20 -0700525 Objects.hashCode(mVideoState) +
Nancy Chen10798dc2014-08-08 14:00:25 -0700526 Objects.hashCode(mStatusHints) +
Jay Shrauner8f988432015-04-16 12:52:19 -0700527 Objects.hashCode(mExtras);
Ihab Awade63fadb2014-07-09 21:52:04 -0700528 }
529
530 /** {@hide} */
531 public Details(
532 Uri handle,
533 int handlePresentation,
534 String callerDisplayName,
535 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -0700536 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -0700537 int capabilities,
Andrew Lee223ad142014-08-27 16:33:08 -0700538 int properties,
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700539 DisconnectCause disconnectCause,
Ihab Awade63fadb2014-07-09 21:52:04 -0700540 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -0700541 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -0700542 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -0700543 StatusHints statusHints,
Jay Shrauner8f988432015-04-16 12:52:19 -0700544 Bundle extras) {
Ihab Awade63fadb2014-07-09 21:52:04 -0700545 mHandle = handle;
546 mHandlePresentation = handlePresentation;
547 mCallerDisplayName = callerDisplayName;
548 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700549 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700550 mCallCapabilities = capabilities;
Andrew Lee223ad142014-08-27 16:33:08 -0700551 mCallProperties = properties;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700552 mDisconnectCause = disconnectCause;
Ihab Awade63fadb2014-07-09 21:52:04 -0700553 mConnectTimeMillis = connectTimeMillis;
554 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700555 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700556 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700557 mExtras = extras;
Ihab Awade63fadb2014-07-09 21:52:04 -0700558 }
559 }
560
Andrew Leeda80c872015-04-15 14:09:50 -0700561 public static abstract class Callback {
Ihab Awade63fadb2014-07-09 21:52:04 -0700562 /**
563 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
564 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700565 * @param call The {@code Call} invoking this method.
566 * @param state The new state of the {@code Call}.
567 */
568 public void onStateChanged(Call call, int state) {}
569
570 /**
571 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
572 *
573 * @param call The {@code Call} invoking this method.
574 * @param parent The new parent of the {@code Call}.
575 */
576 public void onParentChanged(Call call, Call parent) {}
577
578 /**
579 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
580 *
581 * @param call The {@code Call} invoking this method.
582 * @param children The new children of the {@code Call}.
583 */
584 public void onChildrenChanged(Call call, List<Call> children) {}
585
586 /**
587 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
588 *
589 * @param call The {@code Call} invoking this method.
590 * @param details A {@code Details} object describing the {@code Call}.
591 */
592 public void onDetailsChanged(Call call, Details details) {}
593
594 /**
595 * Invoked when the text messages that can be used as responses to the incoming
596 * {@code Call} are loaded from the relevant database.
597 * See {@link #getCannedTextResponses()}.
598 *
599 * @param call The {@code Call} invoking this method.
600 * @param cannedTextResponses The text messages useable as responses.
601 */
602 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
603
604 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700605 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
606 * character. This causes the post-dial signals to stop pending user confirmation. An
607 * implementation should present this choice to the user and invoke
608 * {@link #postDialContinue(boolean)} when the user makes the choice.
609 *
610 * @param call The {@code Call} invoking this method.
611 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
612 */
613 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
614
615 /**
Andrew Lee50aca232014-07-22 16:41:54 -0700616 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700617 *
618 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -0700619 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700620 */
Andrew Lee50aca232014-07-22 16:41:54 -0700621 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -0700622
623 /**
624 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
625 * up their UI for the {@code Call} in response to state transitions. Specifically,
626 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
627 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
628 * clients should wait for this method to be invoked.
629 *
630 * @param call The {@code Call} being destroyed.
631 */
632 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700633
634 /**
635 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
636 * conferenced.
637 *
638 * @param call The {@code Call} being updated.
639 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
640 * conferenced.
641 */
642 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Ihab Awade63fadb2014-07-09 21:52:04 -0700643 }
644
Andrew Leeda80c872015-04-15 14:09:50 -0700645 /**
646 * @deprecated Use {@code Call.Callback} instead.
647 * @hide
648 */
649 @Deprecated
650 @SystemApi
651 public static abstract class Listener extends Callback { }
652
Ihab Awade63fadb2014-07-09 21:52:04 -0700653 private final Phone mPhone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700654 private final String mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700655 private final InCallAdapter mInCallAdapter;
Santos Cordon823fd3c2014-08-07 18:35:18 -0700656 private final List<String> mChildrenIds = new ArrayList<>();
Ihab Awade63fadb2014-07-09 21:52:04 -0700657 private final List<Call> mChildren = new ArrayList<>();
658 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Andrew Lee011728f2015-04-23 15:47:06 -0700659 private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700660 private final List<Call> mConferenceableCalls = new ArrayList<>();
661 private final List<Call> mUnmodifiableConferenceableCalls =
662 Collections.unmodifiableList(mConferenceableCalls);
663
Santos Cordon823fd3c2014-08-07 18:35:18 -0700664 private boolean mChildrenCached;
665 private String mParentId = null;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700666 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -0700667 private List<String> mCannedTextResponses = null;
668 private String mRemainingPostDialSequence;
Andrew Lee50aca232014-07-22 16:41:54 -0700669 private InCallService.VideoCall mVideoCall;
Ihab Awade63fadb2014-07-09 21:52:04 -0700670 private Details mDetails;
Ihab Awade63fadb2014-07-09 21:52:04 -0700671
672 /**
673 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
674 *
675 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
676 * remaining or this {@code Call} is not in a post-dial state.
677 */
678 public String getRemainingPostDialSequence() {
679 return mRemainingPostDialSequence;
680 }
681
682 /**
683 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700684 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -0700685 */
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700686 public void answer(int videoState) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700687 mInCallAdapter.answerCall(mTelecomCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -0700688 }
689
690 /**
691 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
692 *
693 * @param rejectWithMessage Whether to reject with a text message.
694 * @param textMessage An optional text message with which to respond.
695 */
696 public void reject(boolean rejectWithMessage, String textMessage) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700697 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
Ihab Awade63fadb2014-07-09 21:52:04 -0700698 }
699
700 /**
701 * Instructs this {@code Call} to disconnect.
702 */
703 public void disconnect() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700704 mInCallAdapter.disconnectCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700705 }
706
707 /**
708 * Instructs this {@code Call} to go on hold.
709 */
710 public void hold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700711 mInCallAdapter.holdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700712 }
713
714 /**
715 * Instructs this {@link #STATE_HOLDING} call to release from hold.
716 */
717 public void unhold() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700718 mInCallAdapter.unholdCall(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700719 }
720
721 /**
722 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
723 *
724 * Any other currently playing DTMF tone in the specified call is immediately stopped.
725 *
726 * @param digit A character representing the DTMF digit for which to play the tone. This
727 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
728 */
729 public void playDtmfTone(char digit) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700730 mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
Ihab Awade63fadb2014-07-09 21:52:04 -0700731 }
732
733 /**
734 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
735 * currently playing.
736 *
737 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
738 * currently playing, this method will do nothing.
739 */
740 public void stopDtmfTone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700741 mInCallAdapter.stopDtmfTone(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700742 }
743
744 /**
745 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
746 *
747 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
748 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -0700749 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700750 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -0700751 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
752 *
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700753 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
Andrew Leeda80c872015-04-15 14:09:50 -0700754 * {@code Call} will pause playing the tones and notify callbacks via
755 * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
Ihab Awade63fadb2014-07-09 21:52:04 -0700756 * should display to the user an indication of this state and an affordance to continue
757 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
758 * app should invoke the {@link #postDialContinue(boolean)} method.
759 *
760 * @param proceed Whether or not to continue with the post-dial sequence.
761 */
762 public void postDialContinue(boolean proceed) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700763 mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
Ihab Awade63fadb2014-07-09 21:52:04 -0700764 }
765
766 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -0700767 * Notifies this {@code Call} that an account has been selected and to proceed with placing
Nancy Chen36c62f32014-10-21 18:36:39 -0700768 * an outgoing call. Optionally sets this account as the default account.
Nancy Chen5da0fd52014-07-08 14:16:17 -0700769 */
Nancy Chen36c62f32014-10-21 18:36:39 -0700770 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
771 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
Nancy Chen5da0fd52014-07-08 14:16:17 -0700772
773 }
774
775 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700776 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700777 *
778 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -0700779 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700780 public void conference(Call callToConferenceWith) {
781 if (callToConferenceWith != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700782 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700783 }
Ihab Awade63fadb2014-07-09 21:52:04 -0700784 }
785
786 /**
787 * Instructs this {@code Call} to split from any conference call with which it may be
788 * connected.
789 */
790 public void splitFromConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700791 mInCallAdapter.splitFromConference(mTelecomCallId);
Ihab Awade63fadb2014-07-09 21:52:04 -0700792 }
793
794 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800795 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -0700796 */
797 public void mergeConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700798 mInCallAdapter.mergeConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -0700799 }
800
801 /**
Ihab Awad5c9c86e2014-11-12 13:41:16 -0800802 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
Santos Cordona4868042014-09-04 17:39:22 -0700803 */
804 public void swapConference() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700805 mInCallAdapter.swapConference(mTelecomCallId);
Santos Cordona4868042014-09-04 17:39:22 -0700806 }
807
808 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700809 * Obtains the parent of this {@code Call} in a conference, if any.
810 *
811 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
812 * child of any conference {@code Call}s.
813 */
814 public Call getParent() {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700815 if (mParentId != null) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700816 return mPhone.internalGetCallByTelecomId(mParentId);
Santos Cordon823fd3c2014-08-07 18:35:18 -0700817 }
818 return null;
Ihab Awade63fadb2014-07-09 21:52:04 -0700819 }
820
821 /**
822 * Obtains the children of this conference {@code Call}, if any.
823 *
824 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
825 * {@code List} otherwise.
826 */
827 public List<Call> getChildren() {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700828 if (!mChildrenCached) {
829 mChildrenCached = true;
830 mChildren.clear();
831
832 for(String id : mChildrenIds) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700833 Call call = mPhone.internalGetCallByTelecomId(id);
Santos Cordon823fd3c2014-08-07 18:35:18 -0700834 if (call == null) {
835 // At least one child was still not found, so do not save true for "cached"
836 mChildrenCached = false;
837 } else {
838 mChildren.add(call);
839 }
840 }
841 }
842
Ihab Awade63fadb2014-07-09 21:52:04 -0700843 return mUnmodifiableChildren;
844 }
845
846 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700847 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
848 *
849 * @return The list of conferenceable {@code Call}s.
850 */
851 public List<Call> getConferenceableCalls() {
852 return mUnmodifiableConferenceableCalls;
853 }
854
855 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700856 * Obtains the state of this {@code Call}.
857 *
858 * @return A state value, chosen from the {@code STATE_*} constants.
859 */
860 public int getState() {
861 return mState;
862 }
863
864 /**
865 * Obtains a list of canned, pre-configured message responses to present to the user as
866 * ways of rejecting this {@code Call} using via a text message.
867 *
868 * @see #reject(boolean, String)
869 *
870 * @return A list of canned text message responses.
871 */
872 public List<String> getCannedTextResponses() {
873 return mCannedTextResponses;
874 }
875
876 /**
877 * Obtains an object that can be used to display video from this {@code Call}.
878 *
Andrew Lee50aca232014-07-22 16:41:54 -0700879 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700880 */
Andrew Lee50aca232014-07-22 16:41:54 -0700881 public InCallService.VideoCall getVideoCall() {
882 return mVideoCall;
Ihab Awade63fadb2014-07-09 21:52:04 -0700883 }
884
885 /**
886 * Obtains an object containing call details.
887 *
888 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
889 * result may be {@code null}.
890 */
891 public Details getDetails() {
892 return mDetails;
893 }
894
895 /**
Andrew Leeda80c872015-04-15 14:09:50 -0700896 * Registers a callback to this {@code Call}.
897 *
898 * @param callback A {@code Callback}.
899 */
900 public void registerCallback(Callback callback) {
Andrew Lee011728f2015-04-23 15:47:06 -0700901 registerCallback(callback, new Handler());
902 }
903
904 /**
905 * Registers a callback to this {@code Call}.
906 *
907 * @param callback A {@code Callback}.
908 * @param handler A handler which command and status changes will be delivered to.
909 */
910 public void registerCallback(Callback callback, Handler handler) {
911 unregisterCallback(callback);
912 if (callback != null && handler != null) {
913 mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
914 }
Andrew Leeda80c872015-04-15 14:09:50 -0700915 }
916
917 /**
918 * Unregisters a callback from this {@code Call}.
919 *
920 * @param callback A {@code Callback}.
921 */
922 public void unregisterCallback(Callback callback) {
923 if (callback != null) {
Andrew Lee011728f2015-04-23 15:47:06 -0700924 for (CallbackRecord<Callback> record : mCallbackRecords) {
925 if (record.getCallback() == callback) {
926 mCallbackRecords.remove(record);
927 break;
928 }
929 }
Andrew Leeda80c872015-04-15 14:09:50 -0700930 }
931 }
932
933 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700934 * Adds a listener to this {@code Call}.
935 *
936 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -0700937 * @deprecated Use {@link #registerCallback} instead.
938 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -0700939 */
Andrew Leeda80c872015-04-15 14:09:50 -0700940 @Deprecated
941 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -0700942 public void addListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -0700943 registerCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -0700944 }
945
946 /**
947 * Removes a listener from this {@code Call}.
948 *
949 * @param listener A {@code Listener}.
Andrew Leeda80c872015-04-15 14:09:50 -0700950 * @deprecated Use {@link #unregisterCallback} instead.
951 * @hide
Ihab Awade63fadb2014-07-09 21:52:04 -0700952 */
Andrew Leeda80c872015-04-15 14:09:50 -0700953 @Deprecated
954 @SystemApi
Ihab Awade63fadb2014-07-09 21:52:04 -0700955 public void removeListener(Listener listener) {
Andrew Leeda80c872015-04-15 14:09:50 -0700956 unregisterCallback(listener);
Ihab Awade63fadb2014-07-09 21:52:04 -0700957 }
958
Andrew Leeda80c872015-04-15 14:09:50 -0700959
Ihab Awade63fadb2014-07-09 21:52:04 -0700960 /** {@hide} */
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700961 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter) {
Ihab Awade63fadb2014-07-09 21:52:04 -0700962 mPhone = phone;
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700963 mTelecomCallId = telecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700964 mInCallAdapter = inCallAdapter;
965 mState = STATE_NEW;
966 }
967
968 /** {@hide} */
969 final String internalGetCallId() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700970 return mTelecomCallId;
Ihab Awade63fadb2014-07-09 21:52:04 -0700971 }
972
973 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700974 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Ihab Awade63fadb2014-07-09 21:52:04 -0700975 // First, we update the internal state as far as possible before firing any updates.
Ihab Awade63fadb2014-07-09 21:52:04 -0700976 Details details = new Details(
Santos Cordon88b771d2014-07-19 13:10:40 -0700977 parcelableCall.getHandle(),
978 parcelableCall.getHandlePresentation(),
979 parcelableCall.getCallerDisplayName(),
980 parcelableCall.getCallerDisplayNamePresentation(),
981 parcelableCall.getAccountHandle(),
982 parcelableCall.getCapabilities(),
Andrew Lee223ad142014-08-27 16:33:08 -0700983 parcelableCall.getProperties(),
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700984 parcelableCall.getDisconnectCause(),
Santos Cordon88b771d2014-07-19 13:10:40 -0700985 parcelableCall.getConnectTimeMillis(),
986 parcelableCall.getGatewayInfo(),
987 parcelableCall.getVideoState(),
Nancy Chen10798dc2014-08-08 14:00:25 -0700988 parcelableCall.getStatusHints(),
Jay Shrauner8f988432015-04-16 12:52:19 -0700989 parcelableCall.getExtras());
Ihab Awade63fadb2014-07-09 21:52:04 -0700990 boolean detailsChanged = !Objects.equals(mDetails, details);
991 if (detailsChanged) {
992 mDetails = details;
993 }
994
995 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -0700996 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
997 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
998 mCannedTextResponses =
999 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Ihab Awade63fadb2014-07-09 21:52:04 -07001000 }
1001
Tyler Gunn75958422015-04-15 14:23:42 -07001002 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() &&
1003 !Objects.equals(mVideoCall, parcelableCall.getVideoCall());
Andrew Lee50aca232014-07-22 16:41:54 -07001004 if (videoCallChanged) {
1005 mVideoCall = parcelableCall.getVideoCall();
Ihab Awade63fadb2014-07-09 21:52:04 -07001006 }
1007
Santos Cordone3c507b2015-04-23 14:44:19 -07001008 int state = parcelableCall.getState();
Ihab Awade63fadb2014-07-09 21:52:04 -07001009 boolean stateChanged = mState != state;
1010 if (stateChanged) {
1011 mState = state;
1012 }
1013
Santos Cordon823fd3c2014-08-07 18:35:18 -07001014 String parentId = parcelableCall.getParentCallId();
1015 boolean parentChanged = !Objects.equals(mParentId, parentId);
1016 if (parentChanged) {
1017 mParentId = parentId;
Ihab Awade63fadb2014-07-09 21:52:04 -07001018 }
1019
Santos Cordon823fd3c2014-08-07 18:35:18 -07001020 List<String> childCallIds = parcelableCall.getChildCallIds();
1021 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
1022 if (childrenChanged) {
1023 mChildrenIds.clear();
1024 mChildrenIds.addAll(parcelableCall.getChildCallIds());
1025 mChildrenCached = false;
Ihab Awade63fadb2014-07-09 21:52:04 -07001026 }
1027
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001028 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
1029 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
1030 for (String otherId : conferenceableCallIds) {
1031 if (callIdMap.containsKey(otherId)) {
1032 conferenceableCalls.add(callIdMap.get(otherId));
1033 }
1034 }
1035
1036 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
1037 mConferenceableCalls.clear();
1038 mConferenceableCalls.addAll(conferenceableCalls);
1039 fireConferenceableCallsChanged();
1040 }
1041
Ihab Awade63fadb2014-07-09 21:52:04 -07001042 // Now we fire updates, ensuring that any client who listens to any of these notifications
1043 // gets the most up-to-date state.
1044
1045 if (stateChanged) {
1046 fireStateChanged(mState);
1047 }
1048 if (detailsChanged) {
1049 fireDetailsChanged(mDetails);
1050 }
1051 if (cannedTextResponsesChanged) {
1052 fireCannedTextResponsesLoaded(mCannedTextResponses);
1053 }
Andrew Lee50aca232014-07-22 16:41:54 -07001054 if (videoCallChanged) {
1055 fireVideoCallChanged(mVideoCall);
Ihab Awade63fadb2014-07-09 21:52:04 -07001056 }
Santos Cordon823fd3c2014-08-07 18:35:18 -07001057 if (parentChanged) {
1058 fireParentChanged(getParent());
1059 }
1060 if (childrenChanged) {
1061 fireChildrenChanged(getChildren());
1062 }
Ihab Awade63fadb2014-07-09 21:52:04 -07001063
1064 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
1065 // remove ourselves from the Phone. Note that we do this after completing all state updates
1066 // so a client can cleanly transition all their UI to the state appropriate for a
1067 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
1068 if (mState == STATE_DISCONNECTED) {
1069 fireCallDestroyed();
1070 mPhone.internalRemoveCall(this);
1071 }
1072 }
1073
1074 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -07001075 final void internalSetPostDialWait(String remaining) {
1076 mRemainingPostDialSequence = remaining;
1077 firePostDialWait(mRemainingPostDialSequence);
1078 }
1079
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -07001080 /** {@hide} */
Santos Cordonf30d7e92014-08-26 09:54:33 -07001081 final void internalSetDisconnected() {
1082 if (mState != Call.STATE_DISCONNECTED) {
1083 mState = Call.STATE_DISCONNECTED;
1084 fireStateChanged(mState);
1085 fireCallDestroyed();
1086 mPhone.internalRemoveCall(this);
1087 }
1088 }
1089
Andrew Lee011728f2015-04-23 15:47:06 -07001090 private void fireStateChanged(final int newState) {
1091 for (CallbackRecord<Callback> record : mCallbackRecords) {
1092 final Call call = this;
1093 final Callback callback = record.getCallback();
1094 record.getHandler().post(new Runnable() {
1095 @Override
1096 public void run() {
1097 callback.onStateChanged(call, newState);
1098 }
1099 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001100 }
1101 }
1102
Andrew Lee011728f2015-04-23 15:47:06 -07001103 private void fireParentChanged(final Call newParent) {
1104 for (CallbackRecord<Callback> record : mCallbackRecords) {
1105 final Call call = this;
1106 final Callback callback = record.getCallback();
1107 record.getHandler().post(new Runnable() {
1108 @Override
1109 public void run() {
1110 callback.onParentChanged(call, newParent);
1111 }
1112 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001113 }
1114 }
1115
Andrew Lee011728f2015-04-23 15:47:06 -07001116 private void fireChildrenChanged(final List<Call> children) {
1117 for (CallbackRecord<Callback> record : mCallbackRecords) {
1118 final Call call = this;
1119 final Callback callback = record.getCallback();
1120 record.getHandler().post(new Runnable() {
1121 @Override
1122 public void run() {
1123 callback.onChildrenChanged(call, children);
1124 }
1125 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001126 }
1127 }
1128
Andrew Lee011728f2015-04-23 15:47:06 -07001129 private void fireDetailsChanged(final Details details) {
1130 for (CallbackRecord<Callback> record : mCallbackRecords) {
1131 final Call call = this;
1132 final Callback callback = record.getCallback();
1133 record.getHandler().post(new Runnable() {
1134 @Override
1135 public void run() {
1136 callback.onDetailsChanged(call, details);
1137 }
1138 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001139 }
1140 }
1141
Andrew Lee011728f2015-04-23 15:47:06 -07001142 private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
1143 for (CallbackRecord<Callback> record : mCallbackRecords) {
1144 final Call call = this;
1145 final Callback callback = record.getCallback();
1146 record.getHandler().post(new Runnable() {
1147 @Override
1148 public void run() {
1149 callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
1150 }
1151 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001152 }
1153 }
1154
Andrew Lee011728f2015-04-23 15:47:06 -07001155 private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
1156 for (CallbackRecord<Callback> record : mCallbackRecords) {
1157 final Call call = this;
1158 final Callback callback = record.getCallback();
1159 record.getHandler().post(new Runnable() {
1160 @Override
1161 public void run() {
1162 callback.onVideoCallChanged(call, videoCall);
1163 }
1164 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001165 }
1166 }
1167
Andrew Lee011728f2015-04-23 15:47:06 -07001168 private void firePostDialWait(final String remainingPostDialSequence) {
1169 for (CallbackRecord<Callback> record : mCallbackRecords) {
1170 final Call call = this;
1171 final Callback callback = record.getCallback();
1172 record.getHandler().post(new Runnable() {
1173 @Override
1174 public void run() {
1175 callback.onPostDialWait(call, remainingPostDialSequence);
1176 }
1177 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001178 }
1179 }
1180
1181 private void fireCallDestroyed() {
Andrew Lee011728f2015-04-23 15:47:06 -07001182 for (CallbackRecord<Callback> record: mCallbackRecords) {
1183 final Call call = this;
1184 final Callback callback = record.getCallback();
1185 record.getHandler().post(new Runnable() {
1186 @Override
1187 public void run() {
1188 callback.onCallDestroyed(call);
1189 }
1190 });
Ihab Awade63fadb2014-07-09 21:52:04 -07001191 }
1192 }
1193
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001194 private void fireConferenceableCallsChanged() {
Andrew Lee011728f2015-04-23 15:47:06 -07001195 for (CallbackRecord<Callback> record : mCallbackRecords) {
1196 final Call call = this;
1197 final Callback callback = record.getCallback();
1198 record.getHandler().post(new Runnable() {
1199 @Override
1200 public void run() {
1201 callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
1202 }
1203 });
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001204 }
1205 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001206}