RemoteConnection.java revision d7b4b81274e8a0f885be553ea8e153ea5447798d
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 this {@code RemoteConnection} has been destroyed. No further requests 157 * should be made to the {@code RemoteConnection}, and references to it should be cleared. 158 * 159 * @param connection The {@code RemoteConnection} invoking this method. 160 */ 161 public void onDestroyed(RemoteConnection connection) {} 162 163 /** 164 * Indicates that the {@code RemoteConnection}s with which this {@code RemoteConnection} 165 * may be asked to create a conference has changed. 166 * 167 * @param connection The {@code RemoteConnection} invoking this method. 168 * @param conferenceableConnections The {@code RemoteConnection}s with which this 169 * {@code RemoteConnection} may be asked to create a conference. 170 */ 171 public void onConferenceableConnectionsChanged( 172 RemoteConnection connection, 173 List<RemoteConnection> conferenceableConnections) {} 174 175 /** 176 * Indicates that the {@code VideoProvider} associated with this {@code RemoteConnection} 177 * has changed. 178 * 179 * @param connection The {@code RemoteConnection} invoking this method. 180 * @param videoProvider The new {@code VideoProvider} associated with this 181 * {@code RemoteConnection}. 182 * @hide 183 */ 184 public void onVideoProviderChanged( 185 RemoteConnection connection, VideoProvider videoProvider) {} 186 187 /** 188 * Indicates that the {@code RemoteConference} that this {@code RemoteConnection} is a part 189 * of has changed. 190 * 191 * @param connection The {@code RemoteConnection} invoking this method. 192 * @param conference The {@code RemoteConference} of which this {@code RemoteConnection} is 193 * a part, which may be {@code null}. 194 */ 195 public void onConferenceChanged( 196 RemoteConnection connection, 197 RemoteConference conference) {} 198 } 199 200 /** {@hide} */ 201 public static class VideoProvider { 202 203 public abstract static class Listener { 204 public void onReceiveSessionModifyRequest( 205 VideoProvider videoProvider, 206 VideoProfile videoProfile) {} 207 208 public void onReceiveSessionModifyResponse( 209 VideoProvider videoProvider, 210 int status, 211 VideoProfile requestedProfile, 212 VideoProfile responseProfile) {} 213 214 public void onHandleCallSessionEvent(VideoProvider videoProvider, int event) {} 215 216 public void onPeerDimensionsChanged(VideoProvider videoProvider, int width, int height) {} 217 218 public void onCallDataUsageChanged(VideoProvider videoProvider, long dataUsage) {} 219 220 public void onCameraCapabilitiesChanged( 221 VideoProvider videoProvider, 222 CameraCapabilities cameraCapabilities) {} 223 224 public void onVideoQualityChanged(VideoProvider videoProvider, int videoQuality) {} 225 } 226 227 private final IVideoCallback mVideoCallbackDelegate = new IVideoCallback() { 228 @Override 229 public void receiveSessionModifyRequest(VideoProfile videoProfile) { 230 for (Listener l : mListeners) { 231 l.onReceiveSessionModifyRequest(VideoProvider.this, videoProfile); 232 } 233 } 234 235 @Override 236 public void receiveSessionModifyResponse(int status, VideoProfile requestedProfile, 237 VideoProfile responseProfile) { 238 for (Listener l : mListeners) { 239 l.onReceiveSessionModifyResponse( 240 VideoProvider.this, 241 status, 242 requestedProfile, 243 responseProfile); 244 } 245 } 246 247 @Override 248 public void handleCallSessionEvent(int event) { 249 for (Listener l : mListeners) { 250 l.onHandleCallSessionEvent(VideoProvider.this, event); 251 } 252 } 253 254 @Override 255 public void changePeerDimensions(int width, int height) { 256 for (Listener l : mListeners) { 257 l.onPeerDimensionsChanged(VideoProvider.this, width, height); 258 } 259 } 260 261 @Override 262 public void changeCallDataUsage(long dataUsage) { 263 for (Listener l : mListeners) { 264 l.onCallDataUsageChanged(VideoProvider.this, dataUsage); 265 } 266 } 267 268 @Override 269 public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) { 270 for (Listener l : mListeners) { 271 l.onCameraCapabilitiesChanged(VideoProvider.this, cameraCapabilities); 272 } 273 } 274 275 @Override 276 public void changeVideoQuality(int videoQuality) { 277 for (Listener l : mListeners) { 278 l.onVideoQualityChanged(VideoProvider.this, videoQuality); 279 } 280 } 281 282 @Override 283 public IBinder asBinder() { 284 return null; 285 } 286 }; 287 288 private final VideoCallbackServant mVideoCallbackServant = 289 new VideoCallbackServant(mVideoCallbackDelegate); 290 291 private final IVideoProvider mVideoProviderBinder; 292 293 /** 294 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is 295 * load factor before resizing, 1 means we only expect a single thread to 296 * access the map so make only a single shard 297 */ 298 private final Set<Listener> mListeners = Collections.newSetFromMap( 299 new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1)); 300 301 public VideoProvider(IVideoProvider videoProviderBinder) { 302 mVideoProviderBinder = videoProviderBinder; 303 try { 304 mVideoProviderBinder.addVideoCallback(mVideoCallbackServant.getStub().asBinder()); 305 } catch (RemoteException e) { 306 } 307 } 308 309 public void addListener(Listener l) { 310 mListeners.add(l); 311 } 312 313 public void removeListener(Listener l) { 314 mListeners.remove(l); 315 } 316 317 public void setCamera(String cameraId) { 318 try { 319 mVideoProviderBinder.setCamera(cameraId); 320 } catch (RemoteException e) { 321 } 322 } 323 324 public void setPreviewSurface(Surface surface) { 325 try { 326 mVideoProviderBinder.setPreviewSurface(surface); 327 } catch (RemoteException e) { 328 } 329 } 330 331 public void setDisplaySurface(Surface surface) { 332 try { 333 mVideoProviderBinder.setDisplaySurface(surface); 334 } catch (RemoteException e) { 335 } 336 } 337 338 public void setDeviceOrientation(int rotation) { 339 try { 340 mVideoProviderBinder.setDeviceOrientation(rotation); 341 } catch (RemoteException e) { 342 } 343 } 344 345 public void setZoom(float value) { 346 try { 347 mVideoProviderBinder.setZoom(value); 348 } catch (RemoteException e) { 349 } 350 } 351 352 public void sendSessionModifyRequest(VideoProfile reqProfile) { 353 try { 354 mVideoProviderBinder.sendSessionModifyRequest(reqProfile); 355 } catch (RemoteException e) { 356 } 357 } 358 359 public void sendSessionModifyResponse(VideoProfile responseProfile) { 360 try { 361 mVideoProviderBinder.sendSessionModifyResponse(responseProfile); 362 } catch (RemoteException e) { 363 } 364 } 365 366 public void requestCameraCapabilities() { 367 try { 368 mVideoProviderBinder.requestCameraCapabilities(); 369 } catch (RemoteException e) { 370 } 371 } 372 373 public void requestCallDataUsage() { 374 try { 375 mVideoProviderBinder.requestCallDataUsage(); 376 } catch (RemoteException e) { 377 } 378 } 379 380 public void setPauseImage(String uri) { 381 try { 382 mVideoProviderBinder.setPauseImage(uri); 383 } catch (RemoteException e) { 384 } 385 } 386 } 387 388 private IConnectionService mConnectionService; 389 private final String mConnectionId; 390 /** 391 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is 392 * load factor before resizing, 1 means we only expect a single thread to 393 * access the map so make only a single shard 394 */ 395 private final Set<Callback> mCallbacks = Collections.newSetFromMap( 396 new ConcurrentHashMap<Callback, Boolean>(8, 0.9f, 1)); 397 private final List<RemoteConnection> mConferenceableConnections = new ArrayList<>(); 398 private final List<RemoteConnection> mUnmodifiableconferenceableConnections = 399 Collections.unmodifiableList(mConferenceableConnections); 400 401 private int mState = Connection.STATE_NEW; 402 private DisconnectCause mDisconnectCause; 403 private boolean mRingbackRequested; 404 private boolean mConnected; 405 private int mConnectionCapabilities; 406 private int mVideoState; 407 private VideoProvider mVideoProvider; 408 private boolean mIsVoipAudioMode; 409 private StatusHints mStatusHints; 410 private Uri mAddress; 411 private int mAddressPresentation; 412 private String mCallerDisplayName; 413 private int mCallerDisplayNamePresentation; 414 private RemoteConference mConference; 415 416 /** 417 * @hide 418 */ 419 RemoteConnection( 420 String id, 421 IConnectionService connectionService, 422 ConnectionRequest request) { 423 mConnectionId = id; 424 mConnectionService = connectionService; 425 mConnected = true; 426 mState = Connection.STATE_INITIALIZING; 427 } 428 429 /** 430 * @hide 431 */ 432 RemoteConnection(String callId, IConnectionService connectionService, 433 ParcelableConnection connection) { 434 mConnectionId = callId; 435 mConnectionService = connectionService; 436 mConnected = true; 437 mState = connection.getState(); 438 mDisconnectCause = connection.getDisconnectCause(); 439 mRingbackRequested = connection.isRingbackRequested(); 440 mConnectionCapabilities = connection.getConnectionCapabilities(); 441 mVideoState = connection.getVideoState(); 442 mVideoProvider = new RemoteConnection.VideoProvider(connection.getVideoProvider()); 443 mIsVoipAudioMode = connection.getIsVoipAudioMode(); 444 mStatusHints = connection.getStatusHints(); 445 mAddress = connection.getHandle(); 446 mAddressPresentation = connection.getHandlePresentation(); 447 mCallerDisplayName = connection.getCallerDisplayName(); 448 mCallerDisplayNamePresentation = connection.getCallerDisplayNamePresentation(); 449 mConference = null; 450 } 451 452 /** 453 * Create a RemoteConnection which is used for failed connections. Note that using it for any 454 * "real" purpose will almost certainly fail. Callers should note the failure and act 455 * accordingly (moving on to another RemoteConnection, for example) 456 * 457 * @param disconnectCause The reason for the failed connection. 458 * @hide 459 */ 460 RemoteConnection(DisconnectCause disconnectCause) { 461 mConnectionId = "NULL"; 462 mConnected = false; 463 mState = Connection.STATE_DISCONNECTED; 464 mDisconnectCause = disconnectCause; 465 } 466 467 /** 468 * Adds a callback to this {@code RemoteConnection}. 469 * 470 * @param callback A {@code Callback}. 471 */ 472 public void registerCallback(Callback callback) { 473 mCallbacks.add(callback); 474 } 475 476 /** 477 * Removes a callback from this {@code RemoteConnection}. 478 * 479 * @param callback A {@code Callback}. 480 */ 481 public void unregisterCallback(Callback callback) { 482 if (callback != null) { 483 mCallbacks.remove(callback); 484 } 485 } 486 487 /** 488 * Obtains the state of this {@code RemoteConnection}. 489 * 490 * @return A state value, chosen from the {@code STATE_*} constants. 491 */ 492 public int getState() { 493 return mState; 494 } 495 496 /** 497 * Obtains the reason why this {@code RemoteConnection} may have been disconnected. 498 * 499 * @return For a {@link Connection#STATE_DISCONNECTED} {@code RemoteConnection}, the 500 * disconnect cause expressed as a code chosen from among those declared in 501 * {@link DisconnectCause}. 502 */ 503 public DisconnectCause getDisconnectCause() { 504 return mDisconnectCause; 505 } 506 507 /** 508 * Obtains the capabilities of this {@code RemoteConnection}. 509 * 510 * @return A bitmask of the capabilities of the {@code RemoteConnection}, as defined in 511 * the {@code CAPABILITY_*} constants in class {@link Connection}. 512 */ 513 public int getConnectionCapabilities() { 514 return mConnectionCapabilities; 515 } 516 517 /** 518 * Determines if the audio mode of this {@code RemoteConnection} is VOIP. 519 * 520 * @return {@code true} if the {@code RemoteConnection}'s current audio mode is VOIP. 521 */ 522 public boolean isVoipAudioMode() { 523 return mIsVoipAudioMode; 524 } 525 526 /** 527 * Obtains status hints pertaining to this {@code RemoteConnection}. 528 * 529 * @return The current {@link StatusHints} of this {@code RemoteConnection}, 530 * or {@code null} if none have been set. 531 */ 532 public StatusHints getStatusHints() { 533 return mStatusHints; 534 } 535 536 /** 537 * Obtains the address of this {@code RemoteConnection}. 538 * 539 * @return The address (e.g., phone number) to which the {@code RemoteConnection} 540 * is currently connected. 541 */ 542 public Uri getAddress() { 543 return mAddress; 544 } 545 546 /** 547 * Obtains the presentation requirements for the address of this {@code RemoteConnection}. 548 * 549 * @return The presentation requirements for the address. See 550 * {@link TelecomManager} for valid values. 551 */ 552 public int getAddressPresentation() { 553 return mAddressPresentation; 554 } 555 556 /** 557 * Obtains the display name for this {@code RemoteConnection}'s caller. 558 * 559 * @return The display name for the caller. 560 */ 561 public CharSequence getCallerDisplayName() { 562 return mCallerDisplayName; 563 } 564 565 /** 566 * Obtains the presentation requirements for this {@code RemoteConnection}'s 567 * caller's display name. 568 * 569 * @return The presentation requirements for the caller display name. See 570 * {@link TelecomManager} for valid values. 571 */ 572 public int getCallerDisplayNamePresentation() { 573 return mCallerDisplayNamePresentation; 574 } 575 576 /** 577 * Obtains the video state of this {@code RemoteConnection}. 578 * 579 * @return The video state of the {@code RemoteConnection}. See {@link VideoProfile.VideoState}. 580 * @hide 581 */ 582 public int getVideoState() { 583 return mVideoState; 584 } 585 586 /** 587 * Obtains the video provider of this {@code RemoteConnection}. 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 } 846 } 847 848 /** 849 * @hide 850 */ 851 void setDestroyed() { 852 if (!mCallbacks.isEmpty()) { 853 // Make sure that the callbacks are notified that the call is destroyed first. 854 if (mState != Connection.STATE_DISCONNECTED) { 855 setDisconnected( 856 new DisconnectCause(DisconnectCause.ERROR, "Connection destroyed.")); 857 } 858 859 for (Callback c : mCallbacks) { 860 c.onDestroyed(this); 861 } 862 mCallbacks.clear(); 863 864 mConnected = false; 865 } 866 } 867 868 /** 869 * @hide 870 */ 871 void setPostDialWait(String remainingDigits) { 872 for (Callback c : mCallbacks) { 873 c.onPostDialWait(this, remainingDigits); 874 } 875 } 876 877 /** 878 * @hide 879 */ 880 void onPostDialChar(char nextChar) { 881 for (Callback c : mCallbacks) { 882 c.onPostDialChar(this, nextChar); 883 } 884 } 885 886 /** 887 * @hide 888 */ 889 void setVideoState(int videoState) { 890 mVideoState = videoState; 891 for (Callback c : mCallbacks) { 892 c.onVideoStateChanged(this, videoState); 893 } 894 } 895 896 /** 897 * @hide 898 */ 899 void setVideoProvider(VideoProvider videoProvider) { 900 mVideoProvider = videoProvider; 901 for (Callback c : mCallbacks) { 902 c.onVideoProviderChanged(this, videoProvider); 903 } 904 } 905 906 /** @hide */ 907 void setIsVoipAudioMode(boolean isVoip) { 908 mIsVoipAudioMode = isVoip; 909 for (Callback c : mCallbacks) { 910 c.onVoipAudioChanged(this, isVoip); 911 } 912 } 913 914 /** @hide */ 915 void setStatusHints(StatusHints statusHints) { 916 mStatusHints = statusHints; 917 for (Callback c : mCallbacks) { 918 c.onStatusHintsChanged(this, statusHints); 919 } 920 } 921 922 /** @hide */ 923 void setAddress(Uri address, int presentation) { 924 mAddress = address; 925 mAddressPresentation = presentation; 926 for (Callback c : mCallbacks) { 927 c.onAddressChanged(this, address, presentation); 928 } 929 } 930 931 /** @hide */ 932 void setCallerDisplayName(String callerDisplayName, int presentation) { 933 mCallerDisplayName = callerDisplayName; 934 mCallerDisplayNamePresentation = presentation; 935 for (Callback c : mCallbacks) { 936 c.onCallerDisplayNameChanged(this, callerDisplayName, presentation); 937 } 938 } 939 940 /** @hide */ 941 void setConferenceableConnections(List<RemoteConnection> conferenceableConnections) { 942 mConferenceableConnections.clear(); 943 mConferenceableConnections.addAll(conferenceableConnections); 944 for (Callback c : mCallbacks) { 945 c.onConferenceableConnectionsChanged(this, mUnmodifiableconferenceableConnections); 946 } 947 } 948 949 /** @hide */ 950 void setConference(RemoteConference conference) { 951 if (mConference != conference) { 952 mConference = conference; 953 for (Callback c : mCallbacks) { 954 c.onConferenceChanged(this, conference); 955 } 956 } 957 } 958 959 /** 960 * Create a RemoteConnection represents a failure, and which will be in 961 * {@link Connection#STATE_DISCONNECTED}. Attempting to use it for anything will almost 962 * certainly result in bad things happening. Do not do this. 963 * 964 * @return a failed {@link RemoteConnection} 965 * 966 * @hide 967 */ 968 public static RemoteConnection failure(DisconnectCause disconnectCause) { 969 return new RemoteConnection(disconnectCause); 970 } 971} 972