RemoteConnection.java revision 356322fb1e2cc581bb181f927550843a36aedcea
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.annotation.NonNull; 24import android.annotation.Nullable; 25import android.annotation.SystemApi; 26import android.hardware.camera2.CameraManager; 27import android.net.Uri; 28import android.os.Bundle; 29import android.os.Handler; 30import android.os.IBinder; 31import android.os.RemoteException; 32import android.view.Surface; 33 34import java.util.ArrayList; 35import java.util.Collections; 36import java.util.List; 37import java.util.Set; 38import java.util.concurrent.ConcurrentHashMap; 39 40/** 41 * A connection provided to a {@link ConnectionService} by another {@code ConnectionService} 42 * running in a different process. 43 * 44 * @see ConnectionService#createRemoteOutgoingConnection(PhoneAccountHandle, ConnectionRequest) 45 * @see ConnectionService#createRemoteIncomingConnection(PhoneAccountHandle, ConnectionRequest) 46 */ 47public final class RemoteConnection { 48 49 /** 50 * Callback base class for {@link RemoteConnection}. 51 */ 52 public static abstract class Callback { 53 /** 54 * Invoked when the state of this {@code RemoteConnection} has changed. See 55 * {@link #getState()}. 56 * 57 * @param connection The {@code RemoteConnection} invoking this method. 58 * @param state The new state of the {@code RemoteConnection}. 59 */ 60 public void onStateChanged(RemoteConnection connection, int state) {} 61 62 /** 63 * Invoked when this {@code RemoteConnection} is disconnected. 64 * 65 * @param connection The {@code RemoteConnection} invoking this method. 66 * @param disconnectCause The ({@see DisconnectCause}) associated with this failed 67 * connection. 68 */ 69 public void onDisconnected( 70 RemoteConnection connection, 71 DisconnectCause disconnectCause) {} 72 73 /** 74 * Invoked when this {@code RemoteConnection} is requesting ringback. See 75 * {@link #isRingbackRequested()}. 76 * 77 * @param connection The {@code RemoteConnection} invoking this method. 78 * @param ringback Whether the {@code RemoteConnection} is requesting ringback. 79 */ 80 public void onRingbackRequested(RemoteConnection connection, boolean ringback) {} 81 82 /** 83 * Indicates that the call capabilities of this {@code RemoteConnection} have changed. 84 * See {@link #getConnectionCapabilities()}. 85 * 86 * @param connection The {@code RemoteConnection} invoking this method. 87 * @param connectionCapabilities The new capabilities of the {@code RemoteConnection}. 88 */ 89 public void onConnectionCapabilitiesChanged( 90 RemoteConnection connection, 91 int connectionCapabilities) {} 92 93 /** 94 * Indicates that the call properties of this {@code RemoteConnection} have changed. 95 * See {@link #getConnectionProperties()}. 96 * 97 * @param connection The {@code RemoteConnection} invoking this method. 98 * @param connectionProperties The new properties of the {@code RemoteConnection}. 99 */ 100 public void onConnectionPropertiesChanged( 101 RemoteConnection connection, 102 int connectionProperties) {} 103 104 /** 105 * Invoked when the post-dial sequence in the outgoing {@code Connection} has reached a 106 * pause character. This causes the post-dial signals to stop pending user confirmation. An 107 * implementation should present this choice to the user and invoke 108 * {@link RemoteConnection#postDialContinue(boolean)} when the user makes the choice. 109 * 110 * @param connection The {@code RemoteConnection} invoking this method. 111 * @param remainingPostDialSequence The post-dial characters that remain to be sent. 112 */ 113 public void onPostDialWait(RemoteConnection connection, String remainingPostDialSequence) {} 114 115 /** 116 * Invoked when the post-dial sequence in the outgoing {@code Connection} has processed 117 * a character. 118 * 119 * @param connection The {@code RemoteConnection} invoking this method. 120 * @param nextChar The character being processed. 121 */ 122 public void onPostDialChar(RemoteConnection connection, char nextChar) {} 123 124 /** 125 * Indicates that the VOIP audio status of this {@code RemoteConnection} has changed. 126 * See {@link #isVoipAudioMode()}. 127 * 128 * @param connection The {@code RemoteConnection} invoking this method. 129 * @param isVoip Whether the new audio state of the {@code RemoteConnection} is VOIP. 130 */ 131 public void onVoipAudioChanged(RemoteConnection connection, boolean isVoip) {} 132 133 /** 134 * Indicates that the status hints of this {@code RemoteConnection} have changed. See 135 * {@link #getStatusHints()} ()}. 136 * 137 * @param connection The {@code RemoteConnection} invoking this method. 138 * @param statusHints The new status hints of the {@code RemoteConnection}. 139 */ 140 public void onStatusHintsChanged(RemoteConnection connection, StatusHints statusHints) {} 141 142 /** 143 * Indicates that the address (e.g., phone number) of this {@code RemoteConnection} has 144 * changed. See {@link #getAddress()} and {@link #getAddressPresentation()}. 145 * 146 * @param connection The {@code RemoteConnection} invoking this method. 147 * @param address The new address of the {@code RemoteConnection}. 148 * @param presentation The presentation requirements for the address. 149 * See {@link TelecomManager} for valid values. 150 */ 151 public void onAddressChanged(RemoteConnection connection, Uri address, int presentation) {} 152 153 /** 154 * Indicates that the caller display name of this {@code RemoteConnection} has changed. 155 * See {@link #getCallerDisplayName()} and {@link #getCallerDisplayNamePresentation()}. 156 * 157 * @param connection The {@code RemoteConnection} invoking this method. 158 * @param callerDisplayName The new caller display name of the {@code RemoteConnection}. 159 * @param presentation The presentation requirements for the handle. 160 * See {@link TelecomManager} for valid values. 161 */ 162 public void onCallerDisplayNameChanged( 163 RemoteConnection connection, String callerDisplayName, int presentation) {} 164 165 /** 166 * Indicates that the video state of this {@code RemoteConnection} has changed. 167 * See {@link #getVideoState()}. 168 * 169 * @param connection The {@code RemoteConnection} invoking this method. 170 * @param videoState The new video state of the {@code RemoteConnection}. 171 */ 172 public void onVideoStateChanged(RemoteConnection connection, int videoState) {} 173 174 /** 175 * Indicates that this {@code RemoteConnection} has been destroyed. No further requests 176 * should be made to the {@code RemoteConnection}, and references to it should be cleared. 177 * 178 * @param connection The {@code RemoteConnection} invoking this method. 179 */ 180 public void onDestroyed(RemoteConnection connection) {} 181 182 /** 183 * Indicates that the {@code RemoteConnection}s with which this {@code RemoteConnection} 184 * may be asked to create a conference has changed. 185 * 186 * @param connection The {@code RemoteConnection} invoking this method. 187 * @param conferenceableConnections The {@code RemoteConnection}s with which this 188 * {@code RemoteConnection} may be asked to create a conference. 189 */ 190 public void onConferenceableConnectionsChanged( 191 RemoteConnection connection, 192 List<RemoteConnection> conferenceableConnections) {} 193 194 /** 195 * Indicates that the {@code VideoProvider} associated with this {@code RemoteConnection} 196 * has changed. 197 * 198 * @param connection The {@code RemoteConnection} invoking this method. 199 * @param videoProvider The new {@code VideoProvider} associated with this 200 * {@code RemoteConnection}. 201 */ 202 public void onVideoProviderChanged( 203 RemoteConnection connection, VideoProvider videoProvider) {} 204 205 /** 206 * Indicates that the {@code RemoteConference} that this {@code RemoteConnection} is a part 207 * of has changed. 208 * 209 * @param connection The {@code RemoteConnection} invoking this method. 210 * @param conference The {@code RemoteConference} of which this {@code RemoteConnection} is 211 * a part, which may be {@code null}. 212 */ 213 public void onConferenceChanged( 214 RemoteConnection connection, 215 RemoteConference conference) {} 216 217 /** 218 * Handles changes to the {@code RemoteConnection} extras. 219 * 220 * @param connection The {@code RemoteConnection} invoking this method. 221 * @param extras The extras containing other information associated with the connection. 222 */ 223 public void onExtrasChanged(RemoteConnection connection, @Nullable Bundle extras) {} 224 225 /** 226 * Handles a connection event propagated to this {@link RemoteConnection}. 227 * <p> 228 * Connection events originate from {@link Connection#sendConnectionEvent(String, Bundle)}. 229 * 230 * @param connection The {@code RemoteConnection} invoking this method. 231 * @param event The connection event. 232 * @param extras Extras associated with the event. 233 */ 234 public void onConnectionEvent(RemoteConnection connection, String event, Bundle extras) {} 235 236 /** 237 * Indicates that a RTT session was successfully established on this 238 * {@link RemoteConnection}. See {@link Connection#sendRttInitiationSuccess()}. 239 * @hide 240 * @param connection The {@code RemoteConnection} invoking this method. 241 */ 242 public void onRttInitiationSuccess(RemoteConnection connection) {} 243 244 /** 245 * Indicates that a RTT session failed to be established on this 246 * {@link RemoteConnection}. See {@link Connection#sendRttInitiationFailure()}. 247 * @hide 248 * @param connection The {@code RemoteConnection} invoking this method. 249 * @param reason One of the reason codes defined in {@link Connection.RttModifyStatus}, 250 * with the exception of 251 * {@link Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}. 252 */ 253 public void onRttInitiationFailure(RemoteConnection connection, int reason) {} 254 255 /** 256 * Indicates that an established RTT session was terminated remotely on this 257 * {@link RemoteConnection}. See {@link Connection#sendRttSessionRemotelyTerminated()} 258 * @hide 259 * @param connection The {@code RemoteConnection} invoking this method. 260 */ 261 public void onRttSessionRemotelyTerminated(RemoteConnection connection) {} 262 263 /** 264 * Indicates that the remote user on this {@link RemoteConnection} has requested an upgrade 265 * to an RTT session. See {@link Connection#sendRemoteRttRequest()} 266 * @hide 267 * @param connection The {@code RemoteConnection} invoking this method. 268 */ 269 public void onRemoteRttRequest(RemoteConnection connection) {} 270 } 271 272 /** 273 * {@link RemoteConnection.VideoProvider} associated with a {@link RemoteConnection}. Used to 274 * receive video related events and control the video associated with a 275 * {@link RemoteConnection}. 276 * 277 * @see Connection.VideoProvider 278 */ 279 public static class VideoProvider { 280 281 /** 282 * Callback class used by the {@link RemoteConnection.VideoProvider} to relay events from 283 * the {@link Connection.VideoProvider}. 284 */ 285 public abstract static class Callback { 286 /** 287 * Reports a session modification request received from the 288 * {@link Connection.VideoProvider} associated with a {@link RemoteConnection}. 289 * 290 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method. 291 * @param videoProfile The requested video call profile. 292 * @see InCallService.VideoCall.Callback#onSessionModifyRequestReceived(VideoProfile) 293 * @see Connection.VideoProvider#receiveSessionModifyRequest(VideoProfile) 294 */ 295 public void onSessionModifyRequestReceived( 296 VideoProvider videoProvider, 297 VideoProfile videoProfile) {} 298 299 /** 300 * Reports a session modification response received from the 301 * {@link Connection.VideoProvider} associated with a {@link RemoteConnection}. 302 * 303 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method. 304 * @param status Status of the session modify request. 305 * @param requestedProfile The original request which was sent to the peer device. 306 * @param responseProfile The actual profile changes made by the peer device. 307 * @see InCallService.VideoCall.Callback#onSessionModifyResponseReceived(int, 308 * VideoProfile, VideoProfile) 309 * @see Connection.VideoProvider#receiveSessionModifyResponse(int, VideoProfile, 310 * VideoProfile) 311 */ 312 public void onSessionModifyResponseReceived( 313 VideoProvider videoProvider, 314 int status, 315 VideoProfile requestedProfile, 316 VideoProfile responseProfile) {} 317 318 /** 319 * Reports a call session event received from the {@link Connection.VideoProvider} 320 * associated with a {@link RemoteConnection}. 321 * 322 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method. 323 * @param event The event. 324 * @see InCallService.VideoCall.Callback#onCallSessionEvent(int) 325 * @see Connection.VideoProvider#handleCallSessionEvent(int) 326 */ 327 public void onCallSessionEvent(VideoProvider videoProvider, int event) {} 328 329 /** 330 * Reports a change in the peer video dimensions received from the 331 * {@link Connection.VideoProvider} associated with a {@link RemoteConnection}. 332 * 333 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method. 334 * @param width The updated peer video width. 335 * @param height The updated peer video height. 336 * @see InCallService.VideoCall.Callback#onPeerDimensionsChanged(int, int) 337 * @see Connection.VideoProvider#changePeerDimensions(int, int) 338 */ 339 public void onPeerDimensionsChanged(VideoProvider videoProvider, int width, 340 int height) {} 341 342 /** 343 * Reports a change in the data usage (in bytes) received from the 344 * {@link Connection.VideoProvider} associated with a {@link RemoteConnection}. 345 * 346 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method. 347 * @param dataUsage The updated data usage (in bytes). 348 * @see InCallService.VideoCall.Callback#onCallDataUsageChanged(long) 349 * @see Connection.VideoProvider#setCallDataUsage(long) 350 */ 351 public void onCallDataUsageChanged(VideoProvider videoProvider, long dataUsage) {} 352 353 /** 354 * Reports a change in the capabilities of the current camera, received from the 355 * {@link Connection.VideoProvider} associated with a {@link RemoteConnection}. 356 * 357 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method. 358 * @param cameraCapabilities The changed camera capabilities. 359 * @see InCallService.VideoCall.Callback#onCameraCapabilitiesChanged( 360 * VideoProfile.CameraCapabilities) 361 * @see Connection.VideoProvider#changeCameraCapabilities( 362 * VideoProfile.CameraCapabilities) 363 */ 364 public void onCameraCapabilitiesChanged( 365 VideoProvider videoProvider, 366 VideoProfile.CameraCapabilities cameraCapabilities) {} 367 368 /** 369 * Reports a change in the video quality received from the 370 * {@link Connection.VideoProvider} associated with a {@link RemoteConnection}. 371 * 372 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method. 373 * @param videoQuality The updated peer video quality. 374 * @see InCallService.VideoCall.Callback#onVideoQualityChanged(int) 375 * @see Connection.VideoProvider#changeVideoQuality(int) 376 */ 377 public void onVideoQualityChanged(VideoProvider videoProvider, int videoQuality) {} 378 } 379 380 private final IVideoCallback mVideoCallbackDelegate = new IVideoCallback() { 381 @Override 382 public void receiveSessionModifyRequest(VideoProfile videoProfile) { 383 for (Callback l : mCallbacks) { 384 l.onSessionModifyRequestReceived(VideoProvider.this, videoProfile); 385 } 386 } 387 388 @Override 389 public void receiveSessionModifyResponse(int status, VideoProfile requestedProfile, 390 VideoProfile responseProfile) { 391 for (Callback l : mCallbacks) { 392 l.onSessionModifyResponseReceived( 393 VideoProvider.this, 394 status, 395 requestedProfile, 396 responseProfile); 397 } 398 } 399 400 @Override 401 public void handleCallSessionEvent(int event) { 402 for (Callback l : mCallbacks) { 403 l.onCallSessionEvent(VideoProvider.this, event); 404 } 405 } 406 407 @Override 408 public void changePeerDimensions(int width, int height) { 409 for (Callback l : mCallbacks) { 410 l.onPeerDimensionsChanged(VideoProvider.this, width, height); 411 } 412 } 413 414 @Override 415 public void changeCallDataUsage(long dataUsage) { 416 for (Callback l : mCallbacks) { 417 l.onCallDataUsageChanged(VideoProvider.this, dataUsage); 418 } 419 } 420 421 @Override 422 public void changeCameraCapabilities( 423 VideoProfile.CameraCapabilities cameraCapabilities) { 424 for (Callback l : mCallbacks) { 425 l.onCameraCapabilitiesChanged(VideoProvider.this, cameraCapabilities); 426 } 427 } 428 429 @Override 430 public void changeVideoQuality(int videoQuality) { 431 for (Callback l : mCallbacks) { 432 l.onVideoQualityChanged(VideoProvider.this, videoQuality); 433 } 434 } 435 436 @Override 437 public IBinder asBinder() { 438 return null; 439 } 440 }; 441 442 private final VideoCallbackServant mVideoCallbackServant = 443 new VideoCallbackServant(mVideoCallbackDelegate); 444 445 private final IVideoProvider mVideoProviderBinder; 446 447 private final String mCallingPackage; 448 449 private final int mTargetSdkVersion; 450 451 /** 452 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is 453 * load factor before resizing, 1 means we only expect a single thread to 454 * access the map so make only a single shard 455 */ 456 private final Set<Callback> mCallbacks = Collections.newSetFromMap( 457 new ConcurrentHashMap<Callback, Boolean>(8, 0.9f, 1)); 458 459 VideoProvider(IVideoProvider videoProviderBinder, String callingPackage, 460 int targetSdkVersion) { 461 462 mVideoProviderBinder = videoProviderBinder; 463 mCallingPackage = callingPackage; 464 mTargetSdkVersion = targetSdkVersion; 465 try { 466 mVideoProviderBinder.addVideoCallback(mVideoCallbackServant.getStub().asBinder()); 467 } catch (RemoteException e) { 468 } 469 } 470 471 /** 472 * Registers a callback to receive commands and state changes for video calls. 473 * 474 * @param l The video call callback. 475 */ 476 public void registerCallback(Callback l) { 477 mCallbacks.add(l); 478 } 479 480 /** 481 * Clears the video call callback set via {@link #registerCallback}. 482 * 483 * @param l The video call callback to clear. 484 */ 485 public void unregisterCallback(Callback l) { 486 mCallbacks.remove(l); 487 } 488 489 /** 490 * Sets the camera to be used for the outgoing video for the 491 * {@link RemoteConnection.VideoProvider}. 492 * 493 * @param cameraId The id of the camera (use ids as reported by 494 * {@link CameraManager#getCameraIdList()}). 495 * @see Connection.VideoProvider#onSetCamera(String) 496 */ 497 public void setCamera(String cameraId) { 498 try { 499 mVideoProviderBinder.setCamera(cameraId, mCallingPackage, mTargetSdkVersion); 500 } catch (RemoteException e) { 501 } 502 } 503 504 /** 505 * Sets the surface to be used for displaying a preview of what the user's camera is 506 * currently capturing for the {@link RemoteConnection.VideoProvider}. 507 * 508 * @param surface The {@link Surface}. 509 * @see Connection.VideoProvider#onSetPreviewSurface(Surface) 510 */ 511 public void setPreviewSurface(Surface surface) { 512 try { 513 mVideoProviderBinder.setPreviewSurface(surface); 514 } catch (RemoteException e) { 515 } 516 } 517 518 /** 519 * Sets the surface to be used for displaying the video received from the remote device for 520 * the {@link RemoteConnection.VideoProvider}. 521 * 522 * @param surface The {@link Surface}. 523 * @see Connection.VideoProvider#onSetDisplaySurface(Surface) 524 */ 525 public void setDisplaySurface(Surface surface) { 526 try { 527 mVideoProviderBinder.setDisplaySurface(surface); 528 } catch (RemoteException e) { 529 } 530 } 531 532 /** 533 * Sets the device orientation, in degrees, for the {@link RemoteConnection.VideoProvider}. 534 * Assumes that a standard portrait orientation of the device is 0 degrees. 535 * 536 * @param rotation The device orientation, in degrees. 537 * @see Connection.VideoProvider#onSetDeviceOrientation(int) 538 */ 539 public void setDeviceOrientation(int rotation) { 540 try { 541 mVideoProviderBinder.setDeviceOrientation(rotation); 542 } catch (RemoteException e) { 543 } 544 } 545 546 /** 547 * Sets camera zoom ratio for the {@link RemoteConnection.VideoProvider}. 548 * 549 * @param value The camera zoom ratio. 550 * @see Connection.VideoProvider#onSetZoom(float) 551 */ 552 public void setZoom(float value) { 553 try { 554 mVideoProviderBinder.setZoom(value); 555 } catch (RemoteException e) { 556 } 557 } 558 559 /** 560 * Issues a request to modify the properties of the current video session for the 561 * {@link RemoteConnection.VideoProvider}. 562 * 563 * @param fromProfile The video profile prior to the request. 564 * @param toProfile The video profile with the requested changes made. 565 * @see Connection.VideoProvider#onSendSessionModifyRequest(VideoProfile, VideoProfile) 566 */ 567 public void sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) { 568 try { 569 mVideoProviderBinder.sendSessionModifyRequest(fromProfile, toProfile); 570 } catch (RemoteException e) { 571 } 572 } 573 574 /** 575 * Provides a response to a request to change the current call video session 576 * properties for the {@link RemoteConnection.VideoProvider}. 577 * 578 * @param responseProfile The response call video properties. 579 * @see Connection.VideoProvider#onSendSessionModifyResponse(VideoProfile) 580 */ 581 public void sendSessionModifyResponse(VideoProfile responseProfile) { 582 try { 583 mVideoProviderBinder.sendSessionModifyResponse(responseProfile); 584 } catch (RemoteException e) { 585 } 586 } 587 588 /** 589 * Issues a request to retrieve the capabilities of the current camera for the 590 * {@link RemoteConnection.VideoProvider}. 591 * 592 * @see Connection.VideoProvider#onRequestCameraCapabilities() 593 */ 594 public void requestCameraCapabilities() { 595 try { 596 mVideoProviderBinder.requestCameraCapabilities(); 597 } catch (RemoteException e) { 598 } 599 } 600 601 /** 602 * Issues a request to retrieve the data usage (in bytes) of the video portion of the 603 * {@link RemoteConnection} for the {@link RemoteConnection.VideoProvider}. 604 * 605 * @see Connection.VideoProvider#onRequestConnectionDataUsage() 606 */ 607 public void requestCallDataUsage() { 608 try { 609 mVideoProviderBinder.requestCallDataUsage(); 610 } catch (RemoteException e) { 611 } 612 } 613 614 /** 615 * Sets the {@link Uri} of an image to be displayed to the peer device when the video signal 616 * is paused, for the {@link RemoteConnection.VideoProvider}. 617 * 618 * @see Connection.VideoProvider#onSetPauseImage(Uri) 619 */ 620 public void setPauseImage(Uri uri) { 621 try { 622 mVideoProviderBinder.setPauseImage(uri); 623 } catch (RemoteException e) { 624 } 625 } 626 } 627 628 private IConnectionService mConnectionService; 629 private final String mConnectionId; 630 /** 631 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is 632 * load factor before resizing, 1 means we only expect a single thread to 633 * access the map so make only a single shard 634 */ 635 private final Set<CallbackRecord> mCallbackRecords = Collections.newSetFromMap( 636 new ConcurrentHashMap<CallbackRecord, Boolean>(8, 0.9f, 1)); 637 private final List<RemoteConnection> mConferenceableConnections = new ArrayList<>(); 638 private final List<RemoteConnection> mUnmodifiableconferenceableConnections = 639 Collections.unmodifiableList(mConferenceableConnections); 640 641 private int mState = Connection.STATE_NEW; 642 private DisconnectCause mDisconnectCause; 643 private boolean mRingbackRequested; 644 private boolean mConnected; 645 private int mConnectionCapabilities; 646 private int mConnectionProperties; 647 private int mVideoState; 648 private VideoProvider mVideoProvider; 649 private boolean mIsVoipAudioMode; 650 private StatusHints mStatusHints; 651 private Uri mAddress; 652 private int mAddressPresentation; 653 private String mCallerDisplayName; 654 private int mCallerDisplayNamePresentation; 655 private RemoteConference mConference; 656 private Bundle mExtras; 657 658 /** 659 * @hide 660 */ 661 RemoteConnection( 662 String id, 663 IConnectionService connectionService, 664 ConnectionRequest request) { 665 mConnectionId = id; 666 mConnectionService = connectionService; 667 mConnected = true; 668 mState = Connection.STATE_INITIALIZING; 669 } 670 671 /** 672 * @hide 673 */ 674 RemoteConnection(String callId, IConnectionService connectionService, 675 ParcelableConnection connection, String callingPackage, int targetSdkVersion) { 676 mConnectionId = callId; 677 mConnectionService = connectionService; 678 mConnected = true; 679 mState = connection.getState(); 680 mDisconnectCause = connection.getDisconnectCause(); 681 mRingbackRequested = connection.isRingbackRequested(); 682 mConnectionCapabilities = connection.getConnectionCapabilities(); 683 mConnectionProperties = connection.getConnectionProperties(); 684 mVideoState = connection.getVideoState(); 685 IVideoProvider videoProvider = connection.getVideoProvider(); 686 if (videoProvider != null) { 687 mVideoProvider = new RemoteConnection.VideoProvider(videoProvider, callingPackage, 688 targetSdkVersion); 689 } else { 690 mVideoProvider = null; 691 } 692 mIsVoipAudioMode = connection.getIsVoipAudioMode(); 693 mStatusHints = connection.getStatusHints(); 694 mAddress = connection.getHandle(); 695 mAddressPresentation = connection.getHandlePresentation(); 696 mCallerDisplayName = connection.getCallerDisplayName(); 697 mCallerDisplayNamePresentation = connection.getCallerDisplayNamePresentation(); 698 mConference = null; 699 putExtras(connection.getExtras()); 700 701 // Stash the original connection ID as it exists in the source ConnectionService. 702 // Telecom will use this to avoid adding duplicates later. 703 // See comments on Connection.EXTRA_ORIGINAL_CONNECTION_ID for more information. 704 Bundle newExtras = new Bundle(); 705 newExtras.putString(Connection.EXTRA_ORIGINAL_CONNECTION_ID, callId); 706 putExtras(newExtras); 707 } 708 709 /** 710 * Create a RemoteConnection which is used for failed connections. Note that using it for any 711 * "real" purpose will almost certainly fail. Callers should note the failure and act 712 * accordingly (moving on to another RemoteConnection, for example) 713 * 714 * @param disconnectCause The reason for the failed connection. 715 * @hide 716 */ 717 RemoteConnection(DisconnectCause disconnectCause) { 718 mConnectionId = "NULL"; 719 mConnected = false; 720 mState = Connection.STATE_DISCONNECTED; 721 mDisconnectCause = disconnectCause; 722 } 723 724 /** 725 * Adds a callback to this {@code RemoteConnection}. 726 * 727 * @param callback A {@code Callback}. 728 */ 729 public void registerCallback(Callback callback) { 730 registerCallback(callback, new Handler()); 731 } 732 733 /** 734 * Adds a callback to this {@code RemoteConnection}. 735 * 736 * @param callback A {@code Callback}. 737 * @param handler A {@code Handler} which command and status changes will be delivered to. 738 */ 739 public void registerCallback(Callback callback, Handler handler) { 740 unregisterCallback(callback); 741 if (callback != null && handler != null) { 742 mCallbackRecords.add(new CallbackRecord(callback, handler)); 743 } 744 } 745 746 /** 747 * Removes a callback from this {@code RemoteConnection}. 748 * 749 * @param callback A {@code Callback}. 750 */ 751 public void unregisterCallback(Callback callback) { 752 if (callback != null) { 753 for (CallbackRecord record : mCallbackRecords) { 754 if (record.getCallback() == callback) { 755 mCallbackRecords.remove(record); 756 break; 757 } 758 } 759 } 760 } 761 762 /** 763 * Obtains the state of this {@code RemoteConnection}. 764 * 765 * @return A state value, chosen from the {@code STATE_*} constants. 766 */ 767 public int getState() { 768 return mState; 769 } 770 771 /** 772 * Obtains the reason why this {@code RemoteConnection} may have been disconnected. 773 * 774 * @return For a {@link Connection#STATE_DISCONNECTED} {@code RemoteConnection}, the 775 * disconnect cause expressed as a code chosen from among those declared in 776 * {@link DisconnectCause}. 777 */ 778 public DisconnectCause getDisconnectCause() { 779 return mDisconnectCause; 780 } 781 782 /** 783 * Obtains the capabilities of this {@code RemoteConnection}. 784 * 785 * @return A bitmask of the capabilities of the {@code RemoteConnection}, as defined in 786 * the {@code CAPABILITY_*} constants in class {@link Connection}. 787 */ 788 public int getConnectionCapabilities() { 789 return mConnectionCapabilities; 790 } 791 792 /** 793 * Obtains the properties of this {@code RemoteConnection}. 794 * 795 * @return A bitmask of the properties of the {@code RemoteConnection}, as defined in the 796 * {@code PROPERTY_*} constants in class {@link Connection}. 797 */ 798 public int getConnectionProperties() { 799 return mConnectionProperties; 800 } 801 802 /** 803 * Determines if the audio mode of this {@code RemoteConnection} is VOIP. 804 * 805 * @return {@code true} if the {@code RemoteConnection}'s current audio mode is VOIP. 806 */ 807 public boolean isVoipAudioMode() { 808 return mIsVoipAudioMode; 809 } 810 811 /** 812 * Obtains status hints pertaining to this {@code RemoteConnection}. 813 * 814 * @return The current {@link StatusHints} of this {@code RemoteConnection}, 815 * or {@code null} if none have been set. 816 */ 817 public StatusHints getStatusHints() { 818 return mStatusHints; 819 } 820 821 /** 822 * Obtains the address of this {@code RemoteConnection}. 823 * 824 * @return The address (e.g., phone number) to which the {@code RemoteConnection} 825 * is currently connected. 826 */ 827 public Uri getAddress() { 828 return mAddress; 829 } 830 831 /** 832 * Obtains the presentation requirements for the address of this {@code RemoteConnection}. 833 * 834 * @return The presentation requirements for the address. See 835 * {@link TelecomManager} for valid values. 836 */ 837 public int getAddressPresentation() { 838 return mAddressPresentation; 839 } 840 841 /** 842 * Obtains the display name for this {@code RemoteConnection}'s caller. 843 * 844 * @return The display name for the caller. 845 */ 846 public CharSequence getCallerDisplayName() { 847 return mCallerDisplayName; 848 } 849 850 /** 851 * Obtains the presentation requirements for this {@code RemoteConnection}'s 852 * caller's display name. 853 * 854 * @return The presentation requirements for the caller display name. See 855 * {@link TelecomManager} for valid values. 856 */ 857 public int getCallerDisplayNamePresentation() { 858 return mCallerDisplayNamePresentation; 859 } 860 861 /** 862 * Obtains the video state of this {@code RemoteConnection}. 863 * 864 * @return The video state of the {@code RemoteConnection}. See {@link VideoProfile}. 865 */ 866 public int getVideoState() { 867 return mVideoState; 868 } 869 870 /** 871 * Obtains the video provider of this {@code RemoteConnection}. 872 * @return The video provider associated with this {@code RemoteConnection}. 873 */ 874 public final VideoProvider getVideoProvider() { 875 return mVideoProvider; 876 } 877 878 /** 879 * Obtain the extras associated with this {@code RemoteConnection}. 880 * 881 * @return The extras for this connection. 882 */ 883 public final Bundle getExtras() { 884 return mExtras; 885 } 886 887 /** 888 * Determines whether this {@code RemoteConnection} is requesting ringback. 889 * 890 * @return Whether the {@code RemoteConnection} is requesting that the framework play a 891 * ringback tone on its behalf. 892 */ 893 public boolean isRingbackRequested() { 894 return mRingbackRequested; 895 } 896 897 /** 898 * Instructs this {@code RemoteConnection} to abort. 899 */ 900 public void abort() { 901 try { 902 if (mConnected) { 903 mConnectionService.abort(mConnectionId, null /*Session.Info*/); 904 } 905 } catch (RemoteException ignored) { 906 } 907 } 908 909 /** 910 * Instructs this {@link Connection#STATE_RINGING} {@code RemoteConnection} to answer. 911 */ 912 public void answer() { 913 try { 914 if (mConnected) { 915 mConnectionService.answer(mConnectionId, null /*Session.Info*/); 916 } 917 } catch (RemoteException ignored) { 918 } 919 } 920 921 /** 922 * Instructs this {@link Connection#STATE_RINGING} {@code RemoteConnection} to answer. 923 * @param videoState The video state in which to answer the call. 924 * @hide 925 */ 926 public void answer(int videoState) { 927 try { 928 if (mConnected) { 929 mConnectionService.answerVideo(mConnectionId, videoState, null /*Session.Info*/); 930 } 931 } catch (RemoteException ignored) { 932 } 933 } 934 935 /** 936 * Instructs this {@link Connection#STATE_RINGING} {@code RemoteConnection} to reject. 937 */ 938 public void reject() { 939 try { 940 if (mConnected) { 941 mConnectionService.reject(mConnectionId, null /*Session.Info*/); 942 } 943 } catch (RemoteException ignored) { 944 } 945 } 946 947 /** 948 * Instructs this {@code RemoteConnection} to go on hold. 949 */ 950 public void hold() { 951 try { 952 if (mConnected) { 953 mConnectionService.hold(mConnectionId, null /*Session.Info*/); 954 } 955 } catch (RemoteException ignored) { 956 } 957 } 958 959 /** 960 * Instructs this {@link Connection#STATE_HOLDING} call to release from hold. 961 */ 962 public void unhold() { 963 try { 964 if (mConnected) { 965 mConnectionService.unhold(mConnectionId, null /*Session.Info*/); 966 } 967 } catch (RemoteException ignored) { 968 } 969 } 970 971 /** 972 * Instructs this {@code RemoteConnection} to disconnect. 973 */ 974 public void disconnect() { 975 try { 976 if (mConnected) { 977 mConnectionService.disconnect(mConnectionId, null /*Session.Info*/); 978 } 979 } catch (RemoteException ignored) { 980 } 981 } 982 983 /** 984 * Instructs this {@code RemoteConnection} to play a dual-tone multi-frequency signaling 985 * (DTMF) tone. 986 * 987 * Any other currently playing DTMF tone in the specified call is immediately stopped. 988 * 989 * @param digit A character representing the DTMF digit for which to play the tone. This 990 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}. 991 */ 992 public void playDtmfTone(char digit) { 993 try { 994 if (mConnected) { 995 mConnectionService.playDtmfTone(mConnectionId, digit, null /*Session.Info*/); 996 } 997 } catch (RemoteException ignored) { 998 } 999 } 1000 1001 /** 1002 * Instructs this {@code RemoteConnection} to stop any dual-tone multi-frequency signaling 1003 * (DTMF) tone currently playing. 1004 * 1005 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is 1006 * currently playing, this method will do nothing. 1007 */ 1008 public void stopDtmfTone() { 1009 try { 1010 if (mConnected) { 1011 mConnectionService.stopDtmfTone(mConnectionId, null /*Session.Info*/); 1012 } 1013 } catch (RemoteException ignored) { 1014 } 1015 } 1016 1017 /** 1018 * Instructs this {@code RemoteConnection} to continue playing a post-dial DTMF string. 1019 * 1020 * A post-dial DTMF string is a string of digits following the first instance of either 1021 * {@link TelecomManager#DTMF_CHARACTER_WAIT} or {@link TelecomManager#DTMF_CHARACTER_PAUSE}. 1022 * These digits are immediately sent as DTMF tones to the recipient as soon as the 1023 * connection is made. 1024 * 1025 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this 1026 * {@code RemoteConnection} will temporarily pause playing the tones for a pre-defined period 1027 * of time. 1028 * 1029 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this 1030 * {@code RemoteConnection} will pause playing the tones and notify callbacks via 1031 * {@link Callback#onPostDialWait(RemoteConnection, String)}. At this point, the in-call app 1032 * should display to the user an indication of this state and an affordance to continue 1033 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call 1034 * app should invoke the {@link #postDialContinue(boolean)} method. 1035 * 1036 * @param proceed Whether or not to continue with the post-dial sequence. 1037 */ 1038 public void postDialContinue(boolean proceed) { 1039 try { 1040 if (mConnected) { 1041 mConnectionService.onPostDialContinue(mConnectionId, proceed, 1042 null /*Session.Info*/); 1043 } 1044 } catch (RemoteException ignored) { 1045 } 1046 } 1047 1048 /** 1049 * Instructs this {@link RemoteConnection} to pull itself to the local device. 1050 * <p> 1051 * See {@link Call#pullExternalCall()} for more information. 1052 */ 1053 public void pullExternalCall() { 1054 try { 1055 if (mConnected) { 1056 mConnectionService.pullExternalCall(mConnectionId, null /*Session.Info*/); 1057 } 1058 } catch (RemoteException ignored) { 1059 } 1060 } 1061 1062 /** 1063 * Set the audio state of this {@code RemoteConnection}. 1064 * 1065 * @param state The audio state of this {@code RemoteConnection}. 1066 * @hide 1067 * @deprecated Use {@link #setCallAudioState(CallAudioState) instead. 1068 */ 1069 @SystemApi 1070 @Deprecated 1071 public void setAudioState(AudioState state) { 1072 setCallAudioState(new CallAudioState(state)); 1073 } 1074 1075 /** 1076 * Set the audio state of this {@code RemoteConnection}. 1077 * 1078 * @param state The audio state of this {@code RemoteConnection}. 1079 */ 1080 public void setCallAudioState(CallAudioState state) { 1081 try { 1082 if (mConnected) { 1083 mConnectionService.onCallAudioStateChanged(mConnectionId, state, 1084 null /*Session.Info*/); 1085 } 1086 } catch (RemoteException ignored) { 1087 } 1088 } 1089 1090 /** 1091 * Notifies this {@link RemoteConnection} that the user has requested an RTT session. 1092 * @param rttTextStream The object that should be used to send text to or receive text from 1093 * the in-call app. 1094 * @hide 1095 */ 1096 public void startRtt(@NonNull Connection.RttTextStream rttTextStream) { 1097 try { 1098 if (mConnected) { 1099 mConnectionService.startRtt(mConnectionId, rttTextStream.getFdFromInCall(), 1100 rttTextStream.getFdToInCall(), null /*Session.Info*/); 1101 } 1102 } catch (RemoteException ignored) { 1103 } 1104 } 1105 1106 /** 1107 * Notifies this {@link RemoteConnection} that it should terminate any existing RTT 1108 * session. No response to Telecom is needed for this method. 1109 * @hide 1110 */ 1111 public void stopRtt() { 1112 try { 1113 if (mConnected) { 1114 mConnectionService.stopRtt(mConnectionId, null /*Session.Info*/); 1115 } 1116 } catch (RemoteException ignored) { 1117 } 1118 } 1119 1120 /** 1121 * Notifies this {@link RemoteConnection} of a response to a previous remotely-initiated RTT 1122 * upgrade request sent via {@link Connection#sendRemoteRttRequest}. 1123 * Acceptance of the request is indicated by the supplied {@link RttTextStream} being non-null, 1124 * and rejection is indicated by {@code rttTextStream} being {@code null} 1125 * @hide 1126 * @param rttTextStream The object that should be used to send text to or receive text from 1127 * the in-call app. 1128 */ 1129 public void sendRttUpgradeResponse(@Nullable Connection.RttTextStream rttTextStream) { 1130 try { 1131 if (mConnected) { 1132 if (rttTextStream == null) { 1133 mConnectionService.respondToRttUpgradeRequest(mConnectionId, 1134 null, null, null /*Session.Info*/); 1135 } else { 1136 mConnectionService.respondToRttUpgradeRequest(mConnectionId, 1137 rttTextStream.getFdFromInCall(), rttTextStream.getFdToInCall(), 1138 null /*Session.Info*/); 1139 } 1140 } 1141 } catch (RemoteException ignored) { 1142 } 1143 } 1144 1145 /** 1146 * Obtain the {@code RemoteConnection}s with which this {@code RemoteConnection} may be 1147 * successfully asked to create a conference with. 1148 * 1149 * @return The {@code RemoteConnection}s with which this {@code RemoteConnection} may be 1150 * merged into a {@link RemoteConference}. 1151 */ 1152 public List<RemoteConnection> getConferenceableConnections() { 1153 return mUnmodifiableconferenceableConnections; 1154 } 1155 1156 /** 1157 * Obtain the {@code RemoteConference} that this {@code RemoteConnection} may be a part 1158 * of, or {@code null} if there is no such {@code RemoteConference}. 1159 * 1160 * @return A {@code RemoteConference} or {@code null}; 1161 */ 1162 public RemoteConference getConference() { 1163 return mConference; 1164 } 1165 1166 /** {@hide} */ 1167 String getId() { 1168 return mConnectionId; 1169 } 1170 1171 /** {@hide} */ 1172 IConnectionService getConnectionService() { 1173 return mConnectionService; 1174 } 1175 1176 /** 1177 * @hide 1178 */ 1179 void setState(final int state) { 1180 if (mState != state) { 1181 mState = state; 1182 for (CallbackRecord record: mCallbackRecords) { 1183 final RemoteConnection connection = this; 1184 final Callback callback = record.getCallback(); 1185 record.getHandler().post(new Runnable() { 1186 @Override 1187 public void run() { 1188 callback.onStateChanged(connection, state); 1189 } 1190 }); 1191 } 1192 } 1193 } 1194 1195 /** 1196 * @hide 1197 */ 1198 void setDisconnected(final DisconnectCause disconnectCause) { 1199 if (mState != Connection.STATE_DISCONNECTED) { 1200 mState = Connection.STATE_DISCONNECTED; 1201 mDisconnectCause = disconnectCause; 1202 1203 for (CallbackRecord record : mCallbackRecords) { 1204 final RemoteConnection connection = this; 1205 final Callback callback = record.getCallback(); 1206 record.getHandler().post(new Runnable() { 1207 @Override 1208 public void run() { 1209 callback.onDisconnected(connection, disconnectCause); 1210 } 1211 }); 1212 } 1213 } 1214 } 1215 1216 /** 1217 * @hide 1218 */ 1219 void setRingbackRequested(final boolean ringback) { 1220 if (mRingbackRequested != ringback) { 1221 mRingbackRequested = ringback; 1222 for (CallbackRecord record : mCallbackRecords) { 1223 final RemoteConnection connection = this; 1224 final Callback callback = record.getCallback(); 1225 record.getHandler().post(new Runnable() { 1226 @Override 1227 public void run() { 1228 callback.onRingbackRequested(connection, ringback); 1229 } 1230 }); 1231 } 1232 } 1233 } 1234 1235 /** 1236 * @hide 1237 */ 1238 void setConnectionCapabilities(final int connectionCapabilities) { 1239 mConnectionCapabilities = connectionCapabilities; 1240 for (CallbackRecord record : mCallbackRecords) { 1241 final RemoteConnection connection = this; 1242 final Callback callback = record.getCallback(); 1243 record.getHandler().post(new Runnable() { 1244 @Override 1245 public void run() { 1246 callback.onConnectionCapabilitiesChanged(connection, connectionCapabilities); 1247 } 1248 }); 1249 } 1250 } 1251 1252 /** 1253 * @hide 1254 */ 1255 void setConnectionProperties(final int connectionProperties) { 1256 mConnectionProperties = connectionProperties; 1257 for (CallbackRecord record : mCallbackRecords) { 1258 final RemoteConnection connection = this; 1259 final Callback callback = record.getCallback(); 1260 record.getHandler().post(new Runnable() { 1261 @Override 1262 public void run() { 1263 callback.onConnectionPropertiesChanged(connection, connectionProperties); 1264 } 1265 }); 1266 } 1267 } 1268 1269 /** 1270 * @hide 1271 */ 1272 void setDestroyed() { 1273 if (!mCallbackRecords.isEmpty()) { 1274 // Make sure that the callbacks are notified that the call is destroyed first. 1275 if (mState != Connection.STATE_DISCONNECTED) { 1276 setDisconnected( 1277 new DisconnectCause(DisconnectCause.ERROR, "Connection destroyed.")); 1278 } 1279 1280 for (CallbackRecord record : mCallbackRecords) { 1281 final RemoteConnection connection = this; 1282 final Callback callback = record.getCallback(); 1283 record.getHandler().post(new Runnable() { 1284 @Override 1285 public void run() { 1286 callback.onDestroyed(connection); 1287 } 1288 }); 1289 } 1290 mCallbackRecords.clear(); 1291 1292 mConnected = false; 1293 } 1294 } 1295 1296 /** 1297 * @hide 1298 */ 1299 void setPostDialWait(final String remainingDigits) { 1300 for (CallbackRecord record : mCallbackRecords) { 1301 final RemoteConnection connection = this; 1302 final Callback callback = record.getCallback(); 1303 record.getHandler().post(new Runnable() { 1304 @Override 1305 public void run() { 1306 callback.onPostDialWait(connection, remainingDigits); 1307 } 1308 }); 1309 } 1310 } 1311 1312 /** 1313 * @hide 1314 */ 1315 void onPostDialChar(final char nextChar) { 1316 for (CallbackRecord record : mCallbackRecords) { 1317 final RemoteConnection connection = this; 1318 final Callback callback = record.getCallback(); 1319 record.getHandler().post(new Runnable() { 1320 @Override 1321 public void run() { 1322 callback.onPostDialChar(connection, nextChar); 1323 } 1324 }); 1325 } 1326 } 1327 1328 /** 1329 * @hide 1330 */ 1331 void setVideoState(final int videoState) { 1332 mVideoState = videoState; 1333 for (CallbackRecord record : mCallbackRecords) { 1334 final RemoteConnection connection = this; 1335 final Callback callback = record.getCallback(); 1336 record.getHandler().post(new Runnable() { 1337 @Override 1338 public void run() { 1339 callback.onVideoStateChanged(connection, videoState); 1340 } 1341 }); 1342 } 1343 } 1344 1345 /** 1346 * @hide 1347 */ 1348 void setVideoProvider(final VideoProvider videoProvider) { 1349 mVideoProvider = videoProvider; 1350 for (CallbackRecord record : mCallbackRecords) { 1351 final RemoteConnection connection = this; 1352 final Callback callback = record.getCallback(); 1353 record.getHandler().post(new Runnable() { 1354 @Override 1355 public void run() { 1356 callback.onVideoProviderChanged(connection, videoProvider); 1357 } 1358 }); 1359 } 1360 } 1361 1362 /** @hide */ 1363 void setIsVoipAudioMode(final boolean isVoip) { 1364 mIsVoipAudioMode = isVoip; 1365 for (CallbackRecord record : mCallbackRecords) { 1366 final RemoteConnection connection = this; 1367 final Callback callback = record.getCallback(); 1368 record.getHandler().post(new Runnable() { 1369 @Override 1370 public void run() { 1371 callback.onVoipAudioChanged(connection, isVoip); 1372 } 1373 }); 1374 } 1375 } 1376 1377 /** @hide */ 1378 void setStatusHints(final StatusHints statusHints) { 1379 mStatusHints = statusHints; 1380 for (CallbackRecord record : mCallbackRecords) { 1381 final RemoteConnection connection = this; 1382 final Callback callback = record.getCallback(); 1383 record.getHandler().post(new Runnable() { 1384 @Override 1385 public void run() { 1386 callback.onStatusHintsChanged(connection, statusHints); 1387 } 1388 }); 1389 } 1390 } 1391 1392 /** @hide */ 1393 void setAddress(final Uri address, final int presentation) { 1394 mAddress = address; 1395 mAddressPresentation = presentation; 1396 for (CallbackRecord record : mCallbackRecords) { 1397 final RemoteConnection connection = this; 1398 final Callback callback = record.getCallback(); 1399 record.getHandler().post(new Runnable() { 1400 @Override 1401 public void run() { 1402 callback.onAddressChanged(connection, address, presentation); 1403 } 1404 }); 1405 } 1406 } 1407 1408 /** @hide */ 1409 void setCallerDisplayName(final String callerDisplayName, final int presentation) { 1410 mCallerDisplayName = callerDisplayName; 1411 mCallerDisplayNamePresentation = presentation; 1412 for (CallbackRecord record : mCallbackRecords) { 1413 final RemoteConnection connection = this; 1414 final Callback callback = record.getCallback(); 1415 record.getHandler().post(new Runnable() { 1416 @Override 1417 public void run() { 1418 callback.onCallerDisplayNameChanged( 1419 connection, callerDisplayName, presentation); 1420 } 1421 }); 1422 } 1423 } 1424 1425 /** @hide */ 1426 void setConferenceableConnections(final List<RemoteConnection> conferenceableConnections) { 1427 mConferenceableConnections.clear(); 1428 mConferenceableConnections.addAll(conferenceableConnections); 1429 for (CallbackRecord record : mCallbackRecords) { 1430 final RemoteConnection connection = this; 1431 final Callback callback = record.getCallback(); 1432 record.getHandler().post(new Runnable() { 1433 @Override 1434 public void run() { 1435 callback.onConferenceableConnectionsChanged( 1436 connection, mUnmodifiableconferenceableConnections); 1437 } 1438 }); 1439 } 1440 } 1441 1442 /** @hide */ 1443 void setConference(final RemoteConference conference) { 1444 if (mConference != conference) { 1445 mConference = conference; 1446 for (CallbackRecord record : mCallbackRecords) { 1447 final RemoteConnection connection = this; 1448 final Callback callback = record.getCallback(); 1449 record.getHandler().post(new Runnable() { 1450 @Override 1451 public void run() { 1452 callback.onConferenceChanged(connection, conference); 1453 } 1454 }); 1455 } 1456 } 1457 } 1458 1459 /** @hide */ 1460 void putExtras(final Bundle extras) { 1461 if (extras == null) { 1462 return; 1463 } 1464 if (mExtras == null) { 1465 mExtras = new Bundle(); 1466 } 1467 mExtras.putAll(extras); 1468 1469 notifyExtrasChanged(); 1470 } 1471 1472 /** @hide */ 1473 void removeExtras(List<String> keys) { 1474 if (mExtras == null || keys == null || keys.isEmpty()) { 1475 return; 1476 } 1477 for (String key : keys) { 1478 mExtras.remove(key); 1479 } 1480 1481 notifyExtrasChanged(); 1482 } 1483 1484 private void notifyExtrasChanged() { 1485 for (CallbackRecord record : mCallbackRecords) { 1486 final RemoteConnection connection = this; 1487 final Callback callback = record.getCallback(); 1488 record.getHandler().post(new Runnable() { 1489 @Override 1490 public void run() { 1491 callback.onExtrasChanged(connection, mExtras); 1492 } 1493 }); 1494 } 1495 } 1496 1497 /** @hide */ 1498 void onConnectionEvent(final String event, final Bundle extras) { 1499 for (CallbackRecord record : mCallbackRecords) { 1500 final RemoteConnection connection = this; 1501 final Callback callback = record.getCallback(); 1502 record.getHandler().post(new Runnable() { 1503 @Override 1504 public void run() { 1505 callback.onConnectionEvent(connection, event, extras); 1506 } 1507 }); 1508 } 1509 } 1510 1511 /** @hide */ 1512 void onRttInitiationSuccess() { 1513 for (CallbackRecord record : mCallbackRecords) { 1514 final RemoteConnection connection = this; 1515 final Callback callback = record.getCallback(); 1516 record.getHandler().post( 1517 () -> callback.onRttInitiationSuccess(connection)); 1518 } 1519 } 1520 1521 /** @hide */ 1522 void onRttInitiationFailure(int reason) { 1523 for (CallbackRecord record : mCallbackRecords) { 1524 final RemoteConnection connection = this; 1525 final Callback callback = record.getCallback(); 1526 record.getHandler().post( 1527 () -> callback.onRttInitiationFailure(connection, reason)); 1528 } 1529 } 1530 1531 /** @hide */ 1532 void onRttSessionRemotelyTerminated() { 1533 for (CallbackRecord record : mCallbackRecords) { 1534 final RemoteConnection connection = this; 1535 final Callback callback = record.getCallback(); 1536 record.getHandler().post( 1537 () -> callback.onRttSessionRemotelyTerminated(connection)); 1538 } 1539 } 1540 1541 /** @hide */ 1542 void onRemoteRttRequest() { 1543 for (CallbackRecord record : mCallbackRecords) { 1544 final RemoteConnection connection = this; 1545 final Callback callback = record.getCallback(); 1546 record.getHandler().post( 1547 () -> callback.onRemoteRttRequest(connection)); 1548 } 1549 } 1550 1551 /** 1552 /** 1553 * Create a RemoteConnection represents a failure, and which will be in 1554 * {@link Connection#STATE_DISCONNECTED}. Attempting to use it for anything will almost 1555 * certainly result in bad things happening. Do not do this. 1556 * 1557 * @return a failed {@link RemoteConnection} 1558 * 1559 * @hide 1560 */ 1561 public static RemoteConnection failure(DisconnectCause disconnectCause) { 1562 return new RemoteConnection(disconnectCause); 1563 } 1564 1565 private static final class CallbackRecord extends Callback { 1566 private final Callback mCallback; 1567 private final Handler mHandler; 1568 1569 public CallbackRecord(Callback callback, Handler handler) { 1570 mCallback = callback; 1571 mHandler = handler; 1572 } 1573 1574 public Callback getCallback() { 1575 return mCallback; 1576 } 1577 1578 public Handler getHandler() { 1579 return mHandler; 1580 } 1581 } 1582} 1583