blob: d347aadeb713b3c1f692351bfa9b68252950b337 [file] [log] [blame]
Ihab Awad542e0ea2014-05-16 10:22:16 -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 Awad542e0ea2014-05-16 10:22:16 -070020import android.net.Uri;
21import android.os.Bundle;
Ihab Awad542e0ea2014-05-16 10:22:16 -070022
Santos Cordonb6939982014-06-04 20:20:58 -070023import java.util.ArrayList;
Santos Cordonb6939982014-06-04 20:20:58 -070024import java.util.List;
Ihab Awad542e0ea2014-05-16 10:22:16 -070025import java.util.Set;
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070026import java.util.concurrent.CopyOnWriteArraySet;
Ihab Awad542e0ea2014-05-16 10:22:16 -070027
28/**
29 * Represents a connection to a remote endpoint that carries voice traffic.
30 */
31public abstract class Connection {
32
Sailesh Nepal091768c2014-06-30 15:15:23 -070033 /** @hide */
Sailesh Nepal61203862014-07-11 14:50:13 -070034 public abstract static class Listener {
Ihab Awad542e0ea2014-05-16 10:22:16 -070035 public void onStateChanged(Connection c, int state) {}
Sailesh Nepal61203862014-07-11 14:50:13 -070036 public void onHandleChanged(Connection c, Uri newHandle, int presentation) {}
37 public void onCallerDisplayNameChanged(
38 Connection c, String callerDisplayName, int presentation) {}
Tyler Gunnaa07df82014-07-17 07:50:22 -070039 public void onVideoStateChanged(Connection c, int videoState) {}
Ihab Awad542e0ea2014-05-16 10:22:16 -070040 public void onSignalChanged(Connection c, Bundle details) {}
Ihab Awad542e0ea2014-05-16 10:22:16 -070041 public void onDisconnected(Connection c, int cause, String message) {}
Sailesh Nepal091768c2014-06-30 15:15:23 -070042 public void onPostDialWait(Connection c, String remaining) {}
Ihab Awadf8358972014-05-28 16:46:42 -070043 public void onRequestingRingback(Connection c, boolean ringback) {}
Sailesh Nepal61203862014-07-11 14:50:13 -070044 public void onDestroyed(Connection c) {}
Sailesh Nepal1a7061b2014-07-09 21:03:20 -070045 public void onCallCapabilitiesChanged(Connection c, int callCapabilities) {}
Santos Cordonb6939982014-06-04 20:20:58 -070046 public void onParentConnectionChanged(Connection c, Connection parent) {}
Andrew Lee14185762014-07-25 09:41:56 -070047 public void onVideoCallProviderChanged(
48 Connection c, ConnectionService.VideoCallProvider videoCallProvider) {}
Sailesh Nepal001bbbb2014-07-15 14:40:39 -070049 public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}
50 public void onStatusHintsChanged(Connection c, StatusHints statusHints) {}
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -070051 public void onStartActivityFromInCall(Connection c, PendingIntent intent) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070052 public void onConferenceableConnectionsChanged(
53 Connection c, List<Connection> conferenceableConnections) {}
Ihab Awad542e0ea2014-05-16 10:22:16 -070054 }
55
56 public final class State {
57 private State() {}
58
Evan Charltonbf11f982014-07-20 22:06:28 -070059 public static final int INITIALIZING = 0;
60 public static final int NEW = 1;
61 public static final int RINGING = 2;
62 public static final int DIALING = 3;
63 public static final int ACTIVE = 4;
64 public static final int HOLDING = 5;
65 public static final int DISCONNECTED = 6;
66 public static final int FAILED = 7;
67 public static final int CANCELED = 8;
68
Ihab Awad542e0ea2014-05-16 10:22:16 -070069 }
70
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070071 private final Listener mConnectionDeathListener = new Listener() {
72 @Override
73 public void onDestroyed(Connection c) {
74 if (mConferenceableConnections.remove(c)) {
75 fireOnConferenceableConnectionsChanged();
76 }
77 }
78 };
79
80 private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
Santos Cordonb6939982014-06-04 20:20:58 -070081 private final List<Connection> mChildConnections = new ArrayList<>();
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070082 private final List<Connection> mConferenceableConnections = new ArrayList<>();
Santos Cordonb6939982014-06-04 20:20:58 -070083
Ihab Awad542e0ea2014-05-16 10:22:16 -070084 private int mState = State.NEW;
85 private CallAudioState mCallAudioState;
86 private Uri mHandle;
Sailesh Nepal61203862014-07-11 14:50:13 -070087 private int mHandlePresentation;
88 private String mCallerDisplayName;
89 private int mCallerDisplayNamePresentation;
Ihab Awadf8358972014-05-28 16:46:42 -070090 private boolean mRequestingRingback = false;
Sailesh Nepal1a7061b2014-07-09 21:03:20 -070091 private int mCallCapabilities;
Santos Cordonb6939982014-06-04 20:20:58 -070092 private Connection mParentConnection;
Andrew Lee14185762014-07-25 09:41:56 -070093 private ConnectionService.VideoCallProvider mVideoCallProvider;
Sailesh Nepal33aaae42014-07-07 22:49:44 -070094 private boolean mAudioModeIsVoip;
Sailesh Nepale7ef59a2014-07-08 21:48:22 -070095 private StatusHints mStatusHints;
Tyler Gunnaa07df82014-07-17 07:50:22 -070096 private int mVideoState;
Evan Charltonbf11f982014-07-20 22:06:28 -070097 private int mFailureCode;
98 private String mFailureMessage;
99 private boolean mIsCanceled;
Ihab Awad542e0ea2014-05-16 10:22:16 -0700100
101 /**
102 * Create a new Connection.
103 */
Santos Cordonf2951102014-07-20 19:06:29 -0700104 public Connection() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700105
106 /**
Sailesh Nepal61203862014-07-11 14:50:13 -0700107 * @return The handle (e.g., phone number) to which this Connection is currently communicating.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700108 */
109 public final Uri getHandle() {
110 return mHandle;
111 }
112
113 /**
Sailesh Nepal61203862014-07-11 14:50:13 -0700114 * @return The {@link CallPropertyPresentation} which controls how the handle is shown.
115 */
116 public final int getHandlePresentation() {
117 return mHandlePresentation;
118 }
119
120 /**
121 * @return The caller display name (CNAP).
122 */
123 public final String getCallerDisplayName() {
124 return mCallerDisplayName;
125 }
126
127 /**
128 * @return The {@link CallPropertyPresentation} which controls how the caller display name is
129 * shown.
130 */
131 public final int getCallerDisplayNamePresentation() {
132 return mCallerDisplayNamePresentation;
133 }
134
135 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700136 * @return The state of this Connection.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700137 */
138 public final int getState() {
139 return mState;
140 }
141
142 /**
Tyler Gunnaa07df82014-07-17 07:50:22 -0700143 * Returns the video state of the call.
Andrew Lee48332d62014-07-28 14:04:20 -0700144 * Valid values: {@link android.telecomm.VideoCallProfile.VideoState#AUDIO_ONLY},
145 * {@link android.telecomm.VideoCallProfile.VideoState#BIDIRECTIONAL},
146 * {@link android.telecomm.VideoCallProfile.VideoState#TX_ENABLED},
147 * {@link android.telecomm.VideoCallProfile.VideoState#RX_ENABLED}.
Tyler Gunnaa07df82014-07-17 07:50:22 -0700148 *
149 * @return The video state of the call.
150 */
151 public final int getVideoState() {
152 return mVideoState;
153 }
154
155 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700156 * @return The audio state of the call, describing how its audio is currently
157 * being routed by the system. This is {@code null} if this Connection
158 * does not directly know about its audio state.
159 */
160 public final CallAudioState getCallAudioState() {
161 return mCallAudioState;
162 }
163
164 /**
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700165 * Returns whether this connection is requesting that the system play a ringback tone
166 * on its behalf.
167 */
168 public final boolean isRequestingRingback() {
169 return mRequestingRingback;
170 }
171
172 /**
173 * Returns whether this connection is a conference connection (has child connections).
174 */
175 public final boolean isConferenceConnection() {
176 return !mChildConnections.isEmpty();
177 }
178
179 /**
Sailesh Nepal33aaae42014-07-07 22:49:44 -0700180 * @return True if the connection's audio mode is VOIP.
181 */
182 public final boolean getAudioModeIsVoip() {
183 return mAudioModeIsVoip;
184 }
185
186 /**
Sailesh Nepale7ef59a2014-07-08 21:48:22 -0700187 * @return The status hints for this connection.
188 */
189 public final StatusHints getStatusHints() {
190 return mStatusHints;
191 }
192
193 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700194 * Assign a listener to be notified of state changes.
195 *
196 * @param l A listener.
197 * @return This Connection.
198 *
199 * @hide
200 */
201 public final Connection addConnectionListener(Listener l) {
Santos Cordond34e5712014-08-05 18:54:03 +0000202 mListeners.add(l);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700203 return this;
204 }
205
206 /**
207 * Remove a previously assigned listener that was being notified of state changes.
208 *
209 * @param l A Listener.
210 * @return This Connection.
211 *
212 * @hide
213 */
214 public final Connection removeConnectionListener(Listener l) {
Santos Cordond34e5712014-08-05 18:54:03 +0000215 mListeners.remove(l);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700216 return this;
217 }
218
219 /**
Evan Charltonbf11f982014-07-20 22:06:28 -0700220 * @return The failure code ({@see DisconnectCause}) associated with this failed connection.
221 */
222 public final int getFailureCode() {
223 return mFailureCode;
224 }
225
226 /**
227 * @return The reason for the connection failure. This will not be displayed to the user.
228 */
229 public final String getFailureMessage() {
230 return mFailureMessage;
231 }
232
233 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700234 * Inform this Connection that the state of its audio output has been changed externally.
235 *
236 * @param state The new audio state.
Sailesh Nepal400cc482014-06-26 12:04:00 -0700237 * @hide
Ihab Awad542e0ea2014-05-16 10:22:16 -0700238 */
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700239 final void setAudioState(CallAudioState state) {
Ihab Awad60ac30b2014-05-20 22:32:12 -0700240 Log.d(this, "setAudioState %s", state);
Santos Cordond34e5712014-08-05 18:54:03 +0000241 mCallAudioState = state;
242 onSetAudioState(state);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700243 }
244
245 /**
246 * @param state An integer value from {@link State}.
247 * @return A string representation of the value.
248 */
249 public static String stateToString(int state) {
250 switch (state) {
Sailesh Nepalb2d41f42014-07-28 20:33:07 -0700251 case State.INITIALIZING:
252 return "INITIALIZING";
Ihab Awad542e0ea2014-05-16 10:22:16 -0700253 case State.NEW:
254 return "NEW";
255 case State.RINGING:
256 return "RINGING";
257 case State.DIALING:
258 return "DIALING";
259 case State.ACTIVE:
260 return "ACTIVE";
261 case State.HOLDING:
262 return "HOLDING";
263 case State.DISCONNECTED:
264 return "DISCONNECTED";
Evan Charltonbf11f982014-07-20 22:06:28 -0700265 case State.FAILED:
266 return "FAILED";
267 case State.CANCELED:
268 return "CANCELED";
Ihab Awad542e0ea2014-05-16 10:22:16 -0700269 default:
Ihab Awad60ac30b2014-05-20 22:32:12 -0700270 Log.wtf(Connection.class, "Unknown state %d", state);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700271 return "UNKNOWN";
272 }
273 }
274
275 /**
Sailesh Nepal400cc482014-06-26 12:04:00 -0700276 * TODO(santoscordon): Needs documentation.
277 */
278 public final void setParentConnection(Connection parentConnection) {
Santos Cordonb6939982014-06-04 20:20:58 -0700279 Log.d(this, "parenting %s to %s", this, parentConnection);
Santos Cordond34e5712014-08-05 18:54:03 +0000280 if (mParentConnection != parentConnection) {
281 if (mParentConnection != null) {
282 mParentConnection.removeChild(this);
283 }
284 mParentConnection = parentConnection;
285 if (mParentConnection != null) {
286 mParentConnection.addChild(this);
287 // do something if the child connections goes down to ZERO.
288 }
289 for (Listener l : mListeners) {
290 l.onParentConnectionChanged(this, mParentConnection);
291 }
292 }
Santos Cordonb6939982014-06-04 20:20:58 -0700293 }
294
Sailesh Nepal400cc482014-06-26 12:04:00 -0700295 public final Connection getParentConnection() {
Santos Cordonb6939982014-06-04 20:20:58 -0700296 return mParentConnection;
297 }
298
Sailesh Nepal400cc482014-06-26 12:04:00 -0700299 public final List<Connection> getChildConnections() {
Santos Cordonb6939982014-06-04 20:20:58 -0700300 return mChildConnections;
301 }
302
303 /**
Sailesh Nepal1a7061b2014-07-09 21:03:20 -0700304 * Returns the connection's {@link CallCapabilities}
Ihab Awad52a28f62014-06-18 10:26:34 -0700305 */
Sailesh Nepal1a7061b2014-07-09 21:03:20 -0700306 public final int getCallCapabilities() {
307 return mCallCapabilities;
Ihab Awad52a28f62014-06-18 10:26:34 -0700308 }
309
310 /**
Sailesh Nepal61203862014-07-11 14:50:13 -0700311 * Sets the value of the {@link #getHandle()} property.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700312 *
313 * @param handle The new handle.
Sailesh Nepal61203862014-07-11 14:50:13 -0700314 * @param presentation The {@link CallPropertyPresentation} which controls how the handle is
315 * shown.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700316 */
Sailesh Nepal61203862014-07-11 14:50:13 -0700317 public final void setHandle(Uri handle, int presentation) {
Ihab Awad60ac30b2014-05-20 22:32:12 -0700318 Log.d(this, "setHandle %s", handle);
Santos Cordond34e5712014-08-05 18:54:03 +0000319 mHandle = handle;
320 mHandlePresentation = presentation;
321 for (Listener l : mListeners) {
322 l.onHandleChanged(this, handle, presentation);
323 }
Ihab Awad542e0ea2014-05-16 10:22:16 -0700324 }
325
326 /**
Sailesh Nepal61203862014-07-11 14:50:13 -0700327 * Sets the caller display name (CNAP).
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700328 *
Sailesh Nepal61203862014-07-11 14:50:13 -0700329 * @param callerDisplayName The new display name.
330 * @param presentation The {@link CallPropertyPresentation} which controls how the name is
331 * shown.
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700332 */
Sailesh Nepal61203862014-07-11 14:50:13 -0700333 public final void setCallerDisplayName(String callerDisplayName, int presentation) {
334 Log.d(this, "setCallerDisplayName %s", callerDisplayName);
Santos Cordond34e5712014-08-05 18:54:03 +0000335 mCallerDisplayName = callerDisplayName;
336 mCallerDisplayNamePresentation = presentation;
337 for (Listener l : mListeners) {
338 l.onCallerDisplayNameChanged(this, callerDisplayName, presentation);
339 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700340 }
341
342 /**
Evan Charltonbf11f982014-07-20 22:06:28 -0700343 * Cancel the {@link Connection}. Once this is called, the {@link Connection} will not be used,
344 * and no subsequent {@link Connection}s will be attempted.
345 */
346 public final void setCanceled() {
347 Log.d(this, "setCanceled");
Santos Cordond34e5712014-08-05 18:54:03 +0000348 setState(State.CANCELED);
Evan Charltonbf11f982014-07-20 22:06:28 -0700349 }
350
351 /**
352 * Move the {@link Connection} to the {@link State#FAILED} state, with the given code
353 * ({@see DisconnectCause}) and message. This message is not shown to the user, but is useful
354 * for logging and debugging purposes.
355 * <p>
356 * After calling this, the {@link Connection} will not be used.
357 *
358 * @param code The {@link android.telephony.DisconnectCause} indicating why the connection
359 * failed.
360 * @param message A message explaining why the {@link Connection} failed.
361 */
362 public final void setFailed(int code, String message) {
363 Log.d(this, "setFailed (%d: %s)", code, message);
Santos Cordond34e5712014-08-05 18:54:03 +0000364 mFailureCode = code;
365 mFailureMessage = message;
366 setState(State.FAILED);
Evan Charltonbf11f982014-07-20 22:06:28 -0700367 }
368
369 /**
Tyler Gunnaa07df82014-07-17 07:50:22 -0700370 * Set the video state for the connection.
Andrew Lee48332d62014-07-28 14:04:20 -0700371 * Valid values: {@link android.telecomm.VideoCallProfile.VideoState#AUDIO_ONLY},
372 * {@link android.telecomm.VideoCallProfile.VideoState#BIDIRECTIONAL},
373 * {@link android.telecomm.VideoCallProfile.VideoState#TX_ENABLED},
374 * {@link android.telecomm.VideoCallProfile.VideoState#RX_ENABLED}.
Tyler Gunnaa07df82014-07-17 07:50:22 -0700375 *
376 * @param videoState The new video state.
377 */
378 public final void setVideoState(int videoState) {
379 Log.d(this, "setVideoState %d", videoState);
Santos Cordond34e5712014-08-05 18:54:03 +0000380 mVideoState = videoState;
381 for (Listener l : mListeners) {
382 l.onVideoStateChanged(this, mVideoState);
383 }
Tyler Gunnaa07df82014-07-17 07:50:22 -0700384 }
385
386 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700387 * Sets state to active (e.g., an ongoing call where two or more parties can actively
388 * communicate).
389 */
Sailesh Nepal400cc482014-06-26 12:04:00 -0700390 public final void setActive() {
Santos Cordond34e5712014-08-05 18:54:03 +0000391 setRequestingRingback(false);
392 setState(State.ACTIVE);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700393 }
394
395 /**
396 * Sets state to ringing (e.g., an inbound ringing call).
397 */
Sailesh Nepal400cc482014-06-26 12:04:00 -0700398 public final void setRinging() {
Santos Cordond34e5712014-08-05 18:54:03 +0000399 setState(State.RINGING);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700400 }
401
402 /**
Evan Charltonbf11f982014-07-20 22:06:28 -0700403 * Sets state to initializing (this Connection is not yet ready to be used).
404 */
405 public final void setInitializing() {
Santos Cordond34e5712014-08-05 18:54:03 +0000406 setState(State.INITIALIZING);
Evan Charltonbf11f982014-07-20 22:06:28 -0700407 }
408
409 /**
410 * Sets state to initialized (the Connection has been set up and is now ready to be used).
411 */
412 public final void setInitialized() {
413 setState(State.NEW);
414 }
415
416 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700417 * Sets state to dialing (e.g., dialing an outbound call).
418 */
Sailesh Nepal400cc482014-06-26 12:04:00 -0700419 public final void setDialing() {
Santos Cordond34e5712014-08-05 18:54:03 +0000420 setState(State.DIALING);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700421 }
422
423 /**
424 * Sets state to be on hold.
425 */
Sailesh Nepal400cc482014-06-26 12:04:00 -0700426 public final void setOnHold() {
Santos Cordond34e5712014-08-05 18:54:03 +0000427 setState(State.HOLDING);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700428 }
429
430 /**
Andrew Lee50aca232014-07-22 16:41:54 -0700431 * Sets the video call provider.
432 * @param videoCallProvider The video call provider.
Andrew Lee5ffbe8b2014-06-20 16:29:33 -0700433 */
Andrew Lee14185762014-07-25 09:41:56 -0700434 public final void setVideoCallProvider(ConnectionService.VideoCallProvider videoCallProvider) {
Santos Cordond34e5712014-08-05 18:54:03 +0000435 mVideoCallProvider = videoCallProvider;
436 for (Listener l : mListeners) {
437 l.onVideoCallProviderChanged(this, videoCallProvider);
438 }
Andrew Lee5ffbe8b2014-06-20 16:29:33 -0700439 }
440
Andrew Lee14185762014-07-25 09:41:56 -0700441 public final ConnectionService.VideoCallProvider getVideoCallProvider() {
Andrew Lee50aca232014-07-22 16:41:54 -0700442 return mVideoCallProvider;
Andrew Leea27a1932014-07-09 17:07:13 -0700443 }
444
Andrew Lee5ffbe8b2014-06-20 16:29:33 -0700445 /**
Sailesh Nepal091768c2014-06-30 15:15:23 -0700446 * Sets state to disconnected.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700447 *
448 * @param cause The reason for the disconnection, any of
449 * {@link android.telephony.DisconnectCause}.
450 * @param message Optional call-service-provided message about the disconnect.
451 */
Sailesh Nepal400cc482014-06-26 12:04:00 -0700452 public final void setDisconnected(int cause, String message) {
Santos Cordond34e5712014-08-05 18:54:03 +0000453 setState(State.DISCONNECTED);
454 Log.d(this, "Disconnected with cause %d message %s", cause, message);
455 for (Listener l : mListeners) {
456 l.onDisconnected(this, cause, message);
457 }
Ihab Awad542e0ea2014-05-16 10:22:16 -0700458 }
459
460 /**
Sailesh Nepal091768c2014-06-30 15:15:23 -0700461 * TODO(santoscordon): Needs documentation.
462 */
463 public final void setPostDialWait(String remaining) {
Santos Cordond34e5712014-08-05 18:54:03 +0000464 for (Listener l : mListeners) {
465 l.onPostDialWait(this, remaining);
466 }
Sailesh Nepal091768c2014-06-30 15:15:23 -0700467 }
468
469 /**
Ihab Awadf8358972014-05-28 16:46:42 -0700470 * Requests that the framework play a ringback tone. This is to be invoked by implementations
471 * that do not play a ringback tone themselves in the call's audio stream.
472 *
473 * @param ringback Whether the ringback tone is to be played.
474 */
Sailesh Nepal400cc482014-06-26 12:04:00 -0700475 public final void setRequestingRingback(boolean ringback) {
Santos Cordond34e5712014-08-05 18:54:03 +0000476 if (mRequestingRingback != ringback) {
477 mRequestingRingback = ringback;
478 for (Listener l : mListeners) {
479 l.onRequestingRingback(this, ringback);
480 }
481 }
Ihab Awadf8358972014-05-28 16:46:42 -0700482 }
483
484 /**
Sailesh Nepal1a7061b2014-07-09 21:03:20 -0700485 * Sets the connection's {@link CallCapabilities}.
486 *
487 * @param callCapabilities The new call capabilities.
Santos Cordonb6939982014-06-04 20:20:58 -0700488 */
Sailesh Nepal1a7061b2014-07-09 21:03:20 -0700489 public final void setCallCapabilities(int callCapabilities) {
Santos Cordond34e5712014-08-05 18:54:03 +0000490 if (mCallCapabilities != callCapabilities) {
491 mCallCapabilities = callCapabilities;
492 for (Listener l : mListeners) {
493 l.onCallCapabilitiesChanged(this, mCallCapabilities);
494 }
495 }
Santos Cordonb6939982014-06-04 20:20:58 -0700496 }
497
498 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700499 * Tears down the Connection object.
Santos Cordonb6939982014-06-04 20:20:58 -0700500 */
Evan Charlton36a71342014-07-19 16:31:02 -0700501 public final void destroy() {
Santos Cordond34e5712014-08-05 18:54:03 +0000502 // It is possible that onDestroy() will trigger the listener to remove itself which will
503 // result in a concurrent modification exception. To counteract this we make a copy of the
504 // listeners and iterate on that.
505 for (Listener l : new ArrayList<>(mListeners)) {
506 if (mListeners.contains(l)) {
507 l.onDestroyed(this);
508 }
509 }
Santos Cordonb6939982014-06-04 20:20:58 -0700510 }
511
512 /**
Sailesh Nepal61203862014-07-11 14:50:13 -0700513 * Sets the current signal levels for the underlying data transport.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700514 *
515 * @param details A {@link android.os.Bundle} containing details of the current level.
516 */
Sailesh Nepal400cc482014-06-26 12:04:00 -0700517 public final void setSignal(Bundle details) {
Santos Cordond34e5712014-08-05 18:54:03 +0000518 for (Listener l : mListeners) {
519 l.onSignalChanged(this, details);
520 }
Ihab Awad542e0ea2014-05-16 10:22:16 -0700521 }
522
523 /**
Sailesh Nepal33aaae42014-07-07 22:49:44 -0700524 * Requests that the framework use VOIP audio mode for this connection.
525 *
526 * @param isVoip True if the audio mode is VOIP.
527 */
528 public final void setAudioModeIsVoip(boolean isVoip) {
Santos Cordond34e5712014-08-05 18:54:03 +0000529 mAudioModeIsVoip = isVoip;
530 for (Listener l : mListeners) {
531 l.onAudioModeIsVoipChanged(this, isVoip);
532 }
Sailesh Nepal33aaae42014-07-07 22:49:44 -0700533 }
534
535 /**
Sailesh Nepale7ef59a2014-07-08 21:48:22 -0700536 * Sets the label and icon status to display in the in-call UI.
537 *
538 * @param statusHints The status label and icon to set.
539 */
540 public final void setStatusHints(StatusHints statusHints) {
Santos Cordond34e5712014-08-05 18:54:03 +0000541 mStatusHints = statusHints;
542 for (Listener l : mListeners) {
543 l.onStatusHintsChanged(this, statusHints);
544 }
Sailesh Nepale7ef59a2014-07-08 21:48:22 -0700545 }
546
547 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700548 * Sets the connections with which this connection can be conferenced.
549 *
550 * @param conferenceableConnections The set of connections this connection can conference with.
551 */
552 public final void setConferenceableConnections(List<Connection> conferenceableConnections) {
553 clearConferenceableList();
554 for (Connection c : conferenceableConnections) {
555 // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a
556 // small amount of items here.
557 if (!mConferenceableConnections.contains(c)) {
558 c.addConnectionListener(mConnectionDeathListener);
559 mConferenceableConnections.add(c);
560 }
561 }
562 fireOnConferenceableConnectionsChanged();
563 }
564
565 /**
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -0700566 * Launches an activity for this connection on top of the in-call UI.
567 *
568 * @param intent The intent to use to start the activity.
569 */
570 public final void startActivityFromInCall(PendingIntent intent) {
571 if (!intent.isActivity()) {
572 throw new IllegalArgumentException("Activity intent required.");
573 }
Santos Cordond34e5712014-08-05 18:54:03 +0000574 for (Listener l : mListeners) {
575 l.onStartActivityFromInCall(this, intent);
576 }
Sailesh Nepal2ab88cc2014-07-18 14:49:18 -0700577 }
578
579 /**
Sailesh Nepal61203862014-07-11 14:50:13 -0700580 * Notifies this Connection that the {@link #getCallAudioState()} property has a new value.
Sailesh Nepal400cc482014-06-26 12:04:00 -0700581 *
582 * @param state The new call audio state.
583 */
Santos Cordonf2951102014-07-20 19:06:29 -0700584 public void onSetAudioState(CallAudioState state) {}
Sailesh Nepal400cc482014-06-26 12:04:00 -0700585
586 /**
Evan Charltonbf11f982014-07-20 22:06:28 -0700587 * Notifies this Connection of an internal state change. This method is called after the
588 * state is changed.
Ihab Awadf8358972014-05-28 16:46:42 -0700589 *
590 * @param state The new state, a {@link Connection.State} member.
591 */
Santos Cordonf2951102014-07-20 19:06:29 -0700592 public void onSetState(int state) {}
Ihab Awadf8358972014-05-28 16:46:42 -0700593
594 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700595 * Notifies this Connection of a request to play a DTMF tone.
596 *
597 * @param c A DTMF character.
598 */
Santos Cordonf2951102014-07-20 19:06:29 -0700599 public void onPlayDtmfTone(char c) {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700600
601 /**
602 * Notifies this Connection of a request to stop any currently playing DTMF tones.
603 */
Santos Cordonf2951102014-07-20 19:06:29 -0700604 public void onStopDtmfTone() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700605
606 /**
607 * Notifies this Connection of a request to disconnect.
608 */
Santos Cordonf2951102014-07-20 19:06:29 -0700609 public void onDisconnect() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700610
611 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700612 * Notifies this Connection of a request to separate from its parent conference.
Santos Cordonb6939982014-06-04 20:20:58 -0700613 */
Santos Cordonf2951102014-07-20 19:06:29 -0700614 public void onSeparate() {}
Santos Cordonb6939982014-06-04 20:20:58 -0700615
616 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700617 * Notifies this Connection of a request to abort.
618 */
Santos Cordonf2951102014-07-20 19:06:29 -0700619 public void onAbort() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700620
621 /**
622 * Notifies this Connection of a request to hold.
623 */
Santos Cordonf2951102014-07-20 19:06:29 -0700624 public void onHold() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700625
626 /**
627 * Notifies this Connection of a request to exit a hold state.
628 */
Santos Cordonf2951102014-07-20 19:06:29 -0700629 public void onUnhold() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700630
631 /**
Santos Cordond34e5712014-08-05 18:54:03 +0000632 * Notifies this Connection, which is in {@link State#RINGING}, of
633 * a request to accept.
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700634 *
635 * @param videoState The video state in which to answer the call.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700636 */
Santos Cordonf2951102014-07-20 19:06:29 -0700637 public void onAnswer(int videoState) {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700638
639 /**
Santos Cordond34e5712014-08-05 18:54:03 +0000640 * Notifies this Connection, which is in {@link State#RINGING}, of
641 * a request to reject.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700642 */
Santos Cordonf2951102014-07-20 19:06:29 -0700643 public void onReject() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700644
Evan Charlton6dea4ac2014-06-03 14:07:13 -0700645 /**
646 * Notifies this Connection whether the user wishes to proceed with the post-dial DTMF codes.
647 */
Santos Cordonf2951102014-07-20 19:06:29 -0700648 public void onPostDialContinue(boolean proceed) {}
Evan Charlton6dea4ac2014-06-03 14:07:13 -0700649
Santos Cordonb6939982014-06-04 20:20:58 -0700650 /**
Sailesh Nepal61203862014-07-11 14:50:13 -0700651 * Swap this call with a background call. This is used for calls that don't support hold,
652 * e.g. CDMA.
653 */
Santos Cordonf2951102014-07-20 19:06:29 -0700654 public void onSwapWithBackgroundCall() {}
Sailesh Nepal61203862014-07-11 14:50:13 -0700655
656 /**
Santos Cordonb6939982014-06-04 20:20:58 -0700657 * TODO(santoscordon): Needs documentation.
658 */
Santos Cordonf2951102014-07-20 19:06:29 -0700659 public void onChildrenChanged(List<Connection> children) {}
Santos Cordonb6939982014-06-04 20:20:58 -0700660
Sailesh Nepal2bed9562014-07-02 21:26:12 -0700661 /**
662 * Called when the phone account UI was clicked.
663 */
Santos Cordonf2951102014-07-20 19:06:29 -0700664 public void onPhoneAccountClicked() {}
Sailesh Nepal2bed9562014-07-02 21:26:12 -0700665
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700666 /**
667 * Merge this connection and the specified connection into a conference call. Once the
668 * connections are merged, the calls should be added to the an existing or new
669 * {@code Conference} instance. For new {@code Conference} instances, use
670 * {@code ConnectionService#addConference}.
671 *
672 * @param otherConnection The connection with which this connection should be conferenced.
673 */
674 public void onConferenceWith(Connection otherConnection) {}
675
Santos Cordonb6939982014-06-04 20:20:58 -0700676 private void addChild(Connection connection) {
677 Log.d(this, "adding child %s", connection);
678 mChildConnections.add(connection);
679 onChildrenChanged(mChildConnections);
680 }
681
682 private void removeChild(Connection connection) {
683 Log.d(this, "removing child %s", connection);
684 mChildConnections.remove(connection);
685 onChildrenChanged(mChildConnections);
686 }
687
Ihab Awad542e0ea2014-05-16 10:22:16 -0700688 private void setState(int state) {
Evan Charltonbf11f982014-07-20 22:06:28 -0700689 if (mState == State.FAILED || mState == State.CANCELED) {
690 Log.d(this, "Connection already %s; cannot transition out of this state.",
691 stateToString(mState));
692 return;
Sailesh Nepal400cc482014-06-26 12:04:00 -0700693 }
Evan Charltonbf11f982014-07-20 22:06:28 -0700694 if (mState != state) {
695 Log.d(this, "setState: %s", stateToString(state));
696 mState = state;
697 for (Listener l : mListeners) {
698 l.onStateChanged(this, state);
699 }
700 onSetState(state);
701 }
702 }
703
704 /**
705 * Return a {@link Connection} which represents a failed connection attempt. The returned
706 * {@link Connection} will have {@link #getFailureCode()}, {@link #getFailureMessage()}, and
707 * {@link #getState()} set appropriately, but the {@link Connection} itself should not be used
708 * for anything.
709 *
710 * @param code The failure code ({@see DisconnectCause}).
711 * @param message A reason for why the connection failed (not intended to be shown to the user).
712 * @return A {@link Connection} which indicates failure.
713 */
714 public static Connection getFailedConnection(final int code, final String message) {
715 return new Connection() {{
716 setFailed(code, message);
717 }};
718 }
719
720 private static final Connection CANCELED_CONNECTION = new Connection() {{
721 setCanceled();
722 }};
723
724 /**
725 * Return a {@link Connection} which represents a canceled a connection attempt. The returned
726 * {@link Connection} will have state {@link State#CANCELED}, and cannot be moved out of that
727 * state. This connection should not be used for anything, and no other {@link Connection}s
728 * should be attempted.
729 *
730 * @return A {@link Connection} which indicates that the underlying call should be canceled.
731 */
732 public static Connection getCanceledConnection() {
733 return CANCELED_CONNECTION;
Ihab Awad542e0ea2014-05-16 10:22:16 -0700734 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700735
736 private final void fireOnConferenceableConnectionsChanged() {
737 for (Listener l : mListeners) {
738 l.onConferenceableConnectionsChanged(this, mConferenceableConnections);
739 }
740 }
741
742 private final void clearConferenceableList() {
743 for (Connection c : mConferenceableConnections) {
744 c.removeConnectionListener(mConnectionDeathListener);
745 }
746 mConferenceableConnections.clear();
747 }
Ihab Awad542e0ea2014-05-16 10:22:16 -0700748}