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