blob: 7223574b28897f68c25450c6e04cf0ed8d6fa3f5 [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
17package android.telecomm;
18
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -070019import android.app.PendingIntent;
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 -070022import android.telephony.DisconnectCause;
23
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;
27import java.util.List;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070028import java.util.Map;
Ihab Awade63fadb2014-07-09 21:52:04 -070029import java.util.Objects;
Jay Shrauner229e3822014-08-15 09:23:07 -070030import java.util.concurrent.CopyOnWriteArrayList;
Ihab Awade63fadb2014-07-09 21:52:04 -070031
32/**
33 * Represents an ongoing phone call that the in-call app should present to the user.
Ihab Awadb19a0bc2014-08-07 19:46:01 -070034 *
35 * {@hide}
Ihab Awade63fadb2014-07-09 21:52:04 -070036 */
37public 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
Ihab Awade63fadb2014-07-09 21:52:04 -070083 public static class Details {
84 private final Uri mHandle;
85 private final int mHandlePresentation;
86 private final String mCallerDisplayName;
87 private final int mCallerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -070088 private final PhoneAccountHandle mAccountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -070089 private final int mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -070090 private final int mDisconnectCauseCode;
Ihab Awadb19a0bc2014-08-07 19:46:01 -070091 private final String mDisconnectCauseMessage;
Ihab Awade63fadb2014-07-09 21:52:04 -070092 private final long mConnectTimeMillis;
93 private final GatewayInfo mGatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -070094 private final int mVideoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -070095 private final StatusHints mStatusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -070096 private final Bundle mExtras;
Ihab Awade63fadb2014-07-09 21:52:04 -070097
98 /**
99 * @return The handle (e.g., phone number) to which the {@code Call} is currently
100 * connected.
101 */
102 public Uri getHandle() {
103 return mHandle;
104 }
105
106 /**
107 * @return The presentation requirements for the handle. See
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700108 * {@link PropertyPresentation} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700109 */
110 public int getHandlePresentation() {
111 return mHandlePresentation;
112 }
113
114 /**
115 * @return The display name for the caller.
116 */
117 public String getCallerDisplayName() {
118 return mCallerDisplayName;
119 }
120
121 /**
122 * @return The presentation requirements for the caller display name. See
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700123 * {@link PropertyPresentation} for valid values.
Ihab Awade63fadb2014-07-09 21:52:04 -0700124 */
125 public int getCallerDisplayNamePresentation() {
126 return mCallerDisplayNamePresentation;
127 }
128
129 /**
Evan Charlton6eb262c2014-07-19 18:18:19 -0700130 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
131 * routed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700132 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700133 public PhoneAccountHandle getAccountHandle() {
134 return mAccountHandle;
Ihab Awade63fadb2014-07-09 21:52:04 -0700135 }
136
137 /**
138 * @return A bitmask of the capabilities of the {@code Call}, as defined in
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700139 * {@link PhoneCapabilities}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700140 */
Ihab Awad5d0410f2014-07-30 10:07:40 -0700141 public int getCallCapabilities() {
142 return mCallCapabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700143 }
144
145 /**
146 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
147 * as a code chosen from among those declared in {@link DisconnectCause}.
148 */
149 public int getDisconnectCauseCode() {
150 return mDisconnectCauseCode;
151 }
152
153 /**
154 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, an optional reason for
155 * disconnection expressed as a free text message.
156 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700157 public String getDisconnectCauseMessage() {
158 return mDisconnectCauseMessage;
Ihab Awade63fadb2014-07-09 21:52:04 -0700159 }
160
161 /**
162 * @return The time the {@code Call} has been connected. This information is updated
163 * periodically, but user interfaces should not rely on this to display any "call time
164 * clock".
165 */
166 public long getConnectTimeMillis() {
167 return mConnectTimeMillis;
168 }
169
170 /**
171 * @return Information about any calling gateway the {@code Call} may be using.
172 */
173 public GatewayInfo getGatewayInfo() {
174 return mGatewayInfo;
175 }
176
Andrew Lee7a341382014-07-15 17:05:08 -0700177 /**
Ihab Awad5d0410f2014-07-30 10:07:40 -0700178 * @return The video state of the {@code Call}.
Andrew Lee7a341382014-07-15 17:05:08 -0700179 */
180 public int getVideoState() {
181 return mVideoState;
182 }
183
Ihab Awad5d0410f2014-07-30 10:07:40 -0700184 /**
185 * @return The current {@link android.telecomm.StatusHints}, or {@code null} if none
186 * have been set.
Evan Charlton5b49ade2014-07-15 17:03:20 -0700187 */
188 public StatusHints getStatusHints() {
189 return mStatusHints;
190 }
191
Nancy Chen10798dc2014-08-08 14:00:25 -0700192 /**
193 * @return A bundle extras to pass with the call
194 */
195 public Bundle getExtras() {
196 return mExtras;
197 }
198
Ihab Awade63fadb2014-07-09 21:52:04 -0700199 @Override
200 public boolean equals(Object o) {
201 if (o instanceof Details) {
202 Details d = (Details) o;
203 return
204 Objects.equals(mHandle, d.mHandle) &&
205 Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
206 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
207 Objects.equals(mCallerDisplayNamePresentation,
208 d.mCallerDisplayNamePresentation) &&
Evan Charlton8c8a0622014-07-20 12:31:00 -0700209 Objects.equals(mAccountHandle, d.mAccountHandle) &&
Ihab Awad5d0410f2014-07-30 10:07:40 -0700210 Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Ihab Awade63fadb2014-07-09 21:52:04 -0700211 Objects.equals(mDisconnectCauseCode, d.mDisconnectCauseCode) &&
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700212 Objects.equals(mDisconnectCauseMessage, d.mDisconnectCauseMessage) &&
Ihab Awade63fadb2014-07-09 21:52:04 -0700213 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Andrew Lee85f5d422014-07-11 17:22:03 -0700214 Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Evan Charlton5b49ade2014-07-15 17:03:20 -0700215 Objects.equals(mVideoState, d.mVideoState) &&
Nancy Chen10798dc2014-08-08 14:00:25 -0700216 Objects.equals(mStatusHints, d.mStatusHints) &&
217 Objects.equals(mExtras, d.mExtras);
Ihab Awade63fadb2014-07-09 21:52:04 -0700218 }
219 return false;
220 }
221
222 @Override
223 public int hashCode() {
224 return
225 Objects.hashCode(mHandle) +
226 Objects.hashCode(mHandlePresentation) +
227 Objects.hashCode(mCallerDisplayName) +
228 Objects.hashCode(mCallerDisplayNamePresentation) +
Evan Charlton8c8a0622014-07-20 12:31:00 -0700229 Objects.hashCode(mAccountHandle) +
Ihab Awad5d0410f2014-07-30 10:07:40 -0700230 Objects.hashCode(mCallCapabilities) +
Ihab Awade63fadb2014-07-09 21:52:04 -0700231 Objects.hashCode(mDisconnectCauseCode) +
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700232 Objects.hashCode(mDisconnectCauseMessage) +
Ihab Awade63fadb2014-07-09 21:52:04 -0700233 Objects.hashCode(mConnectTimeMillis) +
Andrew Lee85f5d422014-07-11 17:22:03 -0700234 Objects.hashCode(mGatewayInfo) +
Evan Charlton5b49ade2014-07-15 17:03:20 -0700235 Objects.hashCode(mVideoState) +
Nancy Chen10798dc2014-08-08 14:00:25 -0700236 Objects.hashCode(mStatusHints) +
237 Objects.hashCode(mExtras);
Ihab Awade63fadb2014-07-09 21:52:04 -0700238 }
239
240 /** {@hide} */
241 public Details(
242 Uri handle,
243 int handlePresentation,
244 String callerDisplayName,
245 int callerDisplayNamePresentation,
Evan Charlton8c8a0622014-07-20 12:31:00 -0700246 PhoneAccountHandle accountHandle,
Ihab Awade63fadb2014-07-09 21:52:04 -0700247 int capabilities,
248 int disconnectCauseCode,
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700249 String disconnectCauseMessage,
Ihab Awade63fadb2014-07-09 21:52:04 -0700250 long connectTimeMillis,
Andrew Lee85f5d422014-07-11 17:22:03 -0700251 GatewayInfo gatewayInfo,
Evan Charlton5b49ade2014-07-15 17:03:20 -0700252 int videoState,
Nancy Chen10798dc2014-08-08 14:00:25 -0700253 StatusHints statusHints,
254 Bundle extras) {
Ihab Awade63fadb2014-07-09 21:52:04 -0700255 mHandle = handle;
256 mHandlePresentation = handlePresentation;
257 mCallerDisplayName = callerDisplayName;
258 mCallerDisplayNamePresentation = callerDisplayNamePresentation;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700259 mAccountHandle = accountHandle;
Ihab Awad5d0410f2014-07-30 10:07:40 -0700260 mCallCapabilities = capabilities;
Ihab Awade63fadb2014-07-09 21:52:04 -0700261 mDisconnectCauseCode = disconnectCauseCode;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700262 mDisconnectCauseMessage = disconnectCauseMessage;
Ihab Awade63fadb2014-07-09 21:52:04 -0700263 mConnectTimeMillis = connectTimeMillis;
264 mGatewayInfo = gatewayInfo;
Andrew Lee85f5d422014-07-11 17:22:03 -0700265 mVideoState = videoState;
Evan Charlton5b49ade2014-07-15 17:03:20 -0700266 mStatusHints = statusHints;
Nancy Chen10798dc2014-08-08 14:00:25 -0700267 mExtras = extras;
Ihab Awade63fadb2014-07-09 21:52:04 -0700268 }
269 }
270
271 public static abstract class Listener {
272 /**
273 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
274 *
Ihab Awade63fadb2014-07-09 21:52:04 -0700275 * @param call The {@code Call} invoking this method.
276 * @param state The new state of the {@code Call}.
277 */
278 public void onStateChanged(Call call, int state) {}
279
280 /**
281 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
282 *
283 * @param call The {@code Call} invoking this method.
284 * @param parent The new parent of the {@code Call}.
285 */
286 public void onParentChanged(Call call, Call parent) {}
287
288 /**
289 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
290 *
291 * @param call The {@code Call} invoking this method.
292 * @param children The new children of the {@code Call}.
293 */
294 public void onChildrenChanged(Call call, List<Call> children) {}
295
296 /**
297 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
298 *
299 * @param call The {@code Call} invoking this method.
300 * @param details A {@code Details} object describing the {@code Call}.
301 */
302 public void onDetailsChanged(Call call, Details details) {}
303
304 /**
305 * Invoked when the text messages that can be used as responses to the incoming
306 * {@code Call} are loaded from the relevant database.
307 * See {@link #getCannedTextResponses()}.
308 *
309 * @param call The {@code Call} invoking this method.
310 * @param cannedTextResponses The text messages useable as responses.
311 */
312 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
313
314 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700315 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
316 * character. This causes the post-dial signals to stop pending user confirmation. An
317 * implementation should present this choice to the user and invoke
318 * {@link #postDialContinue(boolean)} when the user makes the choice.
319 *
320 * @param call The {@code Call} invoking this method.
321 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
322 */
323 public void onPostDialWait(Call call, String remainingPostDialSequence) {}
324
325 /**
Andrew Lee50aca232014-07-22 16:41:54 -0700326 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
Ihab Awade63fadb2014-07-09 21:52:04 -0700327 *
328 * @param call The {@code Call} invoking this method.
Andrew Lee50aca232014-07-22 16:41:54 -0700329 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700330 */
Andrew Lee50aca232014-07-22 16:41:54 -0700331 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
Ihab Awade63fadb2014-07-09 21:52:04 -0700332
333 /**
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -0700334 * Launches an activity for this connection on top of the in-call UI.
335 *
336 * @param call The {@code Call} invoking this method.
337 * @param intent The intent to use to start the activity.
338 */
339 public void onStartActivity(Call call, PendingIntent intent) {}
340
341 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700342 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
343 * up their UI for the {@code Call} in response to state transitions. Specifically,
344 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
345 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
346 * clients should wait for this method to be invoked.
347 *
348 * @param call The {@code Call} being destroyed.
349 */
350 public void onCallDestroyed(Call call) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700351
352 /**
353 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
354 * conferenced.
355 *
356 * @param call The {@code Call} being updated.
357 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
358 * conferenced.
359 */
360 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
Ihab Awade63fadb2014-07-09 21:52:04 -0700361 }
362
363 private final Phone mPhone;
364 private final String mTelecommCallId;
365 private final InCallAdapter mInCallAdapter;
Ihab Awade63fadb2014-07-09 21:52:04 -0700366 private final List<Call> mChildren = new ArrayList<>();
367 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
Jay Shrauner229e3822014-08-15 09:23:07 -0700368 private final List<Listener> mListeners = new CopyOnWriteArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700369 private final List<Call> mConferenceableCalls = new ArrayList<>();
370 private final List<Call> mUnmodifiableConferenceableCalls =
371 Collections.unmodifiableList(mConferenceableCalls);
372
373 private Call mParent = null;
374 private int mState;
Ihab Awade63fadb2014-07-09 21:52:04 -0700375 private List<String> mCannedTextResponses = null;
376 private String mRemainingPostDialSequence;
Andrew Lee50aca232014-07-22 16:41:54 -0700377 private InCallService.VideoCall mVideoCall;
Ihab Awade63fadb2014-07-09 21:52:04 -0700378 private Details mDetails;
Ihab Awade63fadb2014-07-09 21:52:04 -0700379
380 /**
381 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
382 *
383 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
384 * remaining or this {@code Call} is not in a post-dial state.
385 */
386 public String getRemainingPostDialSequence() {
387 return mRemainingPostDialSequence;
388 }
389
390 /**
391 * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700392 * @param videoState The video state in which to answer the call.
Ihab Awade63fadb2014-07-09 21:52:04 -0700393 */
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700394 public void answer(int videoState) {
395 mInCallAdapter.answerCall(mTelecommCallId, videoState);
Ihab Awade63fadb2014-07-09 21:52:04 -0700396 }
397
398 /**
399 * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
400 *
401 * @param rejectWithMessage Whether to reject with a text message.
402 * @param textMessage An optional text message with which to respond.
403 */
404 public void reject(boolean rejectWithMessage, String textMessage) {
405 mInCallAdapter.rejectCall(mTelecommCallId, rejectWithMessage, textMessage);
406 }
407
408 /**
409 * Instructs this {@code Call} to disconnect.
410 */
411 public void disconnect() {
412 mInCallAdapter.disconnectCall(mTelecommCallId);
413 }
414
415 /**
416 * Instructs this {@code Call} to go on hold.
417 */
418 public void hold() {
419 mInCallAdapter.holdCall(mTelecommCallId);
420 }
421
422 /**
423 * Instructs this {@link #STATE_HOLDING} call to release from hold.
424 */
425 public void unhold() {
426 mInCallAdapter.unholdCall(mTelecommCallId);
427 }
428
429 /**
430 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
431 *
432 * Any other currently playing DTMF tone in the specified call is immediately stopped.
433 *
434 * @param digit A character representing the DTMF digit for which to play the tone. This
435 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
436 */
437 public void playDtmfTone(char digit) {
438 mInCallAdapter.playDtmfTone(mTelecommCallId, digit);
439 }
440
441 /**
442 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
443 * currently playing.
444 *
445 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
446 * currently playing, this method will do nothing.
447 */
448 public void stopDtmfTone() {
449 mInCallAdapter.stopDtmfTone(mTelecommCallId);
450 }
451
452 /**
453 * Instructs this {@code Call} to continue playing a post-dial DTMF string.
454 *
455 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
456 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
Ihab Awade63fadb2014-07-09 21:52:04 -0700457 *
Evan Charlton10197192014-07-19 15:00:29 -0700458 * If the DTMF string contains a {@link TelecommManager#DTMF_CHARACTER_PAUSE} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -0700459 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
460 *
Evan Charlton10197192014-07-19 15:00:29 -0700461 * If the DTMF string contains a {@link TelecommManager#DTMF_CHARACTER_WAIT} symbol, this
Ihab Awade63fadb2014-07-09 21:52:04 -0700462 * {@code Call} will pause playing the tones and notify listeners via
463 * {@link Listener#onPostDialWait(Call, String)}. At this point, the in-call app
464 * should display to the user an indication of this state and an affordance to continue
465 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
466 * app should invoke the {@link #postDialContinue(boolean)} method.
467 *
468 * @param proceed Whether or not to continue with the post-dial sequence.
469 */
470 public void postDialContinue(boolean proceed) {
471 mInCallAdapter.postDialContinue(mTelecommCallId, proceed);
472 }
473
474 /**
475 * Notifies this {@code Call} that the phone account user interface element was touched.
Ihab Awade63fadb2014-07-09 21:52:04 -0700476 */
477 public void phoneAccountClicked() {
478 mInCallAdapter.phoneAccountClicked(mTelecommCallId);
479 }
480
481 /**
Evan Charlton8c8a0622014-07-20 12:31:00 -0700482 * Notifies this {@code Call} that an account has been selected and to proceed with placing
483 * an outgoing call.
Nancy Chen5da0fd52014-07-08 14:16:17 -0700484 */
Evan Charlton8c8a0622014-07-20 12:31:00 -0700485 public void phoneAccountSelected(PhoneAccountHandle accountHandle) {
486 mInCallAdapter.phoneAccountSelected(mTelecommCallId, accountHandle);
Nancy Chen5da0fd52014-07-08 14:16:17 -0700487
488 }
489
490 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700491 * Instructs this {@code Call} to enter a conference.
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700492 *
493 * @param callToConferenceWith The other call with which to conference.
Ihab Awade63fadb2014-07-09 21:52:04 -0700494 */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700495 public void conference(Call callToConferenceWith) {
496 if (callToConferenceWith != null) {
497 mInCallAdapter.conference(mTelecommCallId, callToConferenceWith.mTelecommCallId);
498 }
Ihab Awade63fadb2014-07-09 21:52:04 -0700499 }
500
501 /**
502 * Instructs this {@code Call} to split from any conference call with which it may be
503 * connected.
504 */
505 public void splitFromConference() {
506 mInCallAdapter.splitFromConference(mTelecommCallId);
507 }
508
509 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700510 * Obtains the parent of this {@code Call} in a conference, if any.
511 *
512 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
513 * child of any conference {@code Call}s.
514 */
515 public Call getParent() {
516 return mParent;
517 }
518
519 /**
520 * Obtains the children of this conference {@code Call}, if any.
521 *
522 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
523 * {@code List} otherwise.
524 */
525 public List<Call> getChildren() {
526 return mUnmodifiableChildren;
527 }
528
529 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700530 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
531 *
532 * @return The list of conferenceable {@code Call}s.
533 */
534 public List<Call> getConferenceableCalls() {
535 return mUnmodifiableConferenceableCalls;
536 }
537
538 /**
Ihab Awade63fadb2014-07-09 21:52:04 -0700539 * Obtains the state of this {@code Call}.
540 *
541 * @return A state value, chosen from the {@code STATE_*} constants.
542 */
543 public int getState() {
544 return mState;
545 }
546
547 /**
548 * Obtains a list of canned, pre-configured message responses to present to the user as
549 * ways of rejecting this {@code Call} using via a text message.
550 *
551 * @see #reject(boolean, String)
552 *
553 * @return A list of canned text message responses.
554 */
555 public List<String> getCannedTextResponses() {
556 return mCannedTextResponses;
557 }
558
559 /**
560 * Obtains an object that can be used to display video from this {@code Call}.
561 *
Andrew Lee50aca232014-07-22 16:41:54 -0700562 * @return An {@code Call.VideoCall}.
Ihab Awade63fadb2014-07-09 21:52:04 -0700563 */
Andrew Lee50aca232014-07-22 16:41:54 -0700564 public InCallService.VideoCall getVideoCall() {
565 return mVideoCall;
Ihab Awade63fadb2014-07-09 21:52:04 -0700566 }
567
568 /**
569 * Obtains an object containing call details.
570 *
571 * @return A {@link Details} object. Depending on the state of the {@code Call}, the
572 * result may be {@code null}.
573 */
574 public Details getDetails() {
575 return mDetails;
576 }
577
578 /**
579 * Adds a listener to this {@code Call}.
580 *
581 * @param listener A {@code Listener}.
582 */
583 public void addListener(Listener listener) {
584 mListeners.add(listener);
585 }
586
587 /**
588 * Removes a listener from this {@code Call}.
589 *
590 * @param listener A {@code Listener}.
591 */
592 public void removeListener(Listener listener) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700593 if (listener != null) {
594 mListeners.remove(listener);
595 }
Ihab Awade63fadb2014-07-09 21:52:04 -0700596 }
597
598 /** {@hide} */
599 Call(Phone phone, String telecommCallId, InCallAdapter inCallAdapter) {
600 mPhone = phone;
601 mTelecommCallId = telecommCallId;
602 mInCallAdapter = inCallAdapter;
603 mState = STATE_NEW;
604 }
605
606 /** {@hide} */
607 final String internalGetCallId() {
608 return mTelecommCallId;
609 }
610
611 /** {@hide} */
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700612 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
Ihab Awade63fadb2014-07-09 21:52:04 -0700613 // First, we update the internal state as far as possible before firing any updates.
Ihab Awade63fadb2014-07-09 21:52:04 -0700614 Details details = new Details(
Santos Cordon88b771d2014-07-19 13:10:40 -0700615 parcelableCall.getHandle(),
616 parcelableCall.getHandlePresentation(),
617 parcelableCall.getCallerDisplayName(),
618 parcelableCall.getCallerDisplayNamePresentation(),
619 parcelableCall.getAccountHandle(),
620 parcelableCall.getCapabilities(),
621 parcelableCall.getDisconnectCauseCode(),
622 parcelableCall.getDisconnectCauseMsg(),
623 parcelableCall.getConnectTimeMillis(),
624 parcelableCall.getGatewayInfo(),
625 parcelableCall.getVideoState(),
Nancy Chen10798dc2014-08-08 14:00:25 -0700626 parcelableCall.getStatusHints(),
627 parcelableCall.getExtras());
Ihab Awade63fadb2014-07-09 21:52:04 -0700628 boolean detailsChanged = !Objects.equals(mDetails, details);
629 if (detailsChanged) {
630 mDetails = details;
631 }
632
633 boolean cannedTextResponsesChanged = false;
Santos Cordon88b771d2014-07-19 13:10:40 -0700634 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
635 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
636 mCannedTextResponses =
637 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
Ihab Awade63fadb2014-07-09 21:52:04 -0700638 }
639
Andrew Lee50aca232014-07-22 16:41:54 -0700640 boolean videoCallChanged = !Objects.equals(mVideoCall, parcelableCall.getVideoCall());
641 if (videoCallChanged) {
642 mVideoCall = parcelableCall.getVideoCall();
Ihab Awade63fadb2014-07-09 21:52:04 -0700643 }
644
Santos Cordon88b771d2014-07-19 13:10:40 -0700645 int state = stateFromParcelableCallState(parcelableCall.getState());
Ihab Awade63fadb2014-07-09 21:52:04 -0700646 boolean stateChanged = mState != state;
647 if (stateChanged) {
648 mState = state;
649 }
650
Santos Cordon88b771d2014-07-19 13:10:40 -0700651 if (parcelableCall.getParentCallId() != null) {
652 mParent = mPhone.internalGetCallByTelecommId(parcelableCall.getParentCallId());
Ihab Awade63fadb2014-07-09 21:52:04 -0700653 }
654
655 mChildren.clear();
Santos Cordon88b771d2014-07-19 13:10:40 -0700656 if (parcelableCall.getChildCallIds() != null) {
657 for (int i = 0; i < parcelableCall.getChildCallIds().size(); i++) {
Ihab Awade63fadb2014-07-09 21:52:04 -0700658 mChildren.add(mPhone.internalGetCallByTelecommId(
Santos Cordon88b771d2014-07-19 13:10:40 -0700659 parcelableCall.getChildCallIds().get(i)));
Ihab Awade63fadb2014-07-09 21:52:04 -0700660 }
661 }
662
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700663 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
664 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
665 for (String otherId : conferenceableCallIds) {
666 if (callIdMap.containsKey(otherId)) {
667 conferenceableCalls.add(callIdMap.get(otherId));
668 }
669 }
670
671 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
672 mConferenceableCalls.clear();
673 mConferenceableCalls.addAll(conferenceableCalls);
674 fireConferenceableCallsChanged();
675 }
676
Ihab Awade63fadb2014-07-09 21:52:04 -0700677 // Now we fire updates, ensuring that any client who listens to any of these notifications
678 // gets the most up-to-date state.
679
680 if (stateChanged) {
681 fireStateChanged(mState);
682 }
683 if (detailsChanged) {
684 fireDetailsChanged(mDetails);
685 }
686 if (cannedTextResponsesChanged) {
687 fireCannedTextResponsesLoaded(mCannedTextResponses);
688 }
Andrew Lee50aca232014-07-22 16:41:54 -0700689 if (videoCallChanged) {
690 fireVideoCallChanged(mVideoCall);
Ihab Awade63fadb2014-07-09 21:52:04 -0700691 }
692
693 // If we have transitioned to DISCONNECTED, that means we need to notify clients and
694 // remove ourselves from the Phone. Note that we do this after completing all state updates
695 // so a client can cleanly transition all their UI to the state appropriate for a
696 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
697 if (mState == STATE_DISCONNECTED) {
698 fireCallDestroyed();
699 mPhone.internalRemoveCall(this);
700 }
701 }
702
703 /** {@hide} */
Ihab Awade63fadb2014-07-09 21:52:04 -0700704 final void internalSetPostDialWait(String remaining) {
705 mRemainingPostDialSequence = remaining;
706 firePostDialWait(mRemainingPostDialSequence);
707 }
708
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -0700709 /** {@hide} */
710 final void internalStartActivity(PendingIntent intent) {
711 fireStartActivity(intent);
712 }
713
Ihab Awade63fadb2014-07-09 21:52:04 -0700714 private void fireStateChanged(int newState) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700715 for (Listener listener : mListeners) {
716 listener.onStateChanged(this, newState);
Ihab Awade63fadb2014-07-09 21:52:04 -0700717 }
718 }
719
720 private void fireParentChanged(Call newParent) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700721 for (Listener listener : mListeners) {
722 listener.onParentChanged(this, newParent);
Ihab Awade63fadb2014-07-09 21:52:04 -0700723 }
724 }
725
726 private void fireChildrenChanged(List<Call> children) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700727 for (Listener listener : mListeners) {
728 listener.onChildrenChanged(this, children);
Ihab Awade63fadb2014-07-09 21:52:04 -0700729 }
730 }
731
732 private void fireDetailsChanged(Details details) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700733 for (Listener listener : mListeners) {
734 listener.onDetailsChanged(this, details);
Ihab Awade63fadb2014-07-09 21:52:04 -0700735 }
736 }
737
738 private void fireCannedTextResponsesLoaded(List<String> cannedTextResponses) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700739 for (Listener listener : mListeners) {
740 listener.onCannedTextResponsesLoaded(this, cannedTextResponses);
Ihab Awade63fadb2014-07-09 21:52:04 -0700741 }
742 }
743
Andrew Lee50aca232014-07-22 16:41:54 -0700744 private void fireVideoCallChanged(InCallService.VideoCall videoCall) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700745 for (Listener listener : mListeners) {
746 listener.onVideoCallChanged(this, videoCall);
Ihab Awade63fadb2014-07-09 21:52:04 -0700747 }
748 }
749
Ihab Awade63fadb2014-07-09 21:52:04 -0700750 private void firePostDialWait(String remainingPostDialSequence) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700751 for (Listener listener : mListeners) {
752 listener.onPostDialWait(this, remainingPostDialSequence);
Ihab Awade63fadb2014-07-09 21:52:04 -0700753 }
754 }
755
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -0700756 private void fireStartActivity(PendingIntent intent) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700757 for (Listener listener : mListeners) {
758 listener.onStartActivity(this, intent);
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -0700759 }
760 }
761
Ihab Awade63fadb2014-07-09 21:52:04 -0700762 private void fireCallDestroyed() {
Jay Shrauner229e3822014-08-15 09:23:07 -0700763 for (Listener listener : mListeners) {
764 listener.onCallDestroyed(this);
Ihab Awade63fadb2014-07-09 21:52:04 -0700765 }
766 }
767
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700768 private void fireConferenceableCallsChanged() {
Jay Shrauner229e3822014-08-15 09:23:07 -0700769 for (Listener listener : mListeners) {
770 listener.onConferenceableCallsChanged(this, mUnmodifiableConferenceableCalls);
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700771 }
772 }
773
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700774 private int stateFromParcelableCallState(int parcelableCallState) {
Santos Cordon88b771d2014-07-19 13:10:40 -0700775 switch (parcelableCallState) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700776 case CallState.NEW:
Ihab Awade63fadb2014-07-09 21:52:04 -0700777 return STATE_NEW;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700778 case CallState.CONNECTING:
Nancy Chene20930f2014-08-07 16:17:21 -0700779 return STATE_CONNECTING;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700780 case CallState.PRE_DIAL_WAIT:
Nancy Chen5da0fd52014-07-08 14:16:17 -0700781 return STATE_PRE_DIAL_WAIT;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700782 case CallState.DIALING:
Ihab Awade63fadb2014-07-09 21:52:04 -0700783 return STATE_DIALING;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700784 case CallState.RINGING:
Ihab Awade63fadb2014-07-09 21:52:04 -0700785 return STATE_RINGING;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700786 case CallState.ACTIVE:
Ihab Awade63fadb2014-07-09 21:52:04 -0700787 return STATE_ACTIVE;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700788 case CallState.ON_HOLD:
Ihab Awade63fadb2014-07-09 21:52:04 -0700789 return STATE_HOLDING;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700790 case CallState.DISCONNECTED:
Ihab Awade63fadb2014-07-09 21:52:04 -0700791 return STATE_DISCONNECTED;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700792 case CallState.ABORTED:
Ihab Awade63fadb2014-07-09 21:52:04 -0700793 return STATE_DISCONNECTED;
794 default:
Santos Cordon88b771d2014-07-19 13:10:40 -0700795 Log.wtf(this, "Unrecognized CallState %s", parcelableCallState);
Ihab Awade63fadb2014-07-09 21:52:04 -0700796 return STATE_NEW;
797 }
798 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700799}