RemoteConnection.java revision 55b97525f0f50857f1ab0acd2608053fd0f3416c
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.IConnectionService; 20import com.android.internal.telecom.IVideoCallback; 21import com.android.internal.telecom.IVideoProvider; 22 23import android.net.Uri; 24import android.os.IBinder; 25import android.os.RemoteException; 26import android.view.Surface; 27 28import java.util.ArrayList; 29import java.util.Collections; 30import java.util.List; 31import java.util.Set; 32import java.util.concurrent.ConcurrentHashMap; 33 34/** 35 * A connection provided to a {@link ConnectionService} by another {@code ConnectionService} 36 * running in a different process. 37 * 38 * @see ConnectionService#createRemoteOutgoingConnection(PhoneAccountHandle, ConnectionRequest) 39 * @see ConnectionService#createRemoteIncomingConnection(PhoneAccountHandle, ConnectionRequest) 40 */ 41public final class RemoteConnection { 42 43 public static abstract class Callback { 44 /** 45 * Invoked when the state of this {@code RemoteConnection} has changed. See 46 * {@link #getState()}. 47 * 48 * @param connection The {@code RemoteConnection} invoking this method. 49 * @param state The new state of the {@code RemoteConnection}. 50 */ 51 public void onStateChanged(RemoteConnection connection, int state) {} 52 53 /** 54 * Invoked when this {@code RemoteConnection} is disconnected. 55 * 56 * @param connection The {@code RemoteConnection} invoking this method. 57 * @param disconnectCause The ({@see DisconnectCause}) associated with this failed 58 * connection. 59 */ 60 public void onDisconnected( 61 RemoteConnection connection, 62 DisconnectCause disconnectCause) {} 63 64 /** 65 * Invoked when this {@code RemoteConnection} is requesting ringback. See 66 * {@link #isRingbackRequested()}. 67 * 68 * @param connection The {@code RemoteConnection} invoking this method. 69 * @param ringback Whether the {@code RemoteConnection} is requesting ringback. 70 */ 71 public void onRingbackRequested(RemoteConnection connection, boolean ringback) {} 72 73 /** 74 * Indicates that the call capabilities of this {@code RemoteConnection} have changed. 75 * See {@link #getConnectionCapabilities()}. 76 * 77 * @param connection The {@code RemoteConnection} invoking this method. 78 * @param connectionCapabilities The new capabilities of the {@code RemoteConnection}. 79 */ 80 public void onConnectionCapabilitiesChanged( 81 RemoteConnection connection, 82 int connectionCapabilities) {} 83 84 /** 85 * Invoked when the post-dial sequence in the outgoing {@code Connection} has reached a 86 * pause character. This causes the post-dial signals to stop pending user confirmation. An 87 * implementation should present this choice to the user and invoke 88 * {@link RemoteConnection#postDialContinue(boolean)} when the user makes the choice. 89 * 90 * @param connection The {@code RemoteConnection} invoking this method. 91 * @param remainingPostDialSequence The post-dial characters that remain to be sent. 92 */ 93 public void onPostDialWait(RemoteConnection connection, String remainingPostDialSequence) {} 94 95 /** 96 * Invoked when the post-dial sequence in the outgoing {@code Connection} has processed 97 * a character. 98 * 99 * @param connection The {@code RemoteConnection} invoking this method. 100 * @param nextChar The character being processed. 101 */ 102 public void onPostDialChar(RemoteConnection connection, char nextChar) {} 103 104 /** 105 * Indicates that the VOIP audio status of this {@code RemoteConnection} has changed. 106 * See {@link #isVoipAudioMode()}. 107 * 108 * @param connection The {@code RemoteConnection} invoking this method. 109 * @param isVoip Whether the new audio state of the {@code RemoteConnection} is VOIP. 110 */ 111 public void onVoipAudioChanged(RemoteConnection connection, boolean isVoip) {} 112 113 /** 114 * Indicates that the status hints of this {@code RemoteConnection} have changed. See 115 * {@link #getStatusHints()} ()}. 116 * 117 * @param connection The {@code RemoteConnection} invoking this method. 118 * @param statusHints The new status hints of the {@code RemoteConnection}. 119 */ 120 public void onStatusHintsChanged(RemoteConnection connection, StatusHints statusHints) {} 121 122 /** 123 * Indicates that the address (e.g., phone number) of this {@code RemoteConnection} has 124 * changed. See {@link #getAddress()} and {@link #getAddressPresentation()}. 125 * 126 * @param connection The {@code RemoteConnection} invoking this method. 127 * @param address The new address of the {@code RemoteConnection}. 128 * @param presentation The presentation requirements for the address. 129 * See {@link TelecomManager} for valid values. 130 */ 131 public void onAddressChanged(RemoteConnection connection, Uri address, int presentation) {} 132 133 /** 134 * Indicates that the caller display name of this {@code RemoteConnection} has changed. 135 * See {@link #getCallerDisplayName()} and {@link #getCallerDisplayNamePresentation()}. 136 * 137 * @param connection The {@code RemoteConnection} invoking this method. 138 * @param callerDisplayName The new caller display name of the {@code RemoteConnection}. 139 * @param presentation The presentation requirements for the handle. 140 * See {@link TelecomManager} for valid values. 141 */ 142 public void onCallerDisplayNameChanged( 143 RemoteConnection connection, String callerDisplayName, int presentation) {} 144 145 /** 146 * Indicates that the video state of this {@code RemoteConnection} has changed. 147 * See {@link #getVideoState()}. 148 * 149 * @param connection The {@code RemoteConnection} invoking this method. 150 * @param videoState The new video state of the {@code RemoteConnection}. 151 * @hide 152 */ 153 public void onVideoStateChanged(RemoteConnection connection, int videoState) {} 154 155 /** 156 * Indicates that the call substate of this {@code RemoteConnection} has changed. 157 * See {@link #getCallSubstate()}. 158 * 159 * @param connection The {@code RemoteConnection} invoking this method. 160 * @param callSubstate The new call substate of the {@code RemoteConnection}. 161 * @hide 162 */ 163 public void onCallSubstateChanged(RemoteConnection connection, int callSubstate) {} 164 165 /** 166 * Indicates that this {@code RemoteConnection} has been destroyed. No further requests 167 * should be made to the {@code RemoteConnection}, and references to it should be cleared. 168 * 169 * @param connection The {@code RemoteConnection} invoking this method. 170 */ 171 public void onDestroyed(RemoteConnection connection) {} 172 173 /** 174 * Indicates that the {@code RemoteConnection}s with which this {@code RemoteConnection} 175 * may be asked to create a conference has changed. 176 * 177 * @param connection The {@code RemoteConnection} invoking this method. 178 * @param conferenceableConnections The {@code RemoteConnection}s with which this 179 * {@code RemoteConnection} may be asked to create a conference. 180 */ 181 public void onConferenceableConnectionsChanged( 182 RemoteConnection connection, 183 List<RemoteConnection> conferenceableConnections) {} 184 185 /** 186 * Indicates that the {@code VideoProvider} associated with this {@code RemoteConnection} 187 * has changed. 188 * 189 * @param connection The {@code RemoteConnection} invoking this method. 190 * @param videoProvider The new {@code VideoProvider} associated with this 191 * {@code RemoteConnection}. 192 * @hide 193 */ 194 public void onVideoProviderChanged( 195 RemoteConnection connection, VideoProvider videoProvider) {} 196 197 /** 198 * Indicates that the {@code RemoteConference} that this {@code RemoteConnection} is a part 199 * of has changed. 200 * 201 * @param connection The {@code RemoteConnection} invoking this method. 202 * @param conference The {@code RemoteConference} of which this {@code RemoteConnection} is 203 * a part, which may be {@code null}. 204 */ 205 public void onConferenceChanged( 206 RemoteConnection connection, 207 RemoteConference conference) {} 208 } 209 210 /** {@hide} */ 211 public static class VideoProvider { 212 213 public abstract static class Listener { 214 public void onReceiveSessionModifyRequest( 215 VideoProvider videoProvider, 216 VideoProfile videoProfile) {} 217 218 public void onReceiveSessionModifyResponse( 219 VideoProvider videoProvider, 220 int status, 221 VideoProfile requestedProfile, 222 VideoProfile responseProfile) {} 223 224 public void onHandleCallSessionEvent(VideoProvider videoProvider, int event) {} 225 226 public void onPeerDimensionsChanged(VideoProvider videoProvider, int width, int height) {} 227 228 public void onCallDataUsageChanged(VideoProvider videoProvider, long dataUsage) {} 229 230 public void onCameraCapabilitiesChanged( 231 VideoProvider videoProvider, 232 CameraCapabilities cameraCapabilities) {} 233 234 public void onVideoQualityChanged(VideoProvider videoProvider, int videoQuality) {} 235 } 236 237 private final IVideoCallback mVideoCallbackDelegate = new IVideoCallback() { 238 @Override 239 public void receiveSessionModifyRequest(VideoProfile videoProfile) { 240 for (Listener l : mListeners) { 241 l.onReceiveSessionModifyRequest(VideoProvider.this, videoProfile); 242 } 243 } 244 245 @Override 246 public void receiveSessionModifyResponse(int status, VideoProfile requestedProfile, 247 VideoProfile responseProfile) { 248 for (Listener l : mListeners) { 249 l.onReceiveSessionModifyResponse( 250 VideoProvider.this, 251 status, 252 requestedProfile, 253 responseProfile); 254 } 255 } 256 257 @Override 258 public void handleCallSessionEvent(int event) { 259 for (Listener l : mListeners) { 260 l.onHandleCallSessionEvent(VideoProvider.this, event); 261 } 262 } 263 264 @Override 265 public void changePeerDimensions(int width, int height) { 266 for (Listener l : mListeners) { 267 l.onPeerDimensionsChanged(VideoProvider.this, width, height); 268 } 269 } 270 271 @Override 272 public void changeCallDataUsage(long dataUsage) { 273 for (Listener l : mListeners) { 274 l.onCallDataUsageChanged(VideoProvider.this, dataUsage); 275 } 276 } 277 278 @Override 279 public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) { 280 for (Listener l : mListeners) { 281 l.onCameraCapabilitiesChanged(VideoProvider.this, cameraCapabilities); 282 } 283 } 284 285 @Override 286 public void changeVideoQuality(int videoQuality) { 287 for (Listener l : mListeners) { 288 l.onVideoQualityChanged(VideoProvider.this, videoQuality); 289 } 290 } 291 292 @Override 293 public IBinder asBinder() { 294 return null; 295 } 296 }; 297 298 private final VideoCallbackServant mVideoCallbackServant = 299 new VideoCallbackServant(mVideoCallbackDelegate); 300 301 private final IVideoProvider mVideoProviderBinder; 302 303 /** 304 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is 305 * load factor before resizing, 1 means we only expect a single thread to 306 * access the map so make only a single shard 307 */ 308 private final Set<Listener> mListeners = Collections.newSetFromMap( 309 new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1)); 310 311 public VideoProvider(IVideoProvider videoProviderBinder) { 312 mVideoProviderBinder = videoProviderBinder; 313 try { 314 mVideoProviderBinder.setVideoCallback(mVideoCallbackServant.getStub().asBinder()); 315 } catch (RemoteException e) { 316 } 317 } 318 319 public void addListener(Listener l) { 320 mListeners.add(l); 321 } 322 323 public void removeListener(Listener l) { 324 mListeners.remove(l); 325 } 326 327 public void setCamera(String cameraId) { 328 try { 329 mVideoProviderBinder.setCamera(cameraId); 330 } catch (RemoteException e) { 331 } 332 } 333 334 public void setPreviewSurface(Surface surface) { 335 try { 336 mVideoProviderBinder.setPreviewSurface(surface); 337 } catch (RemoteException e) { 338 } 339 } 340 341 public void setDisplaySurface(Surface surface) { 342 try { 343 mVideoProviderBinder.setDisplaySurface(surface); 344 } catch (RemoteException e) { 345 } 346 } 347 348 public void setDeviceOrientation(int rotation) { 349 try { 350 mVideoProviderBinder.setDeviceOrientation(rotation); 351 } catch (RemoteException e) { 352 } 353 } 354 355 public void setZoom(float value) { 356 try { 357 mVideoProviderBinder.setZoom(value); 358 } catch (RemoteException e) { 359 } 360 } 361 362 public void sendSessionModifyRequest(VideoProfile reqProfile) { 363 try { 364 mVideoProviderBinder.sendSessionModifyRequest(reqProfile); 365 } catch (RemoteException e) { 366 } 367 } 368 369 public void sendSessionModifyResponse(VideoProfile responseProfile) { 370 try { 371 mVideoProviderBinder.sendSessionModifyResponse(responseProfile); 372 } catch (RemoteException e) { 373 } 374 } 375 376 public void requestCameraCapabilities() { 377 try { 378 mVideoProviderBinder.requestCameraCapabilities(); 379 } catch (RemoteException e) { 380 } 381 } 382 383 public void requestCallDataUsage() { 384 try { 385 mVideoProviderBinder.requestCallDataUsage(); 386 } catch (RemoteException e) { 387 } 388 } 389 390 public void setPauseImage(String uri) { 391 try { 392 mVideoProviderBinder.setPauseImage(uri); 393 } catch (RemoteException e) { 394 } 395 } 396 } 397 398 private IConnectionService mConnectionService; 399 private final String mConnectionId; 400 /** 401 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is 402 * load factor before resizing, 1 means we only expect a single thread to 403 * access the map so make only a single shard 404 */ 405 private final Set<Callback> mCallbacks = Collections.newSetFromMap( 406 new ConcurrentHashMap<Callback, Boolean>(8, 0.9f, 1)); 407 private final List<RemoteConnection> mConferenceableConnections = new ArrayList<>(); 408 private final List<RemoteConnection> mUnmodifiableconferenceableConnections = 409 Collections.unmodifiableList(mConferenceableConnections); 410 411 private int mState = Connection.STATE_NEW; 412 private DisconnectCause mDisconnectCause; 413 private boolean mRingbackRequested; 414 private boolean mConnected; 415 private int mConnectionCapabilities; 416 private int mVideoState; 417 private int mCallSubstate; 418 private VideoProvider mVideoProvider; 419 private boolean mIsVoipAudioMode; 420 private StatusHints mStatusHints; 421 private Uri mAddress; 422 private int mAddressPresentation; 423 private String mCallerDisplayName; 424 private int mCallerDisplayNamePresentation; 425 private RemoteConference mConference; 426 427 /** 428 * @hide 429 */ 430 RemoteConnection( 431 String id, 432 IConnectionService connectionService, 433 ConnectionRequest request) { 434 mConnectionId = id; 435 mConnectionService = connectionService; 436 mConnected = true; 437 mState = Connection.STATE_INITIALIZING; 438 } 439 440 /** 441 * @hide 442 */ 443 RemoteConnection(String callId, IConnectionService connectionService, 444 ParcelableConnection connection) { 445 mConnectionId = callId; 446 mConnectionService = connectionService; 447 mConnected = true; 448 mState = connection.getState(); 449 mDisconnectCause = connection.getDisconnectCause(); 450 mRingbackRequested = connection.isRingbackRequested(); 451 mConnectionCapabilities = connection.getConnectionCapabilities(); 452 mVideoState = connection.getVideoState(); 453 mVideoProvider = new RemoteConnection.VideoProvider(connection.getVideoProvider()); 454 mIsVoipAudioMode = connection.getIsVoipAudioMode(); 455 mStatusHints = connection.getStatusHints(); 456 mAddress = connection.getHandle(); 457 mAddressPresentation = connection.getHandlePresentation(); 458 mCallerDisplayName = connection.getCallerDisplayName(); 459 mCallerDisplayNamePresentation = connection.getCallerDisplayNamePresentation(); 460 mConference = null; 461 } 462 463 /** 464 * Create a RemoteConnection which is used for failed connections. Note that using it for any 465 * "real" purpose will almost certainly fail. Callers should note the failure and act 466 * accordingly (moving on to another RemoteConnection, for example) 467 * 468 * @param disconnectCause The reason for the failed connection. 469 * @hide 470 */ 471 RemoteConnection(DisconnectCause disconnectCause) { 472 mConnectionId = "NULL"; 473 mConnected = false; 474 mState = Connection.STATE_DISCONNECTED; 475 mDisconnectCause = disconnectCause; 476 } 477 478 /** 479 * Adds a callback to this {@code RemoteConnection}. 480 * 481 * @param callback A {@code Callback}. 482 */ 483 public void registerCallback(Callback callback) { 484 mCallbacks.add(callback); 485 } 486 487 /** 488 * Removes a callback from this {@code RemoteConnection}. 489 * 490 * @param callback A {@code Callback}. 491 */ 492 public void unregisterCallback(Callback callback) { 493 if (callback != null) { 494 mCallbacks.remove(callback); 495 } 496 } 497 498 /** 499 * Obtains the state of this {@code RemoteConnection}. 500 * 501 * @return A state value, chosen from the {@code STATE_*} constants. 502 */ 503 public int getState() { 504 return mState; 505 } 506 507 /** 508 * Obtains the reason why this {@code RemoteConnection} may have been disconnected. 509 * 510 * @return For a {@link Connection#STATE_DISCONNECTED} {@code RemoteConnection}, the 511 * disconnect cause expressed as a code chosen from among those declared in 512 * {@link DisconnectCause}. 513 */ 514 public DisconnectCause getDisconnectCause() { 515 return mDisconnectCause; 516 } 517 518 /** 519 * Obtains the capabilities of this {@code RemoteConnection}. 520 * 521 * @return A bitmask of the capabilities of the {@code RemoteConnection}, as defined in 522 * the {@code CAPABILITY_*} constants in class {@link Connection}. 523 */ 524 public int getConnectionCapabilities() { 525 return mConnectionCapabilities; 526 } 527 528 /** 529 * Determines if the audio mode of this {@code RemoteConnection} is VOIP. 530 * 531 * @return {@code true} if the {@code RemoteConnection}'s current audio mode is VOIP. 532 */ 533 public boolean isVoipAudioMode() { 534 return mIsVoipAudioMode; 535 } 536 537 /** 538 * Obtains status hints pertaining to this {@code RemoteConnection}. 539 * 540 * @return The current {@link StatusHints} of this {@code RemoteConnection}, 541 * or {@code null} if none have been set. 542 */ 543 public StatusHints getStatusHints() { 544 return mStatusHints; 545 } 546 547 /** 548 * Obtains the address of this {@code RemoteConnection}. 549 * 550 * @return The address (e.g., phone number) to which the {@code RemoteConnection} 551 * is currently connected. 552 */ 553 public Uri getAddress() { 554 return mAddress; 555 } 556 557 /** 558 * Obtains the presentation requirements for the address of this {@code RemoteConnection}. 559 * 560 * @return The presentation requirements for the address. See 561 * {@link TelecomManager} for valid values. 562 */ 563 public int getAddressPresentation() { 564 return mAddressPresentation; 565 } 566 567 /** 568 * Obtains the display name for this {@code RemoteConnection}'s caller. 569 * 570 * @return The display name for the caller. 571 */ 572 public CharSequence getCallerDisplayName() { 573 return mCallerDisplayName; 574 } 575 576 /** 577 * Obtains the presentation requirements for this {@code RemoteConnection}'s 578 * caller's display name. 579 * 580 * @return The presentation requirements for the caller display name. See 581 * {@link TelecomManager} for valid values. 582 */ 583 public int getCallerDisplayNamePresentation() { 584 return mCallerDisplayNamePresentation; 585 } 586 587 /** 588 * Obtains the video state of this {@code RemoteConnection}. 589 * 590 * @return The video state of the {@code RemoteConnection}. See {@link VideoProfile.VideoState}. 591 * @hide 592 */ 593 public int getVideoState() { 594 return mVideoState; 595 } 596 597 /** 598 * 599 * @return The call substate of the {@code RemoteConnection}. See 600 * @hide 601 */ 602 public int getCallSubstate() { 603 return mCallSubstate; 604 } 605 606 /** 607 * Obtains the video provider of this {@code RemoteConnection}. 608 * @return The video provider associated with this {@code RemoteConnection}. 609 * @hide 610 */ 611 public final VideoProvider getVideoProvider() { 612 return mVideoProvider; 613 } 614 615 /** 616 * Determines whether this {@code RemoteConnection} is requesting ringback. 617 * 618 * @return Whether the {@code RemoteConnection} is requesting that the framework play a 619 * ringback tone on its behalf. 620 */ 621 public boolean isRingbackRequested() { 622 return false; 623 } 624 625 /** 626 * Instructs this {@code RemoteConnection} to abort. 627 */ 628 public void abort() { 629 try { 630 if (mConnected) { 631 mConnectionService.abort(mConnectionId); 632 } 633 } catch (RemoteException ignored) { 634 } 635 } 636 637 /** 638 * Instructs this {@link Connection#STATE_RINGING} {@code RemoteConnection} to answer. 639 */ 640 public void answer() { 641 try { 642 if (mConnected) { 643 mConnectionService.answer(mConnectionId); 644 } 645 } catch (RemoteException ignored) { 646 } 647 } 648 649 /** 650 * Instructs this {@link Connection#STATE_RINGING} {@code RemoteConnection} to answer. 651 * @param videoState The video state in which to answer the call. 652 * @hide 653 */ 654 public void answer(int videoState) { 655 try { 656 if (mConnected) { 657 mConnectionService.answerVideo(mConnectionId, videoState); 658 } 659 } catch (RemoteException ignored) { 660 } 661 } 662 663 /** 664 * Instructs this {@link Connection#STATE_RINGING} {@code RemoteConnection} to reject. 665 */ 666 public void reject() { 667 try { 668 if (mConnected) { 669 mConnectionService.reject(mConnectionId); 670 } 671 } catch (RemoteException ignored) { 672 } 673 } 674 675 /** 676 * Instructs this {@code RemoteConnection} to go on hold. 677 */ 678 public void hold() { 679 try { 680 if (mConnected) { 681 mConnectionService.hold(mConnectionId); 682 } 683 } catch (RemoteException ignored) { 684 } 685 } 686 687 /** 688 * Instructs this {@link Connection#STATE_HOLDING} call to release from hold. 689 */ 690 public void unhold() { 691 try { 692 if (mConnected) { 693 mConnectionService.unhold(mConnectionId); 694 } 695 } catch (RemoteException ignored) { 696 } 697 } 698 699 /** 700 * Instructs this {@code RemoteConnection} to disconnect. 701 */ 702 public void disconnect() { 703 try { 704 if (mConnected) { 705 mConnectionService.disconnect(mConnectionId); 706 } 707 } catch (RemoteException ignored) { 708 } 709 } 710 711 /** 712 * Instructs this {@code RemoteConnection} to play a dual-tone multi-frequency signaling 713 * (DTMF) tone. 714 * 715 * Any other currently playing DTMF tone in the specified call is immediately stopped. 716 * 717 * @param digit A character representing the DTMF digit for which to play the tone. This 718 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}. 719 */ 720 public void playDtmfTone(char digit) { 721 try { 722 if (mConnected) { 723 mConnectionService.playDtmfTone(mConnectionId, digit); 724 } 725 } catch (RemoteException ignored) { 726 } 727 } 728 729 /** 730 * Instructs this {@code RemoteConnection} to stop any dual-tone multi-frequency signaling 731 * (DTMF) tone currently playing. 732 * 733 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is 734 * currently playing, this method will do nothing. 735 */ 736 public void stopDtmfTone() { 737 try { 738 if (mConnected) { 739 mConnectionService.stopDtmfTone(mConnectionId); 740 } 741 } catch (RemoteException ignored) { 742 } 743 } 744 745 /** 746 * Instructs this {@code RemoteConnection} to continue playing a post-dial DTMF string. 747 * 748 * A post-dial DTMF string is a string of digits following the first instance of either 749 * {@link TelecomManager#DTMF_CHARACTER_WAIT} or {@link TelecomManager#DTMF_CHARACTER_PAUSE}. 750 * These digits are immediately sent as DTMF tones to the recipient as soon as the 751 * connection is made. 752 * 753 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this 754 * {@code RemoteConnection} will temporarily pause playing the tones for a pre-defined period 755 * of time. 756 * 757 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this 758 * {@code RemoteConnection} will pause playing the tones and notify callbacks via 759 * {@link Callback#onPostDialWait(RemoteConnection, String)}. At this point, the in-call app 760 * should display to the user an indication of this state and an affordance to continue 761 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call 762 * app should invoke the {@link #postDialContinue(boolean)} method. 763 * 764 * @param proceed Whether or not to continue with the post-dial sequence. 765 */ 766 public void postDialContinue(boolean proceed) { 767 try { 768 if (mConnected) { 769 mConnectionService.onPostDialContinue(mConnectionId, proceed); 770 } 771 } catch (RemoteException ignored) { 772 } 773 } 774 775 /** 776 * Set the audio state of this {@code RemoteConnection}. 777 * 778 * @param state The audio state of this {@code RemoteConnection}. 779 */ 780 public void setAudioState(AudioState state) { 781 try { 782 if (mConnected) { 783 mConnectionService.onAudioStateChanged(mConnectionId, state); 784 } 785 } catch (RemoteException ignored) { 786 } 787 } 788 789 /** 790 * Obtain the {@code RemoteConnection}s with which this {@code RemoteConnection} may be 791 * successfully asked to create a conference with. 792 * 793 * @return The {@code RemoteConnection}s with which this {@code RemoteConnection} may be 794 * merged into a {@link RemoteConference}. 795 */ 796 public List<RemoteConnection> getConferenceableConnections() { 797 return mUnmodifiableconferenceableConnections; 798 } 799 800 /** 801 * Obtain the {@code RemoteConference} that this {@code RemoteConnection} may be a part 802 * of, or {@code null} if there is no such {@code RemoteConference}. 803 * 804 * @return A {@code RemoteConference} or {@code null}; 805 */ 806 public RemoteConference getConference() { 807 return mConference; 808 } 809 810 /** {@hide} */ 811 String getId() { 812 return mConnectionId; 813 } 814 815 /** {@hide} */ 816 IConnectionService getConnectionService() { 817 return mConnectionService; 818 } 819 820 /** 821 * @hide 822 */ 823 void setState(int state) { 824 if (mState != state) { 825 mState = state; 826 for (Callback c: mCallbacks) { 827 c.onStateChanged(this, state); 828 } 829 } 830 } 831 832 /** 833 * @hide 834 */ 835 void setDisconnected(DisconnectCause disconnectCause) { 836 if (mState != Connection.STATE_DISCONNECTED) { 837 mState = Connection.STATE_DISCONNECTED; 838 mDisconnectCause = disconnectCause; 839 840 for (Callback c : mCallbacks) { 841 c.onDisconnected(this, mDisconnectCause); 842 } 843 } 844 } 845 846 /** 847 * @hide 848 */ 849 void setRingbackRequested(boolean ringback) { 850 if (mRingbackRequested != ringback) { 851 mRingbackRequested = ringback; 852 for (Callback c : mCallbacks) { 853 c.onRingbackRequested(this, ringback); 854 } 855 } 856 } 857 858 /** 859 * @hide 860 */ 861 void setConnectionCapabilities(int connectionCapabilities) { 862 mConnectionCapabilities = connectionCapabilities; 863 for (Callback c : mCallbacks) { 864 c.onConnectionCapabilitiesChanged(this, connectionCapabilities); 865 } 866 } 867 868 /** 869 * @hide 870 */ 871 void setDestroyed() { 872 if (!mCallbacks.isEmpty()) { 873 // Make sure that the callbacks are notified that the call is destroyed first. 874 if (mState != Connection.STATE_DISCONNECTED) { 875 setDisconnected( 876 new DisconnectCause(DisconnectCause.ERROR, "Connection destroyed.")); 877 } 878 879 for (Callback c : mCallbacks) { 880 c.onDestroyed(this); 881 } 882 mCallbacks.clear(); 883 884 mConnected = false; 885 } 886 } 887 888 /** 889 * @hide 890 */ 891 void setPostDialWait(String remainingDigits) { 892 for (Callback c : mCallbacks) { 893 c.onPostDialWait(this, remainingDigits); 894 } 895 } 896 897 /** 898 * @hide 899 */ 900 void onPostDialChar(char nextChar) { 901 for (Callback c : mCallbacks) { 902 c.onPostDialChar(this, nextChar); 903 } 904 } 905 906 /** 907 * @hide 908 */ 909 void setVideoState(int videoState) { 910 mVideoState = videoState; 911 for (Callback c : mCallbacks) { 912 c.onVideoStateChanged(this, videoState); 913 } 914 } 915 916 /** 917 * @hide 918 */ 919 void setCallSubstate(int callSubstate) { 920 mCallSubstate = callSubstate; 921 for (Callback c : mCallbacks) { 922 c.onCallSubstateChanged(this, callSubstate); 923 } 924 } 925 926 /** 927 * @hide 928 */ 929 void setVideoProvider(VideoProvider videoProvider) { 930 mVideoProvider = videoProvider; 931 for (Callback c : mCallbacks) { 932 c.onVideoProviderChanged(this, videoProvider); 933 } 934 } 935 936 /** @hide */ 937 void setIsVoipAudioMode(boolean isVoip) { 938 mIsVoipAudioMode = isVoip; 939 for (Callback c : mCallbacks) { 940 c.onVoipAudioChanged(this, isVoip); 941 } 942 } 943 944 /** @hide */ 945 void setStatusHints(StatusHints statusHints) { 946 mStatusHints = statusHints; 947 for (Callback c : mCallbacks) { 948 c.onStatusHintsChanged(this, statusHints); 949 } 950 } 951 952 /** @hide */ 953 void setAddress(Uri address, int presentation) { 954 mAddress = address; 955 mAddressPresentation = presentation; 956 for (Callback c : mCallbacks) { 957 c.onAddressChanged(this, address, presentation); 958 } 959 } 960 961 /** @hide */ 962 void setCallerDisplayName(String callerDisplayName, int presentation) { 963 mCallerDisplayName = callerDisplayName; 964 mCallerDisplayNamePresentation = presentation; 965 for (Callback c : mCallbacks) { 966 c.onCallerDisplayNameChanged(this, callerDisplayName, presentation); 967 } 968 } 969 970 /** @hide */ 971 void setConferenceableConnections(List<RemoteConnection> conferenceableConnections) { 972 mConferenceableConnections.clear(); 973 mConferenceableConnections.addAll(conferenceableConnections); 974 for (Callback c : mCallbacks) { 975 c.onConferenceableConnectionsChanged(this, mUnmodifiableconferenceableConnections); 976 } 977 } 978 979 /** @hide */ 980 void setConference(RemoteConference conference) { 981 if (mConference != conference) { 982 mConference = conference; 983 for (Callback c : mCallbacks) { 984 c.onConferenceChanged(this, conference); 985 } 986 } 987 } 988 989 /** 990 * Create a RemoteConnection represents a failure, and which will be in 991 * {@link Connection#STATE_DISCONNECTED}. Attempting to use it for anything will almost 992 * certainly result in bad things happening. Do not do this. 993 * 994 * @return a failed {@link RemoteConnection} 995 * 996 * @hide 997 */ 998 public static RemoteConnection failure(DisconnectCause disconnectCause) { 999 return new RemoteConnection(disconnectCause); 1000 } 1001} 1002