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