blob: 7979e44a0d4f5fe664941a1815f2b1a4ea7833bc [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
Tyler Gunnef9f6f92014-09-12 22:16:17 -070017package android.telecom;
Ihab Awad542e0ea2014-05-16 10:22:16 -070018
Tyler Gunnef9f6f92014-09-12 22:16:17 -070019import com.android.internal.telecom.IVideoCallback;
20import com.android.internal.telecom.IVideoProvider;
Ihab Awadb19a0bc2014-08-07 19:46:01 -070021
Ihab Awad542e0ea2014-05-16 10:22:16 -070022import android.net.Uri;
Ihab Awadb19a0bc2014-08-07 19:46:01 -070023import android.os.Handler;
24import android.os.IBinder;
25import android.os.Message;
26import android.os.RemoteException;
Ihab Awadb19a0bc2014-08-07 19:46:01 -070027import android.view.Surface;
Ihab Awad542e0ea2014-05-16 10:22:16 -070028
Santos Cordonb6939982014-06-04 20:20:58 -070029import java.util.ArrayList;
Ihab Awadb19a0bc2014-08-07 19:46:01 -070030import java.util.Collections;
Santos Cordonb6939982014-06-04 20:20:58 -070031import java.util.List;
Ihab Awad542e0ea2014-05-16 10:22:16 -070032import java.util.Set;
Jay Shrauner229e3822014-08-15 09:23:07 -070033import java.util.concurrent.ConcurrentHashMap;
Ihab Awad542e0ea2014-05-16 10:22:16 -070034
35/**
36 * Represents a connection to a remote endpoint that carries voice traffic.
Ihab Awad6107bab2014-08-18 09:23:25 -070037 * <p>
38 * Implementations create a custom subclass of {@code Connection} and return it to the framework
39 * as the return value of
40 * {@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}
41 * or
42 * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
43 * Implementations are then responsible for updating the state of the {@code Connection}, and
44 * must call {@link #destroy()} to signal to the framework that the {@code Connection} is no
45 * longer used and associated resources may be recovered.
Ihab Awad542e0ea2014-05-16 10:22:16 -070046 */
47public abstract class Connection {
48
Ihab Awadb19a0bc2014-08-07 19:46:01 -070049 public static final int STATE_INITIALIZING = 0;
50
51 public static final int STATE_NEW = 1;
52
53 public static final int STATE_RINGING = 2;
54
55 public static final int STATE_DIALING = 3;
56
57 public static final int STATE_ACTIVE = 4;
58
59 public static final int STATE_HOLDING = 5;
60
61 public static final int STATE_DISCONNECTED = 6;
62
Ihab Awadb19a0bc2014-08-07 19:46:01 -070063 // Flag controlling whether PII is emitted into the logs
64 private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
65
Sailesh Nepal091768c2014-06-30 15:15:23 -070066 /** @hide */
Sailesh Nepal61203862014-07-11 14:50:13 -070067 public abstract static class Listener {
Ihab Awad542e0ea2014-05-16 10:22:16 -070068 public void onStateChanged(Connection c, int state) {}
Andrew Lee100e2932014-09-08 15:34:24 -070069 public void onAddressChanged(Connection c, Uri newAddress, int presentation) {}
Sailesh Nepal61203862014-07-11 14:50:13 -070070 public void onCallerDisplayNameChanged(
71 Connection c, String callerDisplayName, int presentation) {}
Tyler Gunnaa07df82014-07-17 07:50:22 -070072 public void onVideoStateChanged(Connection c, int videoState) {}
Andrew Lee7f3d41f2014-09-11 17:33:16 -070073 public void onDisconnected(Connection c, DisconnectCause disconnectCause) {}
Sailesh Nepal091768c2014-06-30 15:15:23 -070074 public void onPostDialWait(Connection c, String remaining) {}
Andrew Lee100e2932014-09-08 15:34:24 -070075 public void onRingbackRequested(Connection c, boolean ringback) {}
Sailesh Nepal61203862014-07-11 14:50:13 -070076 public void onDestroyed(Connection c) {}
Sailesh Nepal1a7061b2014-07-09 21:03:20 -070077 public void onCallCapabilitiesChanged(Connection c, int callCapabilities) {}
Ihab Awadb19a0bc2014-08-07 19:46:01 -070078 public void onVideoProviderChanged(
79 Connection c, VideoProvider videoProvider) {}
Sailesh Nepal001bbbb2014-07-15 14:40:39 -070080 public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}
81 public void onStatusHintsChanged(Connection c, StatusHints statusHints) {}
Santos Cordon7c7bc7f2014-07-28 18:15:48 -070082 public void onConferenceableConnectionsChanged(
83 Connection c, List<Connection> conferenceableConnections) {}
Santos Cordon823fd3c2014-08-07 18:35:18 -070084 public void onConferenceChanged(Connection c, Conference conference) {}
Ihab Awad542e0ea2014-05-16 10:22:16 -070085 }
86
Tyler Gunn27d1e252014-08-21 16:38:40 -070087 /** @hide */
Ihab Awadb19a0bc2014-08-07 19:46:01 -070088 public static abstract class VideoProvider {
Ihab Awad542e0ea2014-05-16 10:22:16 -070089
Ihab Awadb19a0bc2014-08-07 19:46:01 -070090 /**
91 * Video is not being received (no protocol pause was issued).
92 */
93 public static final int SESSION_EVENT_RX_PAUSE = 1;
Evan Charltonbf11f982014-07-20 22:06:28 -070094
Ihab Awadb19a0bc2014-08-07 19:46:01 -070095 /**
96 * Video reception has resumed after a SESSION_EVENT_RX_PAUSE.
97 */
98 public static final int SESSION_EVENT_RX_RESUME = 2;
99
100 /**
101 * Video transmission has begun. This occurs after a negotiated start of video transmission
102 * when the underlying protocol has actually begun transmitting video to the remote party.
103 */
104 public static final int SESSION_EVENT_TX_START = 3;
105
106 /**
107 * Video transmission has stopped. This occurs after a negotiated stop of video transmission
108 * when the underlying protocol has actually stopped transmitting video to the remote party.
109 */
110 public static final int SESSION_EVENT_TX_STOP = 4;
111
112 /**
113 * A camera failure has occurred for the selected camera. The In-Call UI can use this as a
114 * cue to inform the user the camera is not available.
115 */
116 public static final int SESSION_EVENT_CAMERA_FAILURE = 5;
117
118 /**
119 * Issued after {@code SESSION_EVENT_CAMERA_FAILURE} when the camera is once again ready for
120 * operation. The In-Call UI can use this as a cue to inform the user that the camera has
121 * become available again.
122 */
123 public static final int SESSION_EVENT_CAMERA_READY = 6;
124
125 /**
126 * Session modify request was successful.
127 */
128 public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1;
129
130 /**
131 * Session modify request failed.
132 */
133 public static final int SESSION_MODIFY_REQUEST_FAIL = 2;
134
135 /**
136 * Session modify request ignored due to invalid parameters.
137 */
138 public static final int SESSION_MODIFY_REQUEST_INVALID = 3;
139
Ihab Awada64627c2014-08-20 09:36:40 -0700140 private static final int MSG_SET_VIDEO_CALLBACK = 1;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700141 private static final int MSG_SET_CAMERA = 2;
142 private static final int MSG_SET_PREVIEW_SURFACE = 3;
143 private static final int MSG_SET_DISPLAY_SURFACE = 4;
144 private static final int MSG_SET_DEVICE_ORIENTATION = 5;
145 private static final int MSG_SET_ZOOM = 6;
146 private static final int MSG_SEND_SESSION_MODIFY_REQUEST = 7;
147 private static final int MSG_SEND_SESSION_MODIFY_RESPONSE = 8;
148 private static final int MSG_REQUEST_CAMERA_CAPABILITIES = 9;
149 private static final int MSG_REQUEST_CALL_DATA_USAGE = 10;
150 private static final int MSG_SET_PAUSE_IMAGE = 11;
151
152 private final VideoProvider.VideoProviderHandler
153 mMessageHandler = new VideoProvider.VideoProviderHandler();
154 private final VideoProvider.VideoProviderBinder mBinder;
Ihab Awada64627c2014-08-20 09:36:40 -0700155 private IVideoCallback mVideoCallback;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700156
157 /**
158 * Default handler used to consolidate binder method calls onto a single thread.
159 */
160 private final class VideoProviderHandler extends Handler {
161 @Override
162 public void handleMessage(Message msg) {
163 switch (msg.what) {
Ihab Awada64627c2014-08-20 09:36:40 -0700164 case MSG_SET_VIDEO_CALLBACK:
165 mVideoCallback = IVideoCallback.Stub.asInterface((IBinder) msg.obj);
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700166 break;
167 case MSG_SET_CAMERA:
168 onSetCamera((String) msg.obj);
169 break;
170 case MSG_SET_PREVIEW_SURFACE:
171 onSetPreviewSurface((Surface) msg.obj);
172 break;
173 case MSG_SET_DISPLAY_SURFACE:
174 onSetDisplaySurface((Surface) msg.obj);
175 break;
176 case MSG_SET_DEVICE_ORIENTATION:
177 onSetDeviceOrientation(msg.arg1);
178 break;
179 case MSG_SET_ZOOM:
180 onSetZoom((Float) msg.obj);
181 break;
182 case MSG_SEND_SESSION_MODIFY_REQUEST:
183 onSendSessionModifyRequest((VideoProfile) msg.obj);
184 break;
185 case MSG_SEND_SESSION_MODIFY_RESPONSE:
186 onSendSessionModifyResponse((VideoProfile) msg.obj);
187 break;
188 case MSG_REQUEST_CAMERA_CAPABILITIES:
189 onRequestCameraCapabilities();
190 break;
191 case MSG_REQUEST_CALL_DATA_USAGE:
192 onRequestCallDataUsage();
193 break;
194 case MSG_SET_PAUSE_IMAGE:
195 onSetPauseImage((String) msg.obj);
196 break;
197 default:
198 break;
199 }
200 }
201 }
202
203 /**
204 * IVideoProvider stub implementation.
205 */
206 private final class VideoProviderBinder extends IVideoProvider.Stub {
Ihab Awada64627c2014-08-20 09:36:40 -0700207 public void setVideoCallback(IBinder videoCallbackBinder) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700208 mMessageHandler.obtainMessage(
Ihab Awada64627c2014-08-20 09:36:40 -0700209 MSG_SET_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget();
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700210 }
211
212 public void setCamera(String cameraId) {
213 mMessageHandler.obtainMessage(MSG_SET_CAMERA, cameraId).sendToTarget();
214 }
215
216 public void setPreviewSurface(Surface surface) {
217 mMessageHandler.obtainMessage(MSG_SET_PREVIEW_SURFACE, surface).sendToTarget();
218 }
219
220 public void setDisplaySurface(Surface surface) {
221 mMessageHandler.obtainMessage(MSG_SET_DISPLAY_SURFACE, surface).sendToTarget();
222 }
223
224 public void setDeviceOrientation(int rotation) {
225 mMessageHandler.obtainMessage(MSG_SET_DEVICE_ORIENTATION, rotation).sendToTarget();
226 }
227
228 public void setZoom(float value) {
229 mMessageHandler.obtainMessage(MSG_SET_ZOOM, value).sendToTarget();
230 }
231
232 public void sendSessionModifyRequest(VideoProfile requestProfile) {
233 mMessageHandler.obtainMessage(
234 MSG_SEND_SESSION_MODIFY_REQUEST, requestProfile).sendToTarget();
235 }
236
237 public void sendSessionModifyResponse(VideoProfile responseProfile) {
238 mMessageHandler.obtainMessage(
239 MSG_SEND_SESSION_MODIFY_RESPONSE, responseProfile).sendToTarget();
240 }
241
242 public void requestCameraCapabilities() {
243 mMessageHandler.obtainMessage(MSG_REQUEST_CAMERA_CAPABILITIES).sendToTarget();
244 }
245
246 public void requestCallDataUsage() {
247 mMessageHandler.obtainMessage(MSG_REQUEST_CALL_DATA_USAGE).sendToTarget();
248 }
249
250 public void setPauseImage(String uri) {
251 mMessageHandler.obtainMessage(MSG_SET_PAUSE_IMAGE, uri).sendToTarget();
252 }
253 }
254
255 public VideoProvider() {
256 mBinder = new VideoProvider.VideoProviderBinder();
257 }
258
259 /**
260 * Returns binder object which can be used across IPC methods.
261 * @hide
262 */
263 public final IVideoProvider getInterface() {
264 return mBinder;
265 }
266
267 /**
268 * Sets the camera to be used for video recording in a video call.
269 *
270 * @param cameraId The id of the camera.
271 */
272 public abstract void onSetCamera(String cameraId);
273
274 /**
275 * Sets the surface to be used for displaying a preview of what the user's camera is
276 * currently capturing. When video transmission is enabled, this is the video signal which
277 * is sent to the remote device.
278 *
279 * @param surface The surface.
280 */
281 public abstract void onSetPreviewSurface(Surface surface);
282
283 /**
284 * Sets the surface to be used for displaying the video received from the remote device.
285 *
286 * @param surface The surface.
287 */
288 public abstract void onSetDisplaySurface(Surface surface);
289
290 /**
291 * Sets the device orientation, in degrees. Assumes that a standard portrait orientation of
292 * the device is 0 degrees.
293 *
294 * @param rotation The device orientation, in degrees.
295 */
296 public abstract void onSetDeviceOrientation(int rotation);
297
298 /**
299 * Sets camera zoom ratio.
300 *
301 * @param value The camera zoom ratio.
302 */
303 public abstract void onSetZoom(float value);
304
305 /**
306 * Issues a request to modify the properties of the current session. The request is
307 * sent to the remote device where it it handled by the In-Call UI.
308 * Some examples of session modification requests: upgrade call from audio to video,
309 * downgrade call from video to audio, pause video.
310 *
311 * @param requestProfile The requested call video properties.
312 */
313 public abstract void onSendSessionModifyRequest(VideoProfile requestProfile);
314
315 /**te
316 * Provides a response to a request to change the current call session video
317 * properties.
318 * This is in response to a request the InCall UI has received via the InCall UI.
319 *
320 * @param responseProfile The response call video properties.
321 */
322 public abstract void onSendSessionModifyResponse(VideoProfile responseProfile);
323
324 /**
325 * Issues a request to the video provider to retrieve the camera capabilities.
326 * Camera capabilities are reported back to the caller via the In-Call UI.
327 */
328 public abstract void onRequestCameraCapabilities();
329
330 /**
331 * Issues a request to the video telephony framework to retrieve the cumulative data usage
332 * for the current call. Data usage is reported back to the caller via the
333 * InCall UI.
334 */
335 public abstract void onRequestCallDataUsage();
336
337 /**
338 * Provides the video telephony framework with the URI of an image to be displayed to remote
339 * devices when the video signal is paused.
340 *
341 * @param uri URI of image to display.
342 */
343 public abstract void onSetPauseImage(String uri);
344
345 /**
346 * Invokes callback method defined in In-Call UI.
347 *
348 * @param videoProfile The requested video call profile.
349 */
350 public void receiveSessionModifyRequest(VideoProfile videoProfile) {
Ihab Awada64627c2014-08-20 09:36:40 -0700351 if (mVideoCallback != null) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700352 try {
Ihab Awada64627c2014-08-20 09:36:40 -0700353 mVideoCallback.receiveSessionModifyRequest(videoProfile);
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700354 } catch (RemoteException ignored) {
355 }
356 }
357 }
358
359 /**
360 * Invokes callback method defined in In-Call UI.
361 *
362 * @param status Status of the session modify request. Valid values are
363 * {@link VideoProvider#SESSION_MODIFY_REQUEST_SUCCESS},
364 * {@link VideoProvider#SESSION_MODIFY_REQUEST_FAIL},
365 * {@link VideoProvider#SESSION_MODIFY_REQUEST_INVALID}
366 * @param requestedProfile The original request which was sent to the remote device.
367 * @param responseProfile The actual profile changes made by the remote device.
368 */
369 public void receiveSessionModifyResponse(int status,
370 VideoProfile requestedProfile, VideoProfile responseProfile) {
Ihab Awada64627c2014-08-20 09:36:40 -0700371 if (mVideoCallback != null) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700372 try {
Ihab Awada64627c2014-08-20 09:36:40 -0700373 mVideoCallback.receiveSessionModifyResponse(
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700374 status, requestedProfile, responseProfile);
375 } catch (RemoteException ignored) {
376 }
377 }
378 }
379
380 /**
381 * Invokes callback method defined in In-Call UI.
382 *
383 * Valid values are: {@link VideoProvider#SESSION_EVENT_RX_PAUSE},
384 * {@link VideoProvider#SESSION_EVENT_RX_RESUME},
385 * {@link VideoProvider#SESSION_EVENT_TX_START},
386 * {@link VideoProvider#SESSION_EVENT_TX_STOP}
387 *
388 * @param event The event.
389 */
390 public void handleCallSessionEvent(int event) {
Ihab Awada64627c2014-08-20 09:36:40 -0700391 if (mVideoCallback != null) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700392 try {
Ihab Awada64627c2014-08-20 09:36:40 -0700393 mVideoCallback.handleCallSessionEvent(event);
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700394 } catch (RemoteException ignored) {
395 }
396 }
397 }
398
399 /**
400 * Invokes callback method defined in In-Call UI.
401 *
402 * @param width The updated peer video width.
403 * @param height The updated peer video height.
404 */
405 public void changePeerDimensions(int width, int height) {
Ihab Awada64627c2014-08-20 09:36:40 -0700406 if (mVideoCallback != null) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700407 try {
Ihab Awada64627c2014-08-20 09:36:40 -0700408 mVideoCallback.changePeerDimensions(width, height);
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700409 } catch (RemoteException ignored) {
410 }
411 }
412 }
413
414 /**
415 * Invokes callback method defined in In-Call UI.
416 *
417 * @param dataUsage The updated data usage.
418 */
419 public void changeCallDataUsage(int dataUsage) {
Ihab Awada64627c2014-08-20 09:36:40 -0700420 if (mVideoCallback != null) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700421 try {
Ihab Awada64627c2014-08-20 09:36:40 -0700422 mVideoCallback.changeCallDataUsage(dataUsage);
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700423 } catch (RemoteException ignored) {
424 }
425 }
426 }
427
428 /**
429 * Invokes callback method defined in In-Call UI.
430 *
431 * @param cameraCapabilities The changed camera capabilities.
432 */
433 public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) {
Ihab Awada64627c2014-08-20 09:36:40 -0700434 if (mVideoCallback != null) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700435 try {
Ihab Awada64627c2014-08-20 09:36:40 -0700436 mVideoCallback.changeCameraCapabilities(cameraCapabilities);
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700437 } catch (RemoteException ignored) {
438 }
439 }
440 }
Ihab Awad542e0ea2014-05-16 10:22:16 -0700441 }
442
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700443 private final Listener mConnectionDeathListener = new Listener() {
444 @Override
445 public void onDestroyed(Connection c) {
446 if (mConferenceableConnections.remove(c)) {
447 fireOnConferenceableConnectionsChanged();
448 }
449 }
450 };
451
Jay Shrauner229e3822014-08-15 09:23:07 -0700452 /**
453 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
454 * load factor before resizing, 1 means we only expect a single thread to
455 * access the map so make only a single shard
456 */
457 private final Set<Listener> mListeners = Collections.newSetFromMap(
458 new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700459 private final List<Connection> mConferenceableConnections = new ArrayList<>();
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700460 private final List<Connection> mUnmodifiableConferenceableConnections =
461 Collections.unmodifiableList(mConferenceableConnections);
Santos Cordonb6939982014-06-04 20:20:58 -0700462
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700463 private int mState = STATE_NEW;
464 private AudioState mAudioState;
Andrew Lee100e2932014-09-08 15:34:24 -0700465 private Uri mAddress;
466 private int mAddressPresentation;
Sailesh Nepal61203862014-07-11 14:50:13 -0700467 private String mCallerDisplayName;
468 private int mCallerDisplayNamePresentation;
Andrew Lee100e2932014-09-08 15:34:24 -0700469 private boolean mRingbackRequested = false;
Sailesh Nepal1a7061b2014-07-09 21:03:20 -0700470 private int mCallCapabilities;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700471 private VideoProvider mVideoProvider;
Sailesh Nepal33aaae42014-07-07 22:49:44 -0700472 private boolean mAudioModeIsVoip;
Sailesh Nepale7ef59a2014-07-08 21:48:22 -0700473 private StatusHints mStatusHints;
Tyler Gunnaa07df82014-07-17 07:50:22 -0700474 private int mVideoState;
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700475 private DisconnectCause mDisconnectCause;
Santos Cordon823fd3c2014-08-07 18:35:18 -0700476 private Conference mConference;
477 private ConnectionService mConnectionService;
Ihab Awad542e0ea2014-05-16 10:22:16 -0700478
479 /**
480 * Create a new Connection.
481 */
Santos Cordonf2951102014-07-20 19:06:29 -0700482 public Connection() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700483
484 /**
Andrew Lee100e2932014-09-08 15:34:24 -0700485 * @return The address (e.g., phone number) to which this Connection is currently communicating.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700486 */
Andrew Lee100e2932014-09-08 15:34:24 -0700487 public final Uri getAddress() {
488 return mAddress;
Ihab Awad542e0ea2014-05-16 10:22:16 -0700489 }
490
491 /**
Andrew Lee100e2932014-09-08 15:34:24 -0700492 * @return The presentation requirements for the address.
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700493 * See {@link TelecomManager} for valid values.
Sailesh Nepal61203862014-07-11 14:50:13 -0700494 */
Andrew Lee100e2932014-09-08 15:34:24 -0700495 public final int getAddressPresentation() {
496 return mAddressPresentation;
Sailesh Nepal61203862014-07-11 14:50:13 -0700497 }
498
499 /**
500 * @return The caller display name (CNAP).
501 */
502 public final String getCallerDisplayName() {
503 return mCallerDisplayName;
504 }
505
506 /**
Nancy Chen9d568c02014-09-08 14:17:59 -0700507 * @return The presentation requirements for the handle.
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700508 * See {@link TelecomManager} for valid values.
Sailesh Nepal61203862014-07-11 14:50:13 -0700509 */
510 public final int getCallerDisplayNamePresentation() {
511 return mCallerDisplayNamePresentation;
512 }
513
514 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700515 * @return The state of this Connection.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700516 */
517 public final int getState() {
518 return mState;
519 }
520
521 /**
Tyler Gunnaa07df82014-07-17 07:50:22 -0700522 * Returns the video state of the call.
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700523 * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY},
524 * {@link VideoProfile.VideoState#BIDIRECTIONAL},
525 * {@link VideoProfile.VideoState#TX_ENABLED},
526 * {@link VideoProfile.VideoState#RX_ENABLED}.
Tyler Gunnaa07df82014-07-17 07:50:22 -0700527 *
528 * @return The video state of the call.
Tyler Gunn27d1e252014-08-21 16:38:40 -0700529 * @hide
Tyler Gunnaa07df82014-07-17 07:50:22 -0700530 */
531 public final int getVideoState() {
532 return mVideoState;
533 }
534
535 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700536 * @return The audio state of the call, describing how its audio is currently
537 * being routed by the system. This is {@code null} if this Connection
538 * does not directly know about its audio state.
539 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700540 public final AudioState getAudioState() {
541 return mAudioState;
Ihab Awad542e0ea2014-05-16 10:22:16 -0700542 }
543
544 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -0700545 * @return The conference that this connection is a part of. Null if it is not part of any
546 * conference.
547 */
548 public final Conference getConference() {
549 return mConference;
550 }
551
552 /**
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700553 * Returns whether this connection is requesting that the system play a ringback tone
554 * on its behalf.
555 */
Andrew Lee100e2932014-09-08 15:34:24 -0700556 public final boolean isRingbackRequested() {
557 return mRingbackRequested;
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700558 }
559
560 /**
Sailesh Nepal33aaae42014-07-07 22:49:44 -0700561 * @return True if the connection's audio mode is VOIP.
562 */
563 public final boolean getAudioModeIsVoip() {
564 return mAudioModeIsVoip;
565 }
566
567 /**
Sailesh Nepale7ef59a2014-07-08 21:48:22 -0700568 * @return The status hints for this connection.
569 */
570 public final StatusHints getStatusHints() {
571 return mStatusHints;
572 }
573
574 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700575 * Assign a listener to be notified of state changes.
576 *
577 * @param l A listener.
578 * @return This Connection.
579 *
580 * @hide
581 */
582 public final Connection addConnectionListener(Listener l) {
Santos Cordond34e5712014-08-05 18:54:03 +0000583 mListeners.add(l);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700584 return this;
585 }
586
587 /**
588 * Remove a previously assigned listener that was being notified of state changes.
589 *
590 * @param l A Listener.
591 * @return This Connection.
592 *
593 * @hide
594 */
595 public final Connection removeConnectionListener(Listener l) {
Jay Shrauner229e3822014-08-15 09:23:07 -0700596 if (l != null) {
597 mListeners.remove(l);
598 }
Ihab Awad542e0ea2014-05-16 10:22:16 -0700599 return this;
600 }
601
602 /**
Sailesh Nepalcf7020b2014-08-20 10:07:19 -0700603 * @return The {@link DisconnectCause} for this connection.
Evan Charltonbf11f982014-07-20 22:06:28 -0700604 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700605 public final DisconnectCause getDisconnectCause() {
Sailesh Nepalcf7020b2014-08-20 10:07:19 -0700606 return mDisconnectCause;
Evan Charltonbf11f982014-07-20 22:06:28 -0700607 }
608
609 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700610 * Inform this Connection that the state of its audio output has been changed externally.
611 *
612 * @param state The new audio state.
Sailesh Nepal400cc482014-06-26 12:04:00 -0700613 * @hide
Ihab Awad542e0ea2014-05-16 10:22:16 -0700614 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700615 final void setAudioState(AudioState state) {
Ihab Awad60ac30b2014-05-20 22:32:12 -0700616 Log.d(this, "setAudioState %s", state);
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700617 mAudioState = state;
Nancy Chen354b2bd2014-09-08 18:27:26 -0700618 onAudioStateChanged(state);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700619 }
620
621 /**
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700622 * @param state An integer value of a {@code STATE_*} constant.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700623 * @return A string representation of the value.
624 */
625 public static String stateToString(int state) {
626 switch (state) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700627 case STATE_INITIALIZING:
628 return "STATE_INITIALIZING";
629 case STATE_NEW:
630 return "STATE_NEW";
631 case STATE_RINGING:
632 return "STATE_RINGING";
633 case STATE_DIALING:
634 return "STATE_DIALING";
635 case STATE_ACTIVE:
636 return "STATE_ACTIVE";
637 case STATE_HOLDING:
638 return "STATE_HOLDING";
639 case STATE_DISCONNECTED:
Ihab Awad542e0ea2014-05-16 10:22:16 -0700640 return "DISCONNECTED";
641 default:
Ihab Awad60ac30b2014-05-20 22:32:12 -0700642 Log.wtf(Connection.class, "Unknown state %d", state);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700643 return "UNKNOWN";
644 }
645 }
646
647 /**
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700648 * Returns the connection's {@link PhoneCapabilities}
Ihab Awad52a28f62014-06-18 10:26:34 -0700649 */
Sailesh Nepal1a7061b2014-07-09 21:03:20 -0700650 public final int getCallCapabilities() {
651 return mCallCapabilities;
Ihab Awad52a28f62014-06-18 10:26:34 -0700652 }
653
654 /**
Andrew Lee100e2932014-09-08 15:34:24 -0700655 * Sets the value of the {@link #getAddress()} property.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700656 *
Andrew Lee100e2932014-09-08 15:34:24 -0700657 * @param address The new address.
658 * @param presentation The presentation requirements for the address.
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700659 * See {@link TelecomManager} for valid values.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700660 */
Andrew Lee100e2932014-09-08 15:34:24 -0700661 public final void setAddress(Uri address, int presentation) {
662 Log.d(this, "setAddress %s", address);
663 mAddress = address;
664 mAddressPresentation = presentation;
Santos Cordond34e5712014-08-05 18:54:03 +0000665 for (Listener l : mListeners) {
Andrew Lee100e2932014-09-08 15:34:24 -0700666 l.onAddressChanged(this, address, presentation);
Santos Cordond34e5712014-08-05 18:54:03 +0000667 }
Ihab Awad542e0ea2014-05-16 10:22:16 -0700668 }
669
670 /**
Sailesh Nepal61203862014-07-11 14:50:13 -0700671 * Sets the caller display name (CNAP).
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700672 *
Sailesh Nepal61203862014-07-11 14:50:13 -0700673 * @param callerDisplayName The new display name.
Nancy Chen9d568c02014-09-08 14:17:59 -0700674 * @param presentation The presentation requirements for the handle.
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700675 * See {@link TelecomManager} for valid values.
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700676 */
Sailesh Nepal61203862014-07-11 14:50:13 -0700677 public final void setCallerDisplayName(String callerDisplayName, int presentation) {
678 Log.d(this, "setCallerDisplayName %s", callerDisplayName);
Santos Cordond34e5712014-08-05 18:54:03 +0000679 mCallerDisplayName = callerDisplayName;
680 mCallerDisplayNamePresentation = presentation;
681 for (Listener l : mListeners) {
682 l.onCallerDisplayNameChanged(this, callerDisplayName, presentation);
683 }
Sailesh Nepal2a46b902014-07-04 17:21:07 -0700684 }
685
686 /**
Tyler Gunnaa07df82014-07-17 07:50:22 -0700687 * Set the video state for the connection.
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700688 * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY},
689 * {@link VideoProfile.VideoState#BIDIRECTIONAL},
690 * {@link VideoProfile.VideoState#TX_ENABLED},
691 * {@link VideoProfile.VideoState#RX_ENABLED}.
Tyler Gunnaa07df82014-07-17 07:50:22 -0700692 *
693 * @param videoState The new video state.
Tyler Gunn27d1e252014-08-21 16:38:40 -0700694 * @hide
Tyler Gunnaa07df82014-07-17 07:50:22 -0700695 */
696 public final void setVideoState(int videoState) {
697 Log.d(this, "setVideoState %d", videoState);
Santos Cordond34e5712014-08-05 18:54:03 +0000698 mVideoState = videoState;
699 for (Listener l : mListeners) {
700 l.onVideoStateChanged(this, mVideoState);
701 }
Tyler Gunnaa07df82014-07-17 07:50:22 -0700702 }
703
704 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700705 * Sets state to active (e.g., an ongoing call where two or more parties can actively
706 * communicate).
707 */
Sailesh Nepal400cc482014-06-26 12:04:00 -0700708 public final void setActive() {
Andrew Lee100e2932014-09-08 15:34:24 -0700709 setRingbackRequested(false);
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700710 setState(STATE_ACTIVE);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700711 }
712
713 /**
714 * Sets state to ringing (e.g., an inbound ringing call).
715 */
Sailesh Nepal400cc482014-06-26 12:04:00 -0700716 public final void setRinging() {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700717 setState(STATE_RINGING);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700718 }
719
720 /**
Evan Charltonbf11f982014-07-20 22:06:28 -0700721 * Sets state to initializing (this Connection is not yet ready to be used).
722 */
723 public final void setInitializing() {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700724 setState(STATE_INITIALIZING);
Evan Charltonbf11f982014-07-20 22:06:28 -0700725 }
726
727 /**
728 * Sets state to initialized (the Connection has been set up and is now ready to be used).
729 */
730 public final void setInitialized() {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700731 setState(STATE_NEW);
Evan Charltonbf11f982014-07-20 22:06:28 -0700732 }
733
734 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700735 * Sets state to dialing (e.g., dialing an outbound call).
736 */
Sailesh Nepal400cc482014-06-26 12:04:00 -0700737 public final void setDialing() {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700738 setState(STATE_DIALING);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700739 }
740
741 /**
742 * Sets state to be on hold.
743 */
Sailesh Nepal400cc482014-06-26 12:04:00 -0700744 public final void setOnHold() {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700745 setState(STATE_HOLDING);
Ihab Awad542e0ea2014-05-16 10:22:16 -0700746 }
747
748 /**
Andrew Lee50aca232014-07-22 16:41:54 -0700749 * Sets the video call provider.
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700750 * @param videoProvider The video provider.
Tyler Gunn27d1e252014-08-21 16:38:40 -0700751 * @hide
Andrew Lee5ffbe8b2014-06-20 16:29:33 -0700752 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700753 public final void setVideoProvider(VideoProvider videoProvider) {
754 mVideoProvider = videoProvider;
Santos Cordond34e5712014-08-05 18:54:03 +0000755 for (Listener l : mListeners) {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700756 l.onVideoProviderChanged(this, videoProvider);
Santos Cordond34e5712014-08-05 18:54:03 +0000757 }
Andrew Lee5ffbe8b2014-06-20 16:29:33 -0700758 }
759
Tyler Gunn27d1e252014-08-21 16:38:40 -0700760 /** @hide */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700761 public final VideoProvider getVideoProvider() {
762 return mVideoProvider;
Andrew Leea27a1932014-07-09 17:07:13 -0700763 }
764
Andrew Lee5ffbe8b2014-06-20 16:29:33 -0700765 /**
Sailesh Nepal091768c2014-06-30 15:15:23 -0700766 * Sets state to disconnected.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700767 *
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700768 * @param disconnectCause The reason for the disconnection, as specified by
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700769 * {@link DisconnectCause}.
Ihab Awad542e0ea2014-05-16 10:22:16 -0700770 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700771 public final void setDisconnected(DisconnectCause disconnectCause) {
772 mDisconnectCause = disconnectCause;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700773 setState(STATE_DISCONNECTED);
mike dooleyf34519b2014-09-16 17:33:40 -0700774 Log.d(this, "Disconnected with cause %s", disconnectCause);
Santos Cordond34e5712014-08-05 18:54:03 +0000775 for (Listener l : mListeners) {
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700776 l.onDisconnected(this, disconnectCause);
Santos Cordond34e5712014-08-05 18:54:03 +0000777 }
Ihab Awad542e0ea2014-05-16 10:22:16 -0700778 }
779
780 /**
Santos Cordon8abea422014-08-06 04:46:17 -0700781 * TODO: Needs documentation.
Sailesh Nepal091768c2014-06-30 15:15:23 -0700782 */
783 public final void setPostDialWait(String remaining) {
Santos Cordond34e5712014-08-05 18:54:03 +0000784 for (Listener l : mListeners) {
785 l.onPostDialWait(this, remaining);
786 }
Sailesh Nepal091768c2014-06-30 15:15:23 -0700787 }
788
789 /**
Ihab Awadf8358972014-05-28 16:46:42 -0700790 * Requests that the framework play a ringback tone. This is to be invoked by implementations
791 * that do not play a ringback tone themselves in the call's audio stream.
792 *
793 * @param ringback Whether the ringback tone is to be played.
794 */
Andrew Lee100e2932014-09-08 15:34:24 -0700795 public final void setRingbackRequested(boolean ringback) {
796 if (mRingbackRequested != ringback) {
797 mRingbackRequested = ringback;
Santos Cordond34e5712014-08-05 18:54:03 +0000798 for (Listener l : mListeners) {
Andrew Lee100e2932014-09-08 15:34:24 -0700799 l.onRingbackRequested(this, ringback);
Santos Cordond34e5712014-08-05 18:54:03 +0000800 }
801 }
Ihab Awadf8358972014-05-28 16:46:42 -0700802 }
803
804 /**
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700805 * Sets the connection's {@link PhoneCapabilities}.
Sailesh Nepal1a7061b2014-07-09 21:03:20 -0700806 *
807 * @param callCapabilities The new call capabilities.
Santos Cordonb6939982014-06-04 20:20:58 -0700808 */
Sailesh Nepal1a7061b2014-07-09 21:03:20 -0700809 public final void setCallCapabilities(int callCapabilities) {
Santos Cordond34e5712014-08-05 18:54:03 +0000810 if (mCallCapabilities != callCapabilities) {
811 mCallCapabilities = callCapabilities;
812 for (Listener l : mListeners) {
813 l.onCallCapabilitiesChanged(this, mCallCapabilities);
814 }
815 }
Santos Cordonb6939982014-06-04 20:20:58 -0700816 }
817
818 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700819 * Tears down the Connection object.
Santos Cordonb6939982014-06-04 20:20:58 -0700820 */
Evan Charlton36a71342014-07-19 16:31:02 -0700821 public final void destroy() {
Jay Shrauner229e3822014-08-15 09:23:07 -0700822 for (Listener l : mListeners) {
823 l.onDestroyed(this);
Santos Cordond34e5712014-08-05 18:54:03 +0000824 }
Santos Cordonb6939982014-06-04 20:20:58 -0700825 }
826
827 /**
Sailesh Nepal33aaae42014-07-07 22:49:44 -0700828 * Requests that the framework use VOIP audio mode for this connection.
829 *
830 * @param isVoip True if the audio mode is VOIP.
831 */
832 public final void setAudioModeIsVoip(boolean isVoip) {
Santos Cordond34e5712014-08-05 18:54:03 +0000833 mAudioModeIsVoip = isVoip;
834 for (Listener l : mListeners) {
835 l.onAudioModeIsVoipChanged(this, isVoip);
836 }
Sailesh Nepal33aaae42014-07-07 22:49:44 -0700837 }
838
839 /**
Sailesh Nepale7ef59a2014-07-08 21:48:22 -0700840 * Sets the label and icon status to display in the in-call UI.
841 *
842 * @param statusHints The status label and icon to set.
843 */
844 public final void setStatusHints(StatusHints statusHints) {
Santos Cordond34e5712014-08-05 18:54:03 +0000845 mStatusHints = statusHints;
846 for (Listener l : mListeners) {
847 l.onStatusHintsChanged(this, statusHints);
848 }
Sailesh Nepale7ef59a2014-07-08 21:48:22 -0700849 }
850
851 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700852 * Sets the connections with which this connection can be conferenced.
853 *
854 * @param conferenceableConnections The set of connections this connection can conference with.
855 */
856 public final void setConferenceableConnections(List<Connection> conferenceableConnections) {
857 clearConferenceableList();
858 for (Connection c : conferenceableConnections) {
859 // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a
860 // small amount of items here.
861 if (!mConferenceableConnections.contains(c)) {
862 c.addConnectionListener(mConnectionDeathListener);
863 mConferenceableConnections.add(c);
864 }
865 }
866 fireOnConferenceableConnectionsChanged();
867 }
868
869 /**
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700870 * Obtains the connections with which this connection can be conferenced.
871 */
872 public final List<Connection> getConferenceableConnections() {
873 return mUnmodifiableConferenceableConnections;
874 }
875
Evan Charlton8635c572014-09-24 14:04:51 -0700876 /*
Santos Cordon823fd3c2014-08-07 18:35:18 -0700877 * @hide
878 */
879 public final void setConnectionService(ConnectionService connectionService) {
880 if (mConnectionService != null) {
881 Log.e(this, new Exception(), "Trying to set ConnectionService on a connection " +
882 "which is already associated with another ConnectionService.");
883 } else {
884 mConnectionService = connectionService;
885 }
886 }
887
888 /**
889 * @hide
890 */
891 public final void unsetConnectionService(ConnectionService connectionService) {
892 if (mConnectionService != connectionService) {
893 Log.e(this, new Exception(), "Trying to remove ConnectionService from a Connection " +
894 "that does not belong to the ConnectionService.");
895 } else {
896 mConnectionService = null;
897 }
898 }
899
900 /**
901 * Sets the conference that this connection is a part of. This will fail if the connection is
902 * already part of a conference call. {@link #resetConference} to un-set the conference first.
903 *
904 * @param conference The conference.
905 * @return {@code true} if the conference was successfully set.
906 * @hide
907 */
908 public final boolean setConference(Conference conference) {
909 // We check to see if it is already part of another conference.
Santos Cordon0159ac02014-08-21 14:28:11 -0700910 if (mConference == null) {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700911 mConference = conference;
Santos Cordon0159ac02014-08-21 14:28:11 -0700912 if (mConnectionService != null && mConnectionService.containsConference(conference)) {
913 fireConferenceChanged();
914 }
Santos Cordon823fd3c2014-08-07 18:35:18 -0700915 return true;
916 }
917 return false;
918 }
919
920 /**
921 * Resets the conference that this connection is a part of.
922 * @hide
923 */
924 public final void resetConference() {
925 if (mConference != null) {
Santos Cordon0159ac02014-08-21 14:28:11 -0700926 Log.d(this, "Conference reset");
Santos Cordon823fd3c2014-08-07 18:35:18 -0700927 mConference = null;
928 fireConferenceChanged();
929 }
930 }
931
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700932 /**
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700933 * Notifies this Connection that the {@link #getAudioState()} property has a new value.
Sailesh Nepal400cc482014-06-26 12:04:00 -0700934 *
935 * @param state The new call audio state.
936 */
Nancy Chen354b2bd2014-09-08 18:27:26 -0700937 public void onAudioStateChanged(AudioState state) {}
Sailesh Nepal400cc482014-06-26 12:04:00 -0700938
939 /**
Evan Charltonbf11f982014-07-20 22:06:28 -0700940 * Notifies this Connection of an internal state change. This method is called after the
941 * state is changed.
Ihab Awadf8358972014-05-28 16:46:42 -0700942 *
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700943 * @param state The new state, one of the {@code STATE_*} constants.
Ihab Awadf8358972014-05-28 16:46:42 -0700944 */
Nancy Chen354b2bd2014-09-08 18:27:26 -0700945 public void onStateChanged(int state) {}
Ihab Awadf8358972014-05-28 16:46:42 -0700946
947 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700948 * Notifies this Connection of a request to play a DTMF tone.
949 *
950 * @param c A DTMF character.
951 */
Santos Cordonf2951102014-07-20 19:06:29 -0700952 public void onPlayDtmfTone(char c) {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700953
954 /**
955 * Notifies this Connection of a request to stop any currently playing DTMF tones.
956 */
Santos Cordonf2951102014-07-20 19:06:29 -0700957 public void onStopDtmfTone() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700958
959 /**
960 * Notifies this Connection of a request to disconnect.
961 */
Santos Cordonf2951102014-07-20 19:06:29 -0700962 public void onDisconnect() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700963
964 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -0700965 * Notifies this Connection of a request to separate from its parent conference.
Santos Cordonb6939982014-06-04 20:20:58 -0700966 */
Santos Cordonf2951102014-07-20 19:06:29 -0700967 public void onSeparate() {}
Santos Cordonb6939982014-06-04 20:20:58 -0700968
969 /**
Ihab Awad542e0ea2014-05-16 10:22:16 -0700970 * Notifies this Connection of a request to abort.
971 */
Santos Cordonf2951102014-07-20 19:06:29 -0700972 public void onAbort() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700973
974 /**
975 * Notifies this Connection of a request to hold.
976 */
Santos Cordonf2951102014-07-20 19:06:29 -0700977 public void onHold() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700978
979 /**
980 * Notifies this Connection of a request to exit a hold state.
981 */
Santos Cordonf2951102014-07-20 19:06:29 -0700982 public void onUnhold() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700983
984 /**
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700985 * Notifies this Connection, which is in {@link #STATE_RINGING}, of
Santos Cordond34e5712014-08-05 18:54:03 +0000986 * a request to accept.
Andrew Lee8da4c3c2014-07-16 10:11:42 -0700987 *
988 * @param videoState The video state in which to answer the call.
Tyler Gunnbe74de02014-08-29 14:51:48 -0700989 * @hide
Ihab Awad542e0ea2014-05-16 10:22:16 -0700990 */
Santos Cordonf2951102014-07-20 19:06:29 -0700991 public void onAnswer(int videoState) {}
Ihab Awad542e0ea2014-05-16 10:22:16 -0700992
993 /**
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700994 * Notifies this Connection, which is in {@link #STATE_RINGING}, of
Tyler Gunnbe74de02014-08-29 14:51:48 -0700995 * a request to accept.
996 */
997 public void onAnswer() {
998 onAnswer(VideoProfile.VideoState.AUDIO_ONLY);
999 }
1000
1001 /**
1002 * Notifies this Connection, which is in {@link #STATE_RINGING}, of
Santos Cordond34e5712014-08-05 18:54:03 +00001003 * a request to reject.
Ihab Awad542e0ea2014-05-16 10:22:16 -07001004 */
Santos Cordonf2951102014-07-20 19:06:29 -07001005 public void onReject() {}
Ihab Awad542e0ea2014-05-16 10:22:16 -07001006
Evan Charlton6dea4ac2014-06-03 14:07:13 -07001007 /**
1008 * Notifies this Connection whether the user wishes to proceed with the post-dial DTMF codes.
1009 */
Santos Cordonf2951102014-07-20 19:06:29 -07001010 public void onPostDialContinue(boolean proceed) {}
Evan Charlton6dea4ac2014-06-03 14:07:13 -07001011
Santos Cordonb6939982014-06-04 20:20:58 -07001012 /**
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001013 * Merge this connection and the specified connection into a conference call. Once the
1014 * connections are merged, the calls should be added to the an existing or new
1015 * {@code Conference} instance. For new {@code Conference} instances, use
1016 * {@code ConnectionService#addConference}.
1017 *
1018 * @param otherConnection The connection with which this connection should be conferenced.
1019 */
1020 public void onConferenceWith(Connection otherConnection) {}
1021
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001022 static String toLogSafePhoneNumber(String number) {
1023 // For unknown number, log empty string.
1024 if (number == null) {
1025 return "";
1026 }
1027
1028 if (PII_DEBUG) {
1029 // When PII_DEBUG is true we emit PII.
1030 return number;
1031 }
1032
1033 // Do exactly same thing as Uri#toSafeString() does, which will enable us to compare
1034 // sanitized phone numbers.
1035 StringBuilder builder = new StringBuilder();
1036 for (int i = 0; i < number.length(); i++) {
1037 char c = number.charAt(i);
1038 if (c == '-' || c == '@' || c == '.') {
1039 builder.append(c);
1040 } else {
1041 builder.append('x');
1042 }
1043 }
1044 return builder.toString();
1045 }
1046
Ihab Awad542e0ea2014-05-16 10:22:16 -07001047 private void setState(int state) {
Ihab Awad6107bab2014-08-18 09:23:25 -07001048 if (mState == STATE_DISCONNECTED && mState != state) {
1049 Log.d(this, "Connection already DISCONNECTED; cannot transition out of this state.");
Evan Charltonbf11f982014-07-20 22:06:28 -07001050 return;
Sailesh Nepal400cc482014-06-26 12:04:00 -07001051 }
Evan Charltonbf11f982014-07-20 22:06:28 -07001052 if (mState != state) {
1053 Log.d(this, "setState: %s", stateToString(state));
1054 mState = state;
Nancy Chen354b2bd2014-09-08 18:27:26 -07001055 onStateChanged(state);
Evan Charltonbf11f982014-07-20 22:06:28 -07001056 for (Listener l : mListeners) {
1057 l.onStateChanged(this, state);
1058 }
Evan Charltonbf11f982014-07-20 22:06:28 -07001059 }
1060 }
1061
Sailesh Nepalcf7020b2014-08-20 10:07:19 -07001062 private static class FailureSignalingConnection extends Connection {
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001063 public FailureSignalingConnection(DisconnectCause disconnectCause) {
1064 setDisconnected(disconnectCause);
Ihab Awad6107bab2014-08-18 09:23:25 -07001065 }
1066 }
1067
Evan Charltonbf11f982014-07-20 22:06:28 -07001068 /**
Ihab Awad6107bab2014-08-18 09:23:25 -07001069 * Return a {@code Connection} which represents a failed connection attempt. The returned
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001070 * {@code Connection} will have a {@link android.telecom.DisconnectCause} and as specified,
1071 * and a {@link #getState()} of {@link #STATE_DISCONNECTED}.
Ihab Awad6107bab2014-08-18 09:23:25 -07001072 * <p>
1073 * The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate,
1074 * so users of this method need not maintain a reference to its return value to destroy it.
Evan Charltonbf11f982014-07-20 22:06:28 -07001075 *
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001076 * @param disconnectCause The disconnect cause, ({@see android.telecomm.DisconnectCause}).
Ihab Awad6107bab2014-08-18 09:23:25 -07001077 * @return A {@code Connection} which indicates failure.
Evan Charltonbf11f982014-07-20 22:06:28 -07001078 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001079 public static Connection createFailedConnection(DisconnectCause disconnectCause) {
1080 return new FailureSignalingConnection(disconnectCause);
Evan Charltonbf11f982014-07-20 22:06:28 -07001081 }
1082
Evan Charltonbf11f982014-07-20 22:06:28 -07001083 /**
Ihab Awad6107bab2014-08-18 09:23:25 -07001084 * Return a {@code Connection} which represents a canceled connection attempt. The returned
1085 * {@code Connection} will have state {@link #STATE_DISCONNECTED}, and cannot be moved out of
1086 * that state. This connection should not be used for anything, and no other
1087 * {@code Connection}s should be attempted.
1088 * <p>
1089 * The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate,
1090 * so users of this method need not maintain a reference to its return value to destroy it.
Evan Charltonbf11f982014-07-20 22:06:28 -07001091 *
Ihab Awad6107bab2014-08-18 09:23:25 -07001092 * @return A {@code Connection} which indicates that the underlying call should be canceled.
Evan Charltonbf11f982014-07-20 22:06:28 -07001093 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -07001094 public static Connection createCanceledConnection() {
Andrew Lee7f3d41f2014-09-11 17:33:16 -07001095 return new FailureSignalingConnection(new DisconnectCause(DisconnectCause.CANCELED));
Ihab Awad542e0ea2014-05-16 10:22:16 -07001096 }
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001097
1098 private final void fireOnConferenceableConnectionsChanged() {
1099 for (Listener l : mListeners) {
1100 l.onConferenceableConnectionsChanged(this, mConferenceableConnections);
1101 }
1102 }
1103
Santos Cordon823fd3c2014-08-07 18:35:18 -07001104 private final void fireConferenceChanged() {
1105 for (Listener l : mListeners) {
1106 l.onConferenceChanged(this, mConference);
1107 }
1108 }
1109
Santos Cordon7c7bc7f2014-07-28 18:15:48 -07001110 private final void clearConferenceableList() {
1111 for (Connection c : mConferenceableConnections) {
1112 c.removeConnectionListener(mConnectionDeathListener);
1113 }
1114 mConferenceableConnections.clear();
1115 }
Ihab Awad542e0ea2014-05-16 10:22:16 -07001116}