Connection.java revision 1cf9b6bec12c027a0d551540a6e01f3ac2d0a9d4
1/* 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.telecom; 18 19import com.android.internal.telecom.IVideoCallback; 20import com.android.internal.telecom.IVideoProvider; 21 22import android.net.Uri; 23import android.os.Handler; 24import android.os.IBinder; 25import android.os.Message; 26import android.os.RemoteException; 27import android.view.Surface; 28 29import java.util.ArrayList; 30import java.util.Collections; 31import java.util.List; 32import java.util.Set; 33import java.util.concurrent.ConcurrentHashMap; 34 35/** 36 * Represents a connection to a remote endpoint that carries voice traffic. 37 * <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. 46 */ 47public abstract class Connection implements IConferenceable { 48 49 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 63 /** Connection can currently be put on hold or unheld. */ 64 public static final int CAPABILITY_HOLD = 0x00000001; 65 66 /** Connection supports the hold feature. */ 67 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002; 68 69 /** 70 * Connections within a conference can be merged. A {@link ConnectionService} has the option to 71 * add a {@link Conference} before the child {@link Connection}s are merged. This is how 72 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this 73 * capability allows a merge button to be shown while the conference is in the foreground 74 * of the in-call UI. 75 * <p> 76 * This is only intended for use by a {@link Conference}. 77 */ 78 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004; 79 80 /** 81 * Connections within a conference can be swapped between foreground and background. 82 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information. 83 * <p> 84 * This is only intended for use by a {@link Conference}. 85 */ 86 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008; 87 88 /** 89 * @hide 90 */ 91 public static final int CAPABILITY_UNUSED = 0x00000010; 92 93 /** Connection supports responding via text option. */ 94 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020; 95 96 /** Connection can be muted. */ 97 public static final int CAPABILITY_MUTE = 0x00000040; 98 99 /** 100 * Connection supports conference management. This capability only applies to 101 * {@link Conference}s which can have {@link Connection}s as children. 102 */ 103 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080; 104 105 /** 106 * Local device supports receiving video. 107 * @hide 108 */ 109 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100; 110 111 /** 112 * Local device supports transmitting video. 113 * @hide 114 */ 115 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200; 116 117 /** 118 * Local device supports bidirectional video calling. 119 * @hide 120 */ 121 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL = 122 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX; 123 124 /** 125 * Remote device supports receiving video. 126 * @hide 127 */ 128 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400; 129 130 /** 131 * Remote device supports transmitting video. 132 * @hide 133 */ 134 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800; 135 136 /** 137 * Remote device supports bidirectional video calling. 138 * @hide 139 */ 140 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL = 141 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX; 142 143 /** 144 * Connection is able to be separated from its parent {@code Conference}, if any. 145 */ 146 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000; 147 148 /** 149 * Connection is able to be individually disconnected when in a {@code Conference}. 150 */ 151 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000; 152 153 /** 154 * Whether the call is a generic conference, where we do not know the precise state of 155 * participants in the conference (eg. on CDMA). 156 * 157 * @hide 158 */ 159 public static final int CAPABILITY_GENERIC_CONFERENCE = 0x00004000; 160 161 /** 162 * Connection is using high definition audio. 163 * @hide 164 */ 165 public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00008000; 166 167 /** 168 * Connection is using WIFI. 169 * @hide 170 */ 171 public static final int CAPABILITY_WIFI = 0x00010000; 172 173 /** 174 * Indicates that the current device callback number should be shown. 175 * 176 * @hide 177 */ 178 public static final int CAPABILITY_SHOW_CALLBACK_NUMBER = 0x00020000; 179 180 /** 181 * Speed up audio setup for MT call. 182 * @hide 183 */ 184 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000; 185 186 /** 187 * Call can be upgraded to a video call. 188 * @hide 189 */ 190 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000; 191 192 /** 193 * For video calls, indicates whether the outgoing video for the call can be paused using 194 * the {@link android.telecom.VideoProfile.VideoState#PAUSED} VideoState. 195 * @hide 196 */ 197 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000; 198 199 //********************************************************************************************** 200 // Next CAPABILITY value: 0x00200000 201 //********************************************************************************************** 202 203 /** 204 * Call substate bitmask values 205 */ 206 207 /* Default case */ 208 /** 209 * @hide 210 */ 211 public static final int SUBSTATE_NONE = 0; 212 213 /* Indicates that the call is connected but audio attribute is suspended */ 214 /** 215 * @hide 216 */ 217 public static final int SUBSTATE_AUDIO_CONNECTED_SUSPENDED = 0x1; 218 219 /* Indicates that the call is connected but video attribute is suspended */ 220 /** 221 * @hide 222 */ 223 public static final int SUBSTATE_VIDEO_CONNECTED_SUSPENDED = 0x2; 224 225 /* Indicates that the call is established but media retry is needed */ 226 /** 227 * @hide 228 */ 229 public static final int SUBSTATE_AVP_RETRY = 0x4; 230 231 /* Indicates that the call is multitasking */ 232 /** 233 * @hide 234 */ 235 public static final int SUBSTATE_MEDIA_PAUSED = 0x8; 236 237 /* Mask containing all the call substate bits set */ 238 /** 239 * @hide 240 */ 241 public static final int SUBSTATE_ALL = SUBSTATE_AUDIO_CONNECTED_SUSPENDED | 242 SUBSTATE_VIDEO_CONNECTED_SUSPENDED | SUBSTATE_AVP_RETRY | 243 SUBSTATE_MEDIA_PAUSED; 244 245 // Flag controlling whether PII is emitted into the logs 246 private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG); 247 248 /** 249 * Whether the given capabilities support the specified capability. 250 * 251 * @param capabilities A capability bit field. 252 * @param capability The capability to check capabilities for. 253 * @return Whether the specified capability is supported. 254 * @hide 255 */ 256 public static boolean can(int capabilities, int capability) { 257 return (capabilities & capability) != 0; 258 } 259 260 /** 261 * Whether the capabilities of this {@code Connection} supports the specified capability. 262 * 263 * @param capability The capability to check capabilities for. 264 * @return Whether the specified capability is supported. 265 * @hide 266 */ 267 public boolean can(int capability) { 268 return can(mConnectionCapabilities, capability); 269 } 270 271 /** 272 * Removes the specified capability from the set of capabilities of this {@code Connection}. 273 * 274 * @param capability The capability to remove from the set. 275 * @hide 276 */ 277 public void removeCapability(int capability) { 278 mConnectionCapabilities &= ~capability; 279 } 280 281 /** 282 * Adds the specified capability to the set of capabilities of this {@code Connection}. 283 * 284 * @param capability The capability to add to the set. 285 * @hide 286 */ 287 public void addCapability(int capability) { 288 mConnectionCapabilities |= capability; 289 } 290 291 292 public static String capabilitiesToString(int capabilities) { 293 StringBuilder builder = new StringBuilder(); 294 builder.append("[Capabilities:"); 295 if (can(capabilities, CAPABILITY_HOLD)) { 296 builder.append(" CAPABILITY_HOLD"); 297 } 298 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) { 299 builder.append(" CAPABILITY_SUPPORT_HOLD"); 300 } 301 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) { 302 builder.append(" CAPABILITY_MERGE_CONFERENCE"); 303 } 304 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) { 305 builder.append(" CAPABILITY_SWAP_CONFERENCE"); 306 } 307 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) { 308 builder.append(" CAPABILITY_RESPOND_VIA_TEXT"); 309 } 310 if (can(capabilities, CAPABILITY_MUTE)) { 311 builder.append(" CAPABILITY_MUTE"); 312 } 313 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) { 314 builder.append(" CAPABILITY_MANAGE_CONFERENCE"); 315 } 316 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) { 317 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX"); 318 } 319 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) { 320 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX"); 321 } 322 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) { 323 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL"); 324 } 325 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) { 326 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX"); 327 } 328 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) { 329 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX"); 330 } 331 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) { 332 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL"); 333 } 334 if (can(capabilities, CAPABILITY_HIGH_DEF_AUDIO)) { 335 builder.append(" CAPABILITY_HIGH_DEF_AUDIO"); 336 } 337 if (can(capabilities, CAPABILITY_WIFI)) { 338 builder.append(" CAPABILITY_WIFI"); 339 } 340 if (can(capabilities, CAPABILITY_GENERIC_CONFERENCE)) { 341 builder.append(" CAPABILITY_GENERIC_CONFERENCE"); 342 } 343 if (can(capabilities, CAPABILITY_SHOW_CALLBACK_NUMBER)) { 344 builder.append(" CAPABILITY_SHOW_CALLBACK_NUMBER"); 345 } 346 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) { 347 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO"); 348 } 349 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) { 350 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO"); 351 } 352 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) { 353 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO"); 354 } 355 builder.append("]"); 356 return builder.toString(); 357 } 358 359 /** @hide */ 360 public abstract static class Listener { 361 public void onStateChanged(Connection c, int state) {} 362 public void onAddressChanged(Connection c, Uri newAddress, int presentation) {} 363 public void onCallerDisplayNameChanged( 364 Connection c, String callerDisplayName, int presentation) {} 365 public void onVideoStateChanged(Connection c, int videoState) {} 366 public void onDisconnected(Connection c, DisconnectCause disconnectCause) {} 367 public void onPostDialWait(Connection c, String remaining) {} 368 public void onPostDialChar(Connection c, char nextChar) {} 369 public void onRingbackRequested(Connection c, boolean ringback) {} 370 public void onDestroyed(Connection c) {} 371 public void onConnectionCapabilitiesChanged(Connection c, int capabilities) {} 372 public void onVideoProviderChanged( 373 Connection c, VideoProvider videoProvider) {} 374 public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {} 375 public void onStatusHintsChanged(Connection c, StatusHints statusHints) {} 376 public void onConferenceablesChanged( 377 Connection c, List<IConferenceable> conferenceables) {} 378 public void onConferenceChanged(Connection c, Conference conference) {} 379 /** @hide */ 380 public void onConferenceParticipantsChanged(Connection c, 381 List<ConferenceParticipant> participants) {} 382 public void onConferenceStarted() {} 383 public void onCallSubstateChanged(Connection c, int substate) {} 384 } 385 386 public static abstract class VideoProvider { 387 388 /** 389 * Video is not being received (no protocol pause was issued). 390 */ 391 public static final int SESSION_EVENT_RX_PAUSE = 1; 392 393 /** 394 * Video reception has resumed after a SESSION_EVENT_RX_PAUSE. 395 */ 396 public static final int SESSION_EVENT_RX_RESUME = 2; 397 398 /** 399 * Video transmission has begun. This occurs after a negotiated start of video transmission 400 * when the underlying protocol has actually begun transmitting video to the remote party. 401 */ 402 public static final int SESSION_EVENT_TX_START = 3; 403 404 /** 405 * Video transmission has stopped. This occurs after a negotiated stop of video transmission 406 * when the underlying protocol has actually stopped transmitting video to the remote party. 407 */ 408 public static final int SESSION_EVENT_TX_STOP = 4; 409 410 /** 411 * A camera failure has occurred for the selected camera. The In-Call UI can use this as a 412 * cue to inform the user the camera is not available. 413 */ 414 public static final int SESSION_EVENT_CAMERA_FAILURE = 5; 415 416 /** 417 * Issued after {@code SESSION_EVENT_CAMERA_FAILURE} when the camera is once again ready for 418 * operation. The In-Call UI can use this as a cue to inform the user that the camera has 419 * become available again. 420 */ 421 public static final int SESSION_EVENT_CAMERA_READY = 6; 422 423 /** 424 * Session modify request was successful. 425 */ 426 public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; 427 428 /** 429 * Session modify request failed. 430 */ 431 public static final int SESSION_MODIFY_REQUEST_FAIL = 2; 432 433 /** 434 * Session modify request ignored due to invalid parameters. 435 */ 436 public static final int SESSION_MODIFY_REQUEST_INVALID = 3; 437 438 /** 439 * Session modify request timed out. 440 */ 441 public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; 442 443 /** 444 * Session modify request rejected by remote UE. 445 */ 446 public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; 447 448 private static final int MSG_SET_VIDEO_CALLBACK = 1; 449 private static final int MSG_SET_CAMERA = 2; 450 private static final int MSG_SET_PREVIEW_SURFACE = 3; 451 private static final int MSG_SET_DISPLAY_SURFACE = 4; 452 private static final int MSG_SET_DEVICE_ORIENTATION = 5; 453 private static final int MSG_SET_ZOOM = 6; 454 private static final int MSG_SEND_SESSION_MODIFY_REQUEST = 7; 455 private static final int MSG_SEND_SESSION_MODIFY_RESPONSE = 8; 456 private static final int MSG_REQUEST_CAMERA_CAPABILITIES = 9; 457 private static final int MSG_REQUEST_CONNECTION_DATA_USAGE = 10; 458 private static final int MSG_SET_PAUSE_IMAGE = 11; 459 460 private final VideoProvider.VideoProviderHandler 461 mMessageHandler = new VideoProvider.VideoProviderHandler(); 462 private final VideoProvider.VideoProviderBinder mBinder; 463 private IVideoCallback mVideoCallback; 464 465 /** 466 * Default handler used to consolidate binder method calls onto a single thread. 467 */ 468 private final class VideoProviderHandler extends Handler { 469 @Override 470 public void handleMessage(Message msg) { 471 switch (msg.what) { 472 case MSG_SET_VIDEO_CALLBACK: 473 mVideoCallback = IVideoCallback.Stub.asInterface((IBinder) msg.obj); 474 break; 475 case MSG_SET_CAMERA: 476 onSetCamera((String) msg.obj); 477 break; 478 case MSG_SET_PREVIEW_SURFACE: 479 onSetPreviewSurface((Surface) msg.obj); 480 break; 481 case MSG_SET_DISPLAY_SURFACE: 482 onSetDisplaySurface((Surface) msg.obj); 483 break; 484 case MSG_SET_DEVICE_ORIENTATION: 485 onSetDeviceOrientation(msg.arg1); 486 break; 487 case MSG_SET_ZOOM: 488 onSetZoom((Float) msg.obj); 489 break; 490 case MSG_SEND_SESSION_MODIFY_REQUEST: 491 onSendSessionModifyRequest((VideoProfile) msg.obj); 492 break; 493 case MSG_SEND_SESSION_MODIFY_RESPONSE: 494 onSendSessionModifyResponse((VideoProfile) msg.obj); 495 break; 496 case MSG_REQUEST_CAMERA_CAPABILITIES: 497 onRequestCameraCapabilities(); 498 break; 499 case MSG_REQUEST_CONNECTION_DATA_USAGE: 500 onRequestConnectionDataUsage(); 501 break; 502 case MSG_SET_PAUSE_IMAGE: 503 onSetPauseImage((String) msg.obj); 504 break; 505 default: 506 break; 507 } 508 } 509 } 510 511 /** 512 * IVideoProvider stub implementation. 513 */ 514 private final class VideoProviderBinder extends IVideoProvider.Stub { 515 public void setVideoCallback(IBinder videoCallbackBinder) { 516 mMessageHandler.obtainMessage( 517 MSG_SET_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget(); 518 } 519 520 public void setCamera(String cameraId) { 521 mMessageHandler.obtainMessage(MSG_SET_CAMERA, cameraId).sendToTarget(); 522 } 523 524 public void setPreviewSurface(Surface surface) { 525 mMessageHandler.obtainMessage(MSG_SET_PREVIEW_SURFACE, surface).sendToTarget(); 526 } 527 528 public void setDisplaySurface(Surface surface) { 529 mMessageHandler.obtainMessage(MSG_SET_DISPLAY_SURFACE, surface).sendToTarget(); 530 } 531 532 public void setDeviceOrientation(int rotation) { 533 mMessageHandler.obtainMessage( 534 MSG_SET_DEVICE_ORIENTATION, rotation, 0).sendToTarget(); 535 } 536 537 public void setZoom(float value) { 538 mMessageHandler.obtainMessage(MSG_SET_ZOOM, value).sendToTarget(); 539 } 540 541 public void sendSessionModifyRequest(VideoProfile requestProfile) { 542 mMessageHandler.obtainMessage( 543 MSG_SEND_SESSION_MODIFY_REQUEST, requestProfile).sendToTarget(); 544 } 545 546 public void sendSessionModifyResponse(VideoProfile responseProfile) { 547 mMessageHandler.obtainMessage( 548 MSG_SEND_SESSION_MODIFY_RESPONSE, responseProfile).sendToTarget(); 549 } 550 551 public void requestCameraCapabilities() { 552 mMessageHandler.obtainMessage(MSG_REQUEST_CAMERA_CAPABILITIES).sendToTarget(); 553 } 554 555 public void requestCallDataUsage() { 556 mMessageHandler.obtainMessage(MSG_REQUEST_CONNECTION_DATA_USAGE).sendToTarget(); 557 } 558 559 public void setPauseImage(String uri) { 560 mMessageHandler.obtainMessage(MSG_SET_PAUSE_IMAGE, uri).sendToTarget(); 561 } 562 } 563 564 public VideoProvider() { 565 mBinder = new VideoProvider.VideoProviderBinder(); 566 } 567 568 /** 569 * Returns binder object which can be used across IPC methods. 570 * @hide 571 */ 572 public final IVideoProvider getInterface() { 573 return mBinder; 574 } 575 576 /** 577 * Sets the camera to be used for video recording in a video connection. 578 * 579 * @param cameraId The id of the camera. 580 */ 581 public abstract void onSetCamera(String cameraId); 582 583 /** 584 * Sets the surface to be used for displaying a preview of what the user's camera is 585 * currently capturing. When video transmission is enabled, this is the video signal which 586 * is sent to the remote device. 587 * 588 * @param surface The surface. 589 */ 590 public abstract void onSetPreviewSurface(Surface surface); 591 592 /** 593 * Sets the surface to be used for displaying the video received from the remote device. 594 * 595 * @param surface The surface. 596 */ 597 public abstract void onSetDisplaySurface(Surface surface); 598 599 /** 600 * Sets the device orientation, in degrees. Assumes that a standard portrait orientation of 601 * the device is 0 degrees. 602 * 603 * @param rotation The device orientation, in degrees. 604 */ 605 public abstract void onSetDeviceOrientation(int rotation); 606 607 /** 608 * Sets camera zoom ratio. 609 * 610 * @param value The camera zoom ratio. 611 */ 612 public abstract void onSetZoom(float value); 613 614 /** 615 * Issues a request to modify the properties of the current session. The request is 616 * sent to the remote device where it it handled by the In-Call UI. 617 * Some examples of session modification requests: upgrade connection from audio to video, 618 * downgrade connection from video to audio, pause video. 619 * 620 * @param requestProfile The requested connection video properties. 621 */ 622 public abstract void onSendSessionModifyRequest(VideoProfile requestProfile); 623 624 /**te 625 * Provides a response to a request to change the current connection session video 626 * properties. 627 * This is in response to a request the InCall UI has received via the InCall UI. 628 * 629 * @param responseProfile The response connection video properties. 630 */ 631 public abstract void onSendSessionModifyResponse(VideoProfile responseProfile); 632 633 /** 634 * Issues a request to the video provider to retrieve the camera capabilities. 635 * Camera capabilities are reported back to the caller via the In-Call UI. 636 */ 637 public abstract void onRequestCameraCapabilities(); 638 639 /** 640 * Issues a request to the video telephony framework to retrieve the cumulative data usage 641 * for the current connection. Data usage is reported back to the caller via the 642 * InCall UI. 643 */ 644 public abstract void onRequestConnectionDataUsage(); 645 646 /** 647 * Provides the video telephony framework with the URI of an image to be displayed to remote 648 * devices when the video signal is paused. 649 * 650 * @param uri URI of image to display. 651 */ 652 public abstract void onSetPauseImage(String uri); 653 654 /** 655 * Invokes callback method defined in In-Call UI. 656 * 657 * @param videoProfile The requested video connection profile. 658 */ 659 public void receiveSessionModifyRequest(VideoProfile videoProfile) { 660 if (mVideoCallback != null) { 661 try { 662 mVideoCallback.receiveSessionModifyRequest(videoProfile); 663 } catch (RemoteException ignored) { 664 } 665 } 666 } 667 668 /** 669 * Invokes callback method defined in In-Call UI. 670 * 671 * @param status Status of the session modify request. Valid values are 672 * {@link VideoProvider#SESSION_MODIFY_REQUEST_SUCCESS}, 673 * {@link VideoProvider#SESSION_MODIFY_REQUEST_FAIL}, 674 * {@link VideoProvider#SESSION_MODIFY_REQUEST_INVALID} 675 * @param requestedProfile The original request which was sent to the remote device. 676 * @param responseProfile The actual profile changes made by the remote device. 677 */ 678 public void receiveSessionModifyResponse(int status, 679 VideoProfile requestedProfile, VideoProfile responseProfile) { 680 if (mVideoCallback != null) { 681 try { 682 mVideoCallback.receiveSessionModifyResponse( 683 status, requestedProfile, responseProfile); 684 } catch (RemoteException ignored) { 685 } 686 } 687 } 688 689 /** 690 * Invokes callback method defined in In-Call UI. 691 * 692 * Valid values are: {@link VideoProvider#SESSION_EVENT_RX_PAUSE}, 693 * {@link VideoProvider#SESSION_EVENT_RX_RESUME}, 694 * {@link VideoProvider#SESSION_EVENT_TX_START}, 695 * {@link VideoProvider#SESSION_EVENT_TX_STOP} 696 * 697 * @param event The event. 698 */ 699 public void handleCallSessionEvent(int event) { 700 if (mVideoCallback != null) { 701 try { 702 mVideoCallback.handleCallSessionEvent(event); 703 } catch (RemoteException ignored) { 704 } 705 } 706 } 707 708 /** 709 * Invokes callback method defined in In-Call UI. 710 * 711 * @param width The updated peer video width. 712 * @param height The updated peer video height. 713 */ 714 public void changePeerDimensions(int width, int height) { 715 if (mVideoCallback != null) { 716 try { 717 mVideoCallback.changePeerDimensions(width, height); 718 } catch (RemoteException ignored) { 719 } 720 } 721 } 722 723 /** 724 * Invokes callback method defined in In-Call UI. 725 * 726 * @param dataUsage The updated data usage. 727 */ 728 public void changeCallDataUsage(long dataUsage) { 729 if (mVideoCallback != null) { 730 try { 731 mVideoCallback.changeCallDataUsage(dataUsage); 732 } catch (RemoteException ignored) { 733 } 734 } 735 } 736 737 /** 738 * Invokes callback method defined in In-Call UI. 739 * 740 * @param cameraCapabilities The changed camera capabilities. 741 */ 742 public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) { 743 if (mVideoCallback != null) { 744 try { 745 mVideoCallback.changeCameraCapabilities(cameraCapabilities); 746 } catch (RemoteException ignored) { 747 } 748 } 749 } 750 751 /** 752 * Invokes callback method defined in In-Call UI. 753 * 754 * @param videoQuality The updated video quality. 755 */ 756 public void changeVideoQuality(int videoQuality) { 757 if (mVideoCallback != null) { 758 try { 759 mVideoCallback.changeVideoQuality(videoQuality); 760 } catch (RemoteException ignored) { 761 } 762 } 763 } 764 } 765 766 private final Listener mConnectionDeathListener = new Listener() { 767 @Override 768 public void onDestroyed(Connection c) { 769 if (mConferenceables.remove(c)) { 770 fireOnConferenceableConnectionsChanged(); 771 } 772 } 773 }; 774 775 private final Conference.Listener mConferenceDeathListener = new Conference.Listener() { 776 @Override 777 public void onDestroyed(Conference c) { 778 if (mConferenceables.remove(c)) { 779 fireOnConferenceableConnectionsChanged(); 780 } 781 } 782 }; 783 784 /** 785 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is 786 * load factor before resizing, 1 means we only expect a single thread to 787 * access the map so make only a single shard 788 */ 789 private final Set<Listener> mListeners = Collections.newSetFromMap( 790 new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1)); 791 private final List<IConferenceable> mConferenceables = new ArrayList<>(); 792 private final List<IConferenceable> mUnmodifiableConferenceables = 793 Collections.unmodifiableList(mConferenceables); 794 795 private int mState = STATE_NEW; 796 private AudioState mAudioState; 797 private Uri mAddress; 798 private int mAddressPresentation; 799 private String mCallerDisplayName; 800 private int mCallerDisplayNamePresentation; 801 private boolean mRingbackRequested = false; 802 private int mConnectionCapabilities; 803 private VideoProvider mVideoProvider; 804 private boolean mAudioModeIsVoip; 805 private StatusHints mStatusHints; 806 private int mVideoState; 807 private DisconnectCause mDisconnectCause; 808 private Conference mConference; 809 private ConnectionService mConnectionService; 810 private int mCallSubstate; 811 812 /** 813 * Create a new Connection. 814 */ 815 public Connection() {} 816 817 /** 818 * @return The address (e.g., phone number) to which this Connection is currently communicating. 819 */ 820 public final Uri getAddress() { 821 return mAddress; 822 } 823 824 /** 825 * @return The presentation requirements for the address. 826 * See {@link TelecomManager} for valid values. 827 */ 828 public final int getAddressPresentation() { 829 return mAddressPresentation; 830 } 831 832 /** 833 * @return The caller display name (CNAP). 834 */ 835 public final String getCallerDisplayName() { 836 return mCallerDisplayName; 837 } 838 839 /** 840 * @return The presentation requirements for the handle. 841 * See {@link TelecomManager} for valid values. 842 */ 843 public final int getCallerDisplayNamePresentation() { 844 return mCallerDisplayNamePresentation; 845 } 846 847 /** 848 * @return The state of this Connection. 849 */ 850 public final int getState() { 851 return mState; 852 } 853 854 /** 855 * Returns the video state of the connection. 856 * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY}, 857 * {@link VideoProfile.VideoState#BIDIRECTIONAL}, 858 * {@link VideoProfile.VideoState#TX_ENABLED}, 859 * {@link VideoProfile.VideoState#RX_ENABLED}. 860 * 861 * @return The video state of the connection. 862 * @hide 863 */ 864 public final int getVideoState() { 865 return mVideoState; 866 } 867 868 /** 869 * Returns the call substate of the call. 870 * Valid values: {@link Connection#SUBSTATE_NONE}, 871 * {@link Connection#SUBSTATE_AUDIO_CONNECTED_SUSPENDED}, 872 * {@link Connection#SUBSTATE_VIDEO_CONNECTED_SUSPENDED}, 873 * {@link Connection#SUBSTATE_AVP_RETRY}, 874 * {@link Connection#SUBSTATE_MEDIA_PAUSED}. 875 * 876 * @param callSubstate The new call substate. 877 * @hide 878 */ 879 public final int getCallSubstate() { 880 return mCallSubstate; 881 } 882 883 /** 884 * @return The audio state of the connection, describing how its audio is currently 885 * being routed by the system. This is {@code null} if this Connection 886 * does not directly know about its audio state. 887 */ 888 public final AudioState getAudioState() { 889 return mAudioState; 890 } 891 892 /** 893 * @return The conference that this connection is a part of. Null if it is not part of any 894 * conference. 895 */ 896 public final Conference getConference() { 897 return mConference; 898 } 899 900 /** 901 * Returns whether this connection is requesting that the system play a ringback tone 902 * on its behalf. 903 */ 904 public final boolean isRingbackRequested() { 905 return mRingbackRequested; 906 } 907 908 /** 909 * @return True if the connection's audio mode is VOIP. 910 */ 911 public final boolean getAudioModeIsVoip() { 912 return mAudioModeIsVoip; 913 } 914 915 /** 916 * @return The status hints for this connection. 917 */ 918 public final StatusHints getStatusHints() { 919 return mStatusHints; 920 } 921 922 /** 923 * Assign a listener to be notified of state changes. 924 * 925 * @param l A listener. 926 * @return This Connection. 927 * 928 * @hide 929 */ 930 public final Connection addConnectionListener(Listener l) { 931 mListeners.add(l); 932 return this; 933 } 934 935 /** 936 * Remove a previously assigned listener that was being notified of state changes. 937 * 938 * @param l A Listener. 939 * @return This Connection. 940 * 941 * @hide 942 */ 943 public final Connection removeConnectionListener(Listener l) { 944 if (l != null) { 945 mListeners.remove(l); 946 } 947 return this; 948 } 949 950 /** 951 * @return The {@link DisconnectCause} for this connection. 952 */ 953 public final DisconnectCause getDisconnectCause() { 954 return mDisconnectCause; 955 } 956 957 /** 958 * Inform this Connection that the state of its audio output has been changed externally. 959 * 960 * @param state The new audio state. 961 * @hide 962 */ 963 final void setAudioState(AudioState state) { 964 checkImmutable(); 965 Log.d(this, "setAudioState %s", state); 966 mAudioState = state; 967 onAudioStateChanged(state); 968 } 969 970 /** 971 * @param state An integer value of a {@code STATE_*} constant. 972 * @return A string representation of the value. 973 */ 974 public static String stateToString(int state) { 975 switch (state) { 976 case STATE_INITIALIZING: 977 return "STATE_INITIALIZING"; 978 case STATE_NEW: 979 return "STATE_NEW"; 980 case STATE_RINGING: 981 return "STATE_RINGING"; 982 case STATE_DIALING: 983 return "STATE_DIALING"; 984 case STATE_ACTIVE: 985 return "STATE_ACTIVE"; 986 case STATE_HOLDING: 987 return "STATE_HOLDING"; 988 case STATE_DISCONNECTED: 989 return "DISCONNECTED"; 990 default: 991 Log.wtf(Connection.class, "Unknown state %d", state); 992 return "UNKNOWN"; 993 } 994 } 995 996 /** 997 * Returns the connection's capabilities, as a bit mask of the {@code CAPABILITY_*} constants. 998 */ 999 public final int getConnectionCapabilities() { 1000 return mConnectionCapabilities; 1001 } 1002 1003 /** 1004 * Sets the value of the {@link #getAddress()} property. 1005 * 1006 * @param address The new address. 1007 * @param presentation The presentation requirements for the address. 1008 * See {@link TelecomManager} for valid values. 1009 */ 1010 public final void setAddress(Uri address, int presentation) { 1011 checkImmutable(); 1012 Log.d(this, "setAddress %s", address); 1013 mAddress = address; 1014 mAddressPresentation = presentation; 1015 for (Listener l : mListeners) { 1016 l.onAddressChanged(this, address, presentation); 1017 } 1018 } 1019 1020 /** 1021 * Sets the caller display name (CNAP). 1022 * 1023 * @param callerDisplayName The new display name. 1024 * @param presentation The presentation requirements for the handle. 1025 * See {@link TelecomManager} for valid values. 1026 */ 1027 public final void setCallerDisplayName(String callerDisplayName, int presentation) { 1028 checkImmutable(); 1029 Log.d(this, "setCallerDisplayName %s", callerDisplayName); 1030 mCallerDisplayName = callerDisplayName; 1031 mCallerDisplayNamePresentation = presentation; 1032 for (Listener l : mListeners) { 1033 l.onCallerDisplayNameChanged(this, callerDisplayName, presentation); 1034 } 1035 } 1036 1037 /** 1038 * Set the video state for the connection. 1039 * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY}, 1040 * {@link VideoProfile.VideoState#BIDIRECTIONAL}, 1041 * {@link VideoProfile.VideoState#TX_ENABLED}, 1042 * {@link VideoProfile.VideoState#RX_ENABLED}. 1043 * 1044 * @param videoState The new video state. 1045 * @hide 1046 */ 1047 public final void setVideoState(int videoState) { 1048 checkImmutable(); 1049 Log.d(this, "setVideoState %d", videoState); 1050 mVideoState = videoState; 1051 for (Listener l : mListeners) { 1052 l.onVideoStateChanged(this, mVideoState); 1053 } 1054 } 1055 1056 /** 1057 * Set the call substate for the connection. 1058 * Valid values: {@link Connection#SUBSTATE_NONE}, 1059 * {@link Connection#SUBSTATE_AUDIO_CONNECTED_SUSPENDED}, 1060 * {@link Connection#SUBSTATE_VIDEO_CONNECTED_SUSPENDED}, 1061 * {@link Connection#SUBSTATE_AVP_RETRY}, 1062 * {@link Connection#SUBSTATE_MEDIA_PAUSED}. 1063 * 1064 * @param callSubstate The new call substate. 1065 * @hide 1066 */ 1067 public final void setCallSubstate(int callSubstate) { 1068 Log.d(this, "setCallSubstate %d", callSubstate); 1069 mCallSubstate = callSubstate; 1070 for (Listener l : mListeners) { 1071 l.onCallSubstateChanged(this, mCallSubstate); 1072 } 1073 } 1074 1075 /** 1076 * Sets state to active (e.g., an ongoing connection where two or more parties can actively 1077 * communicate). 1078 */ 1079 public final void setActive() { 1080 checkImmutable(); 1081 setRingbackRequested(false); 1082 setState(STATE_ACTIVE); 1083 } 1084 1085 /** 1086 * Sets state to ringing (e.g., an inbound ringing connection). 1087 */ 1088 public final void setRinging() { 1089 checkImmutable(); 1090 setState(STATE_RINGING); 1091 } 1092 1093 /** 1094 * Sets state to initializing (this Connection is not yet ready to be used). 1095 */ 1096 public final void setInitializing() { 1097 checkImmutable(); 1098 setState(STATE_INITIALIZING); 1099 } 1100 1101 /** 1102 * Sets state to initialized (the Connection has been set up and is now ready to be used). 1103 */ 1104 public final void setInitialized() { 1105 checkImmutable(); 1106 setState(STATE_NEW); 1107 } 1108 1109 /** 1110 * Sets state to dialing (e.g., dialing an outbound connection). 1111 */ 1112 public final void setDialing() { 1113 checkImmutable(); 1114 setState(STATE_DIALING); 1115 } 1116 1117 /** 1118 * Sets state to be on hold. 1119 */ 1120 public final void setOnHold() { 1121 checkImmutable(); 1122 setState(STATE_HOLDING); 1123 } 1124 1125 /** 1126 * Sets the video connection provider. 1127 * @param videoProvider The video provider. 1128 * @hide 1129 */ 1130 public final void setVideoProvider(VideoProvider videoProvider) { 1131 checkImmutable(); 1132 mVideoProvider = videoProvider; 1133 for (Listener l : mListeners) { 1134 l.onVideoProviderChanged(this, videoProvider); 1135 } 1136 } 1137 1138 public final VideoProvider getVideoProvider() { 1139 return mVideoProvider; 1140 } 1141 1142 /** 1143 * Sets state to disconnected. 1144 * 1145 * @param disconnectCause The reason for the disconnection, as specified by 1146 * {@link DisconnectCause}. 1147 */ 1148 public final void setDisconnected(DisconnectCause disconnectCause) { 1149 checkImmutable(); 1150 mDisconnectCause = disconnectCause; 1151 setState(STATE_DISCONNECTED); 1152 Log.d(this, "Disconnected with cause %s", disconnectCause); 1153 for (Listener l : mListeners) { 1154 l.onDisconnected(this, disconnectCause); 1155 } 1156 } 1157 1158 /** 1159 * Informs listeners that this {@code Connection} is in a post-dial wait state. This is done 1160 * when (a) the {@code Connection} is issuing a DTMF sequence; (b) it has encountered a "wait" 1161 * character; and (c) it wishes to inform the In-Call app that it is waiting for the end-user 1162 * to send an {@link #onPostDialContinue(boolean)} signal. 1163 * 1164 * @param remaining The DTMF character sequence remaining to be emitted once the 1165 * {@link #onPostDialContinue(boolean)} is received, including any "wait" characters 1166 * that remaining sequence may contain. 1167 */ 1168 public final void setPostDialWait(String remaining) { 1169 checkImmutable(); 1170 for (Listener l : mListeners) { 1171 l.onPostDialWait(this, remaining); 1172 } 1173 } 1174 1175 /** 1176 * Informs listeners that this {@code Connection} has processed a character in the post-dial 1177 * started state. This is done when (a) the {@code Connection} is issuing a DTMF sequence; 1178 * (b) it has encountered a "wait" character; and (c) it wishes to signal Telecom to play 1179 * the corresponding DTMF tone locally. 1180 * 1181 * @param nextChar The DTMF character that was just processed by the {@code Connection}. 1182 * 1183 * @hide 1184 */ 1185 public final void setNextPostDialWaitChar(char nextChar) { 1186 checkImmutable(); 1187 for (Listener l : mListeners) { 1188 l.onPostDialChar(this, nextChar); 1189 } 1190 } 1191 1192 /** 1193 * Requests that the framework play a ringback tone. This is to be invoked by implementations 1194 * that do not play a ringback tone themselves in the connection's audio stream. 1195 * 1196 * @param ringback Whether the ringback tone is to be played. 1197 */ 1198 public final void setRingbackRequested(boolean ringback) { 1199 checkImmutable(); 1200 if (mRingbackRequested != ringback) { 1201 mRingbackRequested = ringback; 1202 for (Listener l : mListeners) { 1203 l.onRingbackRequested(this, ringback); 1204 } 1205 } 1206 } 1207 1208 /** 1209 * Sets the connection's capabilities as a bit mask of the {@code CAPABILITY_*} constants. 1210 * 1211 * @param connectionCapabilities The new connection capabilities. 1212 */ 1213 public final void setConnectionCapabilities(int connectionCapabilities) { 1214 checkImmutable(); 1215 if (mConnectionCapabilities != connectionCapabilities) { 1216 mConnectionCapabilities = connectionCapabilities; 1217 for (Listener l : mListeners) { 1218 l.onConnectionCapabilitiesChanged(this, mConnectionCapabilities); 1219 } 1220 } 1221 } 1222 1223 /** 1224 * Tears down the Connection object. 1225 */ 1226 public final void destroy() { 1227 for (Listener l : mListeners) { 1228 l.onDestroyed(this); 1229 } 1230 } 1231 1232 /** 1233 * Requests that the framework use VOIP audio mode for this connection. 1234 * 1235 * @param isVoip True if the audio mode is VOIP. 1236 */ 1237 public final void setAudioModeIsVoip(boolean isVoip) { 1238 checkImmutable(); 1239 mAudioModeIsVoip = isVoip; 1240 for (Listener l : mListeners) { 1241 l.onAudioModeIsVoipChanged(this, isVoip); 1242 } 1243 } 1244 1245 /** 1246 * Sets the label and icon status to display in the in-call UI. 1247 * 1248 * @param statusHints The status label and icon to set. 1249 */ 1250 public final void setStatusHints(StatusHints statusHints) { 1251 checkImmutable(); 1252 mStatusHints = statusHints; 1253 for (Listener l : mListeners) { 1254 l.onStatusHintsChanged(this, statusHints); 1255 } 1256 } 1257 1258 /** 1259 * Sets the connections with which this connection can be conferenced. 1260 * 1261 * @param conferenceableConnections The set of connections this connection can conference with. 1262 */ 1263 public final void setConferenceableConnections(List<Connection> conferenceableConnections) { 1264 checkImmutable(); 1265 clearConferenceableList(); 1266 for (Connection c : conferenceableConnections) { 1267 // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a 1268 // small amount of items here. 1269 if (!mConferenceables.contains(c)) { 1270 c.addConnectionListener(mConnectionDeathListener); 1271 mConferenceables.add(c); 1272 } 1273 } 1274 fireOnConferenceableConnectionsChanged(); 1275 } 1276 1277 /** 1278 * Similar to {@link #setConferenceableConnections(java.util.List)}, sets a list of connections 1279 * or conferences with which this connection can be conferenced. 1280 * 1281 * @param conferenceables The conferenceables. 1282 */ 1283 public final void setConferenceables(List<IConferenceable> conferenceables) { 1284 clearConferenceableList(); 1285 for (IConferenceable c : conferenceables) { 1286 // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a 1287 // small amount of items here. 1288 if (!mConferenceables.contains(c)) { 1289 if (c instanceof Connection) { 1290 Connection connection = (Connection) c; 1291 connection.addConnectionListener(mConnectionDeathListener); 1292 } else if (c instanceof Conference) { 1293 Conference conference = (Conference) c; 1294 conference.addListener(mConferenceDeathListener); 1295 } 1296 mConferenceables.add(c); 1297 } 1298 } 1299 fireOnConferenceableConnectionsChanged(); 1300 } 1301 1302 /** 1303 * Returns the connections or conferences with which this connection can be conferenced. 1304 */ 1305 public final List<IConferenceable> getConferenceables() { 1306 return mUnmodifiableConferenceables; 1307 } 1308 1309 /* 1310 * @hide 1311 */ 1312 public final void setConnectionService(ConnectionService connectionService) { 1313 checkImmutable(); 1314 if (mConnectionService != null) { 1315 Log.e(this, new Exception(), "Trying to set ConnectionService on a connection " + 1316 "which is already associated with another ConnectionService."); 1317 } else { 1318 mConnectionService = connectionService; 1319 } 1320 } 1321 1322 /** 1323 * @hide 1324 */ 1325 public final void unsetConnectionService(ConnectionService connectionService) { 1326 if (mConnectionService != connectionService) { 1327 Log.e(this, new Exception(), "Trying to remove ConnectionService from a Connection " + 1328 "that does not belong to the ConnectionService."); 1329 } else { 1330 mConnectionService = null; 1331 } 1332 } 1333 1334 /** 1335 * @hide 1336 */ 1337 public final ConnectionService getConnectionService() { 1338 return mConnectionService; 1339 } 1340 1341 /** 1342 * Sets the conference that this connection is a part of. This will fail if the connection is 1343 * already part of a conference. {@link #resetConference} to un-set the conference first. 1344 * 1345 * @param conference The conference. 1346 * @return {@code true} if the conference was successfully set. 1347 * @hide 1348 */ 1349 public final boolean setConference(Conference conference) { 1350 checkImmutable(); 1351 // We check to see if it is already part of another conference. 1352 if (mConference == null) { 1353 mConference = conference; 1354 if (mConnectionService != null && mConnectionService.containsConference(conference)) { 1355 fireConferenceChanged(); 1356 } 1357 return true; 1358 } 1359 return false; 1360 } 1361 1362 /** 1363 * Resets the conference that this connection is a part of. 1364 * @hide 1365 */ 1366 public final void resetConference() { 1367 if (mConference != null) { 1368 Log.d(this, "Conference reset"); 1369 mConference = null; 1370 fireConferenceChanged(); 1371 } 1372 } 1373 1374 /** 1375 * Notifies this Connection that the {@link #getAudioState()} property has a new value. 1376 * 1377 * @param state The new connection audio state. 1378 */ 1379 public void onAudioStateChanged(AudioState state) {} 1380 1381 /** 1382 * Notifies this Connection of an internal state change. This method is called after the 1383 * state is changed. 1384 * 1385 * @param state The new state, one of the {@code STATE_*} constants. 1386 */ 1387 public void onStateChanged(int state) {} 1388 1389 /** 1390 * Notifies this Connection of a request to play a DTMF tone. 1391 * 1392 * @param c A DTMF character. 1393 */ 1394 public void onPlayDtmfTone(char c) {} 1395 1396 /** 1397 * Notifies this Connection of a request to stop any currently playing DTMF tones. 1398 */ 1399 public void onStopDtmfTone() {} 1400 1401 /** 1402 * Notifies this Connection of a request to disconnect. 1403 */ 1404 public void onDisconnect() {} 1405 1406 /** 1407 * Notifies this Connection of a request to disconnect a participant of the conference managed 1408 * by the connection. 1409 * 1410 * @param endpoint the {@link Uri} of the participant to disconnect. 1411 * @hide 1412 */ 1413 public void onDisconnectConferenceParticipant(Uri endpoint) {} 1414 1415 /** 1416 * Notifies this Connection of a request to separate from its parent conference. 1417 */ 1418 public void onSeparate() {} 1419 1420 /** 1421 * Notifies this Connection of a request to abort. 1422 */ 1423 public void onAbort() {} 1424 1425 /** 1426 * Notifies this Connection of a request to hold. 1427 */ 1428 public void onHold() {} 1429 1430 /** 1431 * Notifies this Connection of a request to exit a hold state. 1432 */ 1433 public void onUnhold() {} 1434 1435 /** 1436 * Notifies this Connection, which is in {@link #STATE_RINGING}, of 1437 * a request to accept. 1438 * 1439 * @param videoState The video state in which to answer the connection. 1440 * @hide 1441 */ 1442 public void onAnswer(int videoState) {} 1443 1444 /** 1445 * Notifies this Connection, which is in {@link #STATE_RINGING}, of 1446 * a request to accept. 1447 */ 1448 public void onAnswer() { 1449 onAnswer(VideoProfile.VideoState.AUDIO_ONLY); 1450 } 1451 1452 /** 1453 * Notifies this Connection, which is in {@link #STATE_RINGING}, of 1454 * a request to reject. 1455 */ 1456 public void onReject() {} 1457 1458 /** 1459 * Notifies this Connection whether the user wishes to proceed with the post-dial DTMF codes. 1460 */ 1461 public void onPostDialContinue(boolean proceed) {} 1462 1463 static String toLogSafePhoneNumber(String number) { 1464 // For unknown number, log empty string. 1465 if (number == null) { 1466 return ""; 1467 } 1468 1469 if (PII_DEBUG) { 1470 // When PII_DEBUG is true we emit PII. 1471 return number; 1472 } 1473 1474 // Do exactly same thing as Uri#toSafeString() does, which will enable us to compare 1475 // sanitized phone numbers. 1476 StringBuilder builder = new StringBuilder(); 1477 for (int i = 0; i < number.length(); i++) { 1478 char c = number.charAt(i); 1479 if (c == '-' || c == '@' || c == '.') { 1480 builder.append(c); 1481 } else { 1482 builder.append('x'); 1483 } 1484 } 1485 return builder.toString(); 1486 } 1487 1488 private void setState(int state) { 1489 checkImmutable(); 1490 if (mState == STATE_DISCONNECTED && mState != state) { 1491 Log.d(this, "Connection already DISCONNECTED; cannot transition out of this state."); 1492 return; 1493 } 1494 if (mState != state) { 1495 Log.d(this, "setState: %s", stateToString(state)); 1496 mState = state; 1497 onStateChanged(state); 1498 for (Listener l : mListeners) { 1499 l.onStateChanged(this, state); 1500 } 1501 } 1502 } 1503 1504 private static class FailureSignalingConnection extends Connection { 1505 private boolean mImmutable = false; 1506 public FailureSignalingConnection(DisconnectCause disconnectCause) { 1507 setDisconnected(disconnectCause); 1508 mImmutable = true; 1509 } 1510 1511 public void checkImmutable() { 1512 if (mImmutable) { 1513 throw new UnsupportedOperationException("Connection is immutable"); 1514 } 1515 } 1516 } 1517 1518 /** 1519 * Return a {@code Connection} which represents a failed connection attempt. The returned 1520 * {@code Connection} will have a {@link android.telecom.DisconnectCause} and as specified, 1521 * and a {@link #getState()} of {@link #STATE_DISCONNECTED}. 1522 * <p> 1523 * The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate, 1524 * so users of this method need not maintain a reference to its return value to destroy it. 1525 * 1526 * @param disconnectCause The disconnect cause, ({@see android.telecomm.DisconnectCause}). 1527 * @return A {@code Connection} which indicates failure. 1528 */ 1529 public static Connection createFailedConnection(DisconnectCause disconnectCause) { 1530 return new FailureSignalingConnection(disconnectCause); 1531 } 1532 1533 /** 1534 * Override to throw an {@link UnsupportedOperationException} if this {@code Connection} is 1535 * not intended to be mutated, e.g., if it is a marker for failure. Only for framework use; 1536 * this should never be un-@hide-den. 1537 * 1538 * @hide 1539 */ 1540 public void checkImmutable() {} 1541 1542 /** 1543 * Return a {@code Connection} which represents a canceled connection attempt. The returned 1544 * {@code Connection} will have state {@link #STATE_DISCONNECTED}, and cannot be moved out of 1545 * that state. This connection should not be used for anything, and no other 1546 * {@code Connection}s should be attempted. 1547 * <p> 1548 * so users of this method need not maintain a reference to its return value to destroy it. 1549 * 1550 * @return A {@code Connection} which indicates that the underlying connection should 1551 * be canceled. 1552 */ 1553 public static Connection createCanceledConnection() { 1554 return new FailureSignalingConnection(new DisconnectCause(DisconnectCause.CANCELED)); 1555 } 1556 1557 private final void fireOnConferenceableConnectionsChanged() { 1558 for (Listener l : mListeners) { 1559 l.onConferenceablesChanged(this, getConferenceables()); 1560 } 1561 } 1562 1563 private final void fireConferenceChanged() { 1564 for (Listener l : mListeners) { 1565 l.onConferenceChanged(this, mConference); 1566 } 1567 } 1568 1569 private final void clearConferenceableList() { 1570 for (IConferenceable c : mConferenceables) { 1571 if (c instanceof Connection) { 1572 Connection connection = (Connection) c; 1573 connection.removeConnectionListener(mConnectionDeathListener); 1574 } else if (c instanceof Conference) { 1575 Conference conference = (Conference) c; 1576 conference.removeListener(mConferenceDeathListener); 1577 } 1578 } 1579 mConferenceables.clear(); 1580 } 1581 1582 /** 1583 * Notifies listeners of a change to conference participant(s). 1584 * 1585 * @param conferenceParticipants The participants. 1586 * @hide 1587 */ 1588 protected final void updateConferenceParticipants( 1589 List<ConferenceParticipant> conferenceParticipants) { 1590 for (Listener l : mListeners) { 1591 l.onConferenceParticipantsChanged(this, conferenceParticipants); 1592 } 1593 } 1594 1595 /** 1596 * Notifies listeners that a conference call has been started. 1597 * @hide 1598 */ 1599 protected void notifyConferenceStarted() { 1600 for (Listener l : mListeners) { 1601 l.onConferenceStarted(); 1602 } 1603 } 1604} 1605