2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package android.telecom;
19 import com.android.internal.telecom.IConnectionService;
20 import com.android.internal.telecom.IVideoCallback;
21 import com.android.internal.telecom.IVideoProvider;
23 import android.annotation.Nullable;
24 import android.annotation.SystemApi;
25 import android.hardware.camera2.CameraManager;
26 import android.net.Uri;
27 import android.os.Bundle;
28 import android.os.Handler;
29 import android.os.IBinder;
30 import android.os.RemoteException;
31 import android.view.Surface;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.List;
37 import java.util.concurrent.ConcurrentHashMap;
40 * A connection provided to a {@link ConnectionService} by another {@code ConnectionService}
41 * running in a different process.
43 * @see ConnectionService#createRemoteOutgoingConnection(PhoneAccountHandle, ConnectionRequest)
44 * @see ConnectionService#createRemoteIncomingConnection(PhoneAccountHandle, ConnectionRequest)
46 public final class RemoteConnection {
49 * Callback base class for {@link RemoteConnection}.
51 public static abstract class Callback {
53 * Invoked when the state of this {@code RemoteConnection} has changed. See
54 * {@link #getState()}.
56 * @param connection The {@code RemoteConnection} invoking this method.
57 * @param state The new state of the {@code RemoteConnection}.
59 public void onStateChanged(RemoteConnection connection, int state) {}
62 * Invoked when this {@code RemoteConnection} is disconnected.
64 * @param connection The {@code RemoteConnection} invoking this method.
65 * @param disconnectCause The ({@see DisconnectCause}) associated with this failed
68 public void onDisconnected(
69 RemoteConnection connection,
70 DisconnectCause disconnectCause) {}
73 * Invoked when this {@code RemoteConnection} is requesting ringback. See
74 * {@link #isRingbackRequested()}.
76 * @param connection The {@code RemoteConnection} invoking this method.
77 * @param ringback Whether the {@code RemoteConnection} is requesting ringback.
79 public void onRingbackRequested(RemoteConnection connection, boolean ringback) {}
82 * Indicates that the call capabilities of this {@code RemoteConnection} have changed.
83 * See {@link #getConnectionCapabilities()}.
85 * @param connection The {@code RemoteConnection} invoking this method.
86 * @param connectionCapabilities The new capabilities of the {@code RemoteConnection}.
88 public void onConnectionCapabilitiesChanged(
89 RemoteConnection connection,
90 int connectionCapabilities) {}
93 * Indicates that the call properties of this {@code RemoteConnection} have changed.
94 * See {@link #getConnectionProperties()}.
96 * @param connection The {@code RemoteConnection} invoking this method.
97 * @param connectionProperties The new properties of the {@code RemoteConnection}.
100 public void onConnectionPropertiesChanged(
101 RemoteConnection connection,
102 int connectionProperties) {}
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.
110 * @param connection The {@code RemoteConnection} invoking this method.
111 * @param remainingPostDialSequence The post-dial characters that remain to be sent.
113 public void onPostDialWait(RemoteConnection connection, String remainingPostDialSequence) {}
116 * Invoked when the post-dial sequence in the outgoing {@code Connection} has processed
119 * @param connection The {@code RemoteConnection} invoking this method.
120 * @param nextChar The character being processed.
122 public void onPostDialChar(RemoteConnection connection, char nextChar) {}
125 * Indicates that the VOIP audio status of this {@code RemoteConnection} has changed.
126 * See {@link #isVoipAudioMode()}.
128 * @param connection The {@code RemoteConnection} invoking this method.
129 * @param isVoip Whether the new audio state of the {@code RemoteConnection} is VOIP.
131 public void onVoipAudioChanged(RemoteConnection connection, boolean isVoip) {}
134 * Indicates that the status hints of this {@code RemoteConnection} have changed. See
135 * {@link #getStatusHints()} ()}.
137 * @param connection The {@code RemoteConnection} invoking this method.
138 * @param statusHints The new status hints of the {@code RemoteConnection}.
140 public void onStatusHintsChanged(RemoteConnection connection, StatusHints statusHints) {}
143 * Indicates that the address (e.g., phone number) of this {@code RemoteConnection} has
144 * changed. See {@link #getAddress()} and {@link #getAddressPresentation()}.
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.
151 public void onAddressChanged(RemoteConnection connection, Uri address, int presentation) {}
154 * Indicates that the caller display name of this {@code RemoteConnection} has changed.
155 * See {@link #getCallerDisplayName()} and {@link #getCallerDisplayNamePresentation()}.
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.
162 public void onCallerDisplayNameChanged(
163 RemoteConnection connection, String callerDisplayName, int presentation) {}
166 * Indicates that the video state of this {@code RemoteConnection} has changed.
167 * See {@link #getVideoState()}.
169 * @param connection The {@code RemoteConnection} invoking this method.
170 * @param videoState The new video state of the {@code RemoteConnection}.
172 public void onVideoStateChanged(RemoteConnection connection, int videoState) {}
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.
178 * @param connection The {@code RemoteConnection} invoking this method.
180 public void onDestroyed(RemoteConnection connection) {}
183 * Indicates that the {@code RemoteConnection}s with which this {@code RemoteConnection}
184 * may be asked to create a conference has changed.
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.
190 public void onConferenceableConnectionsChanged(
191 RemoteConnection connection,
192 List<RemoteConnection> conferenceableConnections) {}
195 * Indicates that the {@code VideoProvider} associated with this {@code RemoteConnection}
198 * @param connection The {@code RemoteConnection} invoking this method.
199 * @param videoProvider The new {@code VideoProvider} associated with this
200 * {@code RemoteConnection}.
202 public void onVideoProviderChanged(
203 RemoteConnection connection, VideoProvider videoProvider) {}
206 * Indicates that the {@code RemoteConference} that this {@code RemoteConnection} is a part
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}.
213 public void onConferenceChanged(
214 RemoteConnection connection,
215 RemoteConference conference) {}
218 * Handles changes to the {@code RemoteConnection} extras.
220 * @param connection The {@code RemoteConnection} invoking this method.
221 * @param extras The extras containing other information associated with the connection.
223 public void onExtrasChanged(RemoteConnection connection, @Nullable Bundle extras) {}
226 * Handles a connection event propagated to this {@link RemoteConnection}.
228 * Connection events originate from {@link Connection#sendConnectionEvent(String, Bundle)}.
230 * @param connection The {@code RemoteConnection} invoking this method.
231 * @param event The connection event.
232 * @param extras Extras associated with the event.
235 public void onConnectionEvent(RemoteConnection connection, String event, Bundle extras) {}
239 * {@link RemoteConnection.VideoProvider} associated with a {@link RemoteConnection}. Used to
240 * receive video related events and control the video associated with a
241 * {@link RemoteConnection}.
243 * @see Connection.VideoProvider
245 public static class VideoProvider {
248 * Callback class used by the {@link RemoteConnection.VideoProvider} to relay events from
249 * the {@link Connection.VideoProvider}.
251 public abstract static class Callback {
253 * Reports a session modification request received from the
254 * {@link Connection.VideoProvider} associated with a {@link RemoteConnection}.
256 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method.
257 * @param videoProfile The requested video call profile.
258 * @see InCallService.VideoCall.Callback#onSessionModifyRequestReceived(VideoProfile)
259 * @see Connection.VideoProvider#receiveSessionModifyRequest(VideoProfile)
261 public void onSessionModifyRequestReceived(
262 VideoProvider videoProvider,
263 VideoProfile videoProfile) {}
266 * Reports a session modification response received from the
267 * {@link Connection.VideoProvider} associated with a {@link RemoteConnection}.
269 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method.
270 * @param status Status of the session modify request.
271 * @param requestedProfile The original request which was sent to the peer device.
272 * @param responseProfile The actual profile changes made by the peer device.
273 * @see InCallService.VideoCall.Callback#onSessionModifyResponseReceived(int,
274 * VideoProfile, VideoProfile)
275 * @see Connection.VideoProvider#receiveSessionModifyResponse(int, VideoProfile,
278 public void onSessionModifyResponseReceived(
279 VideoProvider videoProvider,
281 VideoProfile requestedProfile,
282 VideoProfile responseProfile) {}
285 * Reports a call session event received from the {@link Connection.VideoProvider}
286 * associated with a {@link RemoteConnection}.
288 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method.
289 * @param event The event.
290 * @see InCallService.VideoCall.Callback#onCallSessionEvent(int)
291 * @see Connection.VideoProvider#handleCallSessionEvent(int)
293 public void onCallSessionEvent(VideoProvider videoProvider, int event) {}
296 * Reports a change in the peer video dimensions received from the
297 * {@link Connection.VideoProvider} associated with a {@link RemoteConnection}.
299 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method.
300 * @param width The updated peer video width.
301 * @param height The updated peer video height.
302 * @see InCallService.VideoCall.Callback#onPeerDimensionsChanged(int, int)
303 * @see Connection.VideoProvider#changePeerDimensions(int, int)
305 public void onPeerDimensionsChanged(VideoProvider videoProvider, int width,
309 * Reports a change in the data usage (in bytes) received from the
310 * {@link Connection.VideoProvider} associated with a {@link RemoteConnection}.
312 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method.
313 * @param dataUsage The updated data usage (in bytes).
314 * @see InCallService.VideoCall.Callback#onCallDataUsageChanged(long)
315 * @see Connection.VideoProvider#setCallDataUsage(long)
317 public void onCallDataUsageChanged(VideoProvider videoProvider, long dataUsage) {}
320 * Reports a change in the capabilities of the current camera, received from the
321 * {@link Connection.VideoProvider} associated with a {@link RemoteConnection}.
323 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method.
324 * @param cameraCapabilities The changed camera capabilities.
325 * @see InCallService.VideoCall.Callback#onCameraCapabilitiesChanged(
326 * VideoProfile.CameraCapabilities)
327 * @see Connection.VideoProvider#changeCameraCapabilities(
328 * VideoProfile.CameraCapabilities)
330 public void onCameraCapabilitiesChanged(
331 VideoProvider videoProvider,
332 VideoProfile.CameraCapabilities cameraCapabilities) {}
335 * Reports a change in the video quality received from the
336 * {@link Connection.VideoProvider} associated with a {@link RemoteConnection}.
338 * @param videoProvider The {@link RemoteConnection.VideoProvider} invoking this method.
339 * @param videoQuality The updated peer video quality.
340 * @see InCallService.VideoCall.Callback#onVideoQualityChanged(int)
341 * @see Connection.VideoProvider#changeVideoQuality(int)
343 public void onVideoQualityChanged(VideoProvider videoProvider, int videoQuality) {}
346 private final IVideoCallback mVideoCallbackDelegate = new IVideoCallback() {
348 public void receiveSessionModifyRequest(VideoProfile videoProfile) {
349 for (Callback l : mCallbacks) {
350 l.onSessionModifyRequestReceived(VideoProvider.this, videoProfile);
355 public void receiveSessionModifyResponse(int status, VideoProfile requestedProfile,
356 VideoProfile responseProfile) {
357 for (Callback l : mCallbacks) {
358 l.onSessionModifyResponseReceived(
367 public void handleCallSessionEvent(int event) {
368 for (Callback l : mCallbacks) {
369 l.onCallSessionEvent(VideoProvider.this, event);
374 public void changePeerDimensions(int width, int height) {
375 for (Callback l : mCallbacks) {
376 l.onPeerDimensionsChanged(VideoProvider.this, width, height);
381 public void changeCallDataUsage(long dataUsage) {
382 for (Callback l : mCallbacks) {
383 l.onCallDataUsageChanged(VideoProvider.this, dataUsage);
388 public void changeCameraCapabilities(
389 VideoProfile.CameraCapabilities cameraCapabilities) {
390 for (Callback l : mCallbacks) {
391 l.onCameraCapabilitiesChanged(VideoProvider.this, cameraCapabilities);
396 public void changeVideoQuality(int videoQuality) {
397 for (Callback l : mCallbacks) {
398 l.onVideoQualityChanged(VideoProvider.this, videoQuality);
403 public IBinder asBinder() {
408 private final VideoCallbackServant mVideoCallbackServant =
409 new VideoCallbackServant(mVideoCallbackDelegate);
411 private final IVideoProvider mVideoProviderBinder;
414 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
415 * load factor before resizing, 1 means we only expect a single thread to
416 * access the map so make only a single shard
418 private final Set<Callback> mCallbacks = Collections.newSetFromMap(
419 new ConcurrentHashMap<Callback, Boolean>(8, 0.9f, 1));
421 VideoProvider(IVideoProvider videoProviderBinder) {
422 mVideoProviderBinder = videoProviderBinder;
424 mVideoProviderBinder.addVideoCallback(mVideoCallbackServant.getStub().asBinder());
425 } catch (RemoteException e) {
430 * Registers a callback to receive commands and state changes for video calls.
432 * @param l The video call callback.
434 public void registerCallback(Callback l) {
439 * Clears the video call callback set via {@link #registerCallback}.
441 * @param l The video call callback to clear.
443 public void unregisterCallback(Callback l) {
444 mCallbacks.remove(l);
448 * Sets the camera to be used for the outgoing video for the
449 * {@link RemoteConnection.VideoProvider}.
451 * @param cameraId The id of the camera (use ids as reported by
452 * {@link CameraManager#getCameraIdList()}).
453 * @see Connection.VideoProvider#onSetCamera(String)
455 public void setCamera(String cameraId) {
457 mVideoProviderBinder.setCamera(cameraId);
458 } catch (RemoteException e) {
463 * Sets the surface to be used for displaying a preview of what the user's camera is
464 * currently capturing for the {@link RemoteConnection.VideoProvider}.
466 * @param surface The {@link Surface}.
467 * @see Connection.VideoProvider#onSetPreviewSurface(Surface)
469 public void setPreviewSurface(Surface surface) {
471 mVideoProviderBinder.setPreviewSurface(surface);
472 } catch (RemoteException e) {
477 * Sets the surface to be used for displaying the video received from the remote device for
478 * the {@link RemoteConnection.VideoProvider}.
480 * @param surface The {@link Surface}.
481 * @see Connection.VideoProvider#onSetDisplaySurface(Surface)
483 public void setDisplaySurface(Surface surface) {
485 mVideoProviderBinder.setDisplaySurface(surface);
486 } catch (RemoteException e) {
491 * Sets the device orientation, in degrees, for the {@link RemoteConnection.VideoProvider}.
492 * Assumes that a standard portrait orientation of the device is 0 degrees.
494 * @param rotation The device orientation, in degrees.
495 * @see Connection.VideoProvider#onSetDeviceOrientation(int)
497 public void setDeviceOrientation(int rotation) {
499 mVideoProviderBinder.setDeviceOrientation(rotation);
500 } catch (RemoteException e) {
505 * Sets camera zoom ratio for the {@link RemoteConnection.VideoProvider}.
507 * @param value The camera zoom ratio.
508 * @see Connection.VideoProvider#onSetZoom(float)
510 public void setZoom(float value) {
512 mVideoProviderBinder.setZoom(value);
513 } catch (RemoteException e) {
518 * Issues a request to modify the properties of the current video session for the
519 * {@link RemoteConnection.VideoProvider}.
521 * @param fromProfile The video profile prior to the request.
522 * @param toProfile The video profile with the requested changes made.
523 * @see Connection.VideoProvider#onSendSessionModifyRequest(VideoProfile, VideoProfile)
525 public void sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
527 mVideoProviderBinder.sendSessionModifyRequest(fromProfile, toProfile);
528 } catch (RemoteException e) {
533 * Provides a response to a request to change the current call video session
534 * properties for the {@link RemoteConnection.VideoProvider}.
536 * @param responseProfile The response call video properties.
537 * @see Connection.VideoProvider#onSendSessionModifyResponse(VideoProfile)
539 public void sendSessionModifyResponse(VideoProfile responseProfile) {
541 mVideoProviderBinder.sendSessionModifyResponse(responseProfile);
542 } catch (RemoteException e) {
547 * Issues a request to retrieve the capabilities of the current camera for the
548 * {@link RemoteConnection.VideoProvider}.
550 * @see Connection.VideoProvider#onRequestCameraCapabilities()
552 public void requestCameraCapabilities() {
554 mVideoProviderBinder.requestCameraCapabilities();
555 } catch (RemoteException e) {
560 * Issues a request to retrieve the data usage (in bytes) of the video portion of the
561 * {@link RemoteConnection} for the {@link RemoteConnection.VideoProvider}.
563 * @see Connection.VideoProvider#onRequestConnectionDataUsage()
565 public void requestCallDataUsage() {
567 mVideoProviderBinder.requestCallDataUsage();
568 } catch (RemoteException e) {
573 * Sets the {@link Uri} of an image to be displayed to the peer device when the video signal
574 * is paused, for the {@link RemoteConnection.VideoProvider}.
576 * @see Connection.VideoProvider#onSetPauseImage(Uri)
578 public void setPauseImage(Uri uri) {
580 mVideoProviderBinder.setPauseImage(uri);
581 } catch (RemoteException e) {
586 private IConnectionService mConnectionService;
587 private final String mConnectionId;
589 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
590 * load factor before resizing, 1 means we only expect a single thread to
591 * access the map so make only a single shard
593 private final Set<CallbackRecord> mCallbackRecords = Collections.newSetFromMap(
594 new ConcurrentHashMap<CallbackRecord, Boolean>(8, 0.9f, 1));
595 private final List<RemoteConnection> mConferenceableConnections = new ArrayList<>();
596 private final List<RemoteConnection> mUnmodifiableconferenceableConnections =
597 Collections.unmodifiableList(mConferenceableConnections);
599 private int mState = Connection.STATE_NEW;
600 private DisconnectCause mDisconnectCause;
601 private boolean mRingbackRequested;
602 private boolean mConnected;
603 private int mConnectionCapabilities;
604 private int mConnectionProperties;
605 private int mVideoState;
606 private VideoProvider mVideoProvider;
607 private boolean mIsVoipAudioMode;
608 private StatusHints mStatusHints;
609 private Uri mAddress;
610 private int mAddressPresentation;
611 private String mCallerDisplayName;
612 private int mCallerDisplayNamePresentation;
613 private RemoteConference mConference;
614 private Bundle mExtras;
621 IConnectionService connectionService,
622 ConnectionRequest request) {
624 mConnectionService = connectionService;
626 mState = Connection.STATE_INITIALIZING;
632 RemoteConnection(String callId, IConnectionService connectionService,
633 ParcelableConnection connection) {
634 mConnectionId = callId;
635 mConnectionService = connectionService;
637 mState = connection.getState();
638 mDisconnectCause = connection.getDisconnectCause();
639 mRingbackRequested = connection.isRingbackRequested();
640 mConnectionCapabilities = connection.getConnectionCapabilities();
641 mConnectionProperties = connection.getConnectionProperties();
642 mVideoState = connection.getVideoState();
643 mVideoProvider = new RemoteConnection.VideoProvider(connection.getVideoProvider());
644 mIsVoipAudioMode = connection.getIsVoipAudioMode();
645 mStatusHints = connection.getStatusHints();
646 mAddress = connection.getHandle();
647 mAddressPresentation = connection.getHandlePresentation();
648 mCallerDisplayName = connection.getCallerDisplayName();
649 mCallerDisplayNamePresentation = connection.getCallerDisplayNamePresentation();
654 * Create a RemoteConnection which is used for failed connections. Note that using it for any
655 * "real" purpose will almost certainly fail. Callers should note the failure and act
656 * accordingly (moving on to another RemoteConnection, for example)
658 * @param disconnectCause The reason for the failed connection.
661 RemoteConnection(DisconnectCause disconnectCause) {
662 mConnectionId = "NULL";
664 mState = Connection.STATE_DISCONNECTED;
665 mDisconnectCause = disconnectCause;
669 * Adds a callback to this {@code RemoteConnection}.
671 * @param callback A {@code Callback}.
673 public void registerCallback(Callback callback) {
674 registerCallback(callback, new Handler());
678 * Adds a callback to this {@code RemoteConnection}.
680 * @param callback A {@code Callback}.
681 * @param handler A {@code Handler} which command and status changes will be delivered to.
683 public void registerCallback(Callback callback, Handler handler) {
684 unregisterCallback(callback);
685 if (callback != null && handler != null) {
686 mCallbackRecords.add(new CallbackRecord(callback, handler));
691 * Removes a callback from this {@code RemoteConnection}.
693 * @param callback A {@code Callback}.
695 public void unregisterCallback(Callback callback) {
696 if (callback != null) {
697 for (CallbackRecord record : mCallbackRecords) {
698 if (record.getCallback() == callback) {
699 mCallbackRecords.remove(record);
707 * Obtains the state of this {@code RemoteConnection}.
709 * @return A state value, chosen from the {@code STATE_*} constants.
711 public int getState() {
716 * Obtains the reason why this {@code RemoteConnection} may have been disconnected.
718 * @return For a {@link Connection#STATE_DISCONNECTED} {@code RemoteConnection}, the
719 * disconnect cause expressed as a code chosen from among those declared in
720 * {@link DisconnectCause}.
722 public DisconnectCause getDisconnectCause() {
723 return mDisconnectCause;
727 * Obtains the capabilities of this {@code RemoteConnection}.
729 * @return A bitmask of the capabilities of the {@code RemoteConnection}, as defined in
730 * the {@code CAPABILITY_*} constants in class {@link Connection}.
732 public int getConnectionCapabilities() {
733 return mConnectionCapabilities;
737 * Obtains the properties of this {@code RemoteConnection}.
739 * @return A bitmask of the properties of the {@code RemoteConnection}, as defined in the
740 * {@code PROPERTY_*} constants in class {@link Connection}.
743 public int getConnectionProperties() {
744 return mConnectionProperties;
748 * Determines if the audio mode of this {@code RemoteConnection} is VOIP.
750 * @return {@code true} if the {@code RemoteConnection}'s current audio mode is VOIP.
752 public boolean isVoipAudioMode() {
753 return mIsVoipAudioMode;
757 * Obtains status hints pertaining to this {@code RemoteConnection}.
759 * @return The current {@link StatusHints} of this {@code RemoteConnection},
760 * or {@code null} if none have been set.
762 public StatusHints getStatusHints() {
767 * Obtains the address of this {@code RemoteConnection}.
769 * @return The address (e.g., phone number) to which the {@code RemoteConnection}
770 * is currently connected.
772 public Uri getAddress() {
777 * Obtains the presentation requirements for the address of this {@code RemoteConnection}.
779 * @return The presentation requirements for the address. See
780 * {@link TelecomManager} for valid values.
782 public int getAddressPresentation() {
783 return mAddressPresentation;
787 * Obtains the display name for this {@code RemoteConnection}'s caller.
789 * @return The display name for the caller.
791 public CharSequence getCallerDisplayName() {
792 return mCallerDisplayName;
796 * Obtains the presentation requirements for this {@code RemoteConnection}'s
797 * caller's display name.
799 * @return The presentation requirements for the caller display name. See
800 * {@link TelecomManager} for valid values.
802 public int getCallerDisplayNamePresentation() {
803 return mCallerDisplayNamePresentation;
807 * Obtains the video state of this {@code RemoteConnection}.
809 * @return The video state of the {@code RemoteConnection}. See {@link VideoProfile}.
811 public int getVideoState() {
816 * Obtains the video provider of this {@code RemoteConnection}.
817 * @return The video provider associated with this {@code RemoteConnection}.
819 public final VideoProvider getVideoProvider() {
820 return mVideoProvider;
824 * Obtain the extras associated with this {@code RemoteConnection}.
826 * @return The extras for this connection.
828 public final Bundle getExtras() {
833 * Determines whether this {@code RemoteConnection} is requesting ringback.
835 * @return Whether the {@code RemoteConnection} is requesting that the framework play a
836 * ringback tone on its behalf.
838 public boolean isRingbackRequested() {
839 return mRingbackRequested;
843 * Instructs this {@code RemoteConnection} to abort.
845 public void abort() {
848 mConnectionService.abort(mConnectionId);
850 } catch (RemoteException ignored) {
855 * Instructs this {@link Connection#STATE_RINGING} {@code RemoteConnection} to answer.
857 public void answer() {
860 mConnectionService.answer(mConnectionId);
862 } catch (RemoteException ignored) {
867 * Instructs this {@link Connection#STATE_RINGING} {@code RemoteConnection} to answer.
868 * @param videoState The video state in which to answer the call.
871 public void answer(int videoState) {
874 mConnectionService.answerVideo(mConnectionId, videoState);
876 } catch (RemoteException ignored) {
881 * Instructs this {@link Connection#STATE_RINGING} {@code RemoteConnection} to reject.
883 public void reject() {
886 mConnectionService.reject(mConnectionId);
888 } catch (RemoteException ignored) {
893 * Instructs this {@code RemoteConnection} to go on hold.
898 mConnectionService.hold(mConnectionId);
900 } catch (RemoteException ignored) {
905 * Instructs this {@link Connection#STATE_HOLDING} call to release from hold.
907 public void unhold() {
910 mConnectionService.unhold(mConnectionId);
912 } catch (RemoteException ignored) {
917 * Instructs this {@code RemoteConnection} to disconnect.
919 public void disconnect() {
922 mConnectionService.disconnect(mConnectionId);
924 } catch (RemoteException ignored) {
929 * Instructs this {@code RemoteConnection} to play a dual-tone multi-frequency signaling
932 * Any other currently playing DTMF tone in the specified call is immediately stopped.
934 * @param digit A character representing the DTMF digit for which to play the tone. This
935 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
937 public void playDtmfTone(char digit) {
940 mConnectionService.playDtmfTone(mConnectionId, digit);
942 } catch (RemoteException ignored) {
947 * Instructs this {@code RemoteConnection} to stop any dual-tone multi-frequency signaling
948 * (DTMF) tone currently playing.
950 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
951 * currently playing, this method will do nothing.
953 public void stopDtmfTone() {
956 mConnectionService.stopDtmfTone(mConnectionId);
958 } catch (RemoteException ignored) {
963 * Instructs this {@code RemoteConnection} to continue playing a post-dial DTMF string.
965 * A post-dial DTMF string is a string of digits following the first instance of either
966 * {@link TelecomManager#DTMF_CHARACTER_WAIT} or {@link TelecomManager#DTMF_CHARACTER_PAUSE}.
967 * These digits are immediately sent as DTMF tones to the recipient as soon as the
968 * connection is made.
970 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
971 * {@code RemoteConnection} will temporarily pause playing the tones for a pre-defined period
974 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
975 * {@code RemoteConnection} will pause playing the tones and notify callbacks via
976 * {@link Callback#onPostDialWait(RemoteConnection, String)}. At this point, the in-call app
977 * should display to the user an indication of this state and an affordance to continue
978 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
979 * app should invoke the {@link #postDialContinue(boolean)} method.
981 * @param proceed Whether or not to continue with the post-dial sequence.
983 public void postDialContinue(boolean proceed) {
986 mConnectionService.onPostDialContinue(mConnectionId, proceed);
988 } catch (RemoteException ignored) {
993 * Instructs this {@link RemoteConnection} to pull itself to the local device.
995 * See {@link Call#pullExternalCall()} for more information.
998 public void pullExternalCall() {
1001 mConnectionService.pullExternalCall(mConnectionId);
1003 } catch (RemoteException ignored) {
1008 * Set the audio state of this {@code RemoteConnection}.
1010 * @param state The audio state of this {@code RemoteConnection}.
1012 * @deprecated Use {@link #setCallAudioState(CallAudioState) instead.
1016 public void setAudioState(AudioState state) {
1017 setCallAudioState(new CallAudioState(state));
1021 * Set the audio state of this {@code RemoteConnection}.
1023 * @param state The audio state of this {@code RemoteConnection}.
1025 public void setCallAudioState(CallAudioState state) {
1028 mConnectionService.onCallAudioStateChanged(mConnectionId, state);
1030 } catch (RemoteException ignored) {
1035 * Obtain the {@code RemoteConnection}s with which this {@code RemoteConnection} may be
1036 * successfully asked to create a conference with.
1038 * @return The {@code RemoteConnection}s with which this {@code RemoteConnection} may be
1039 * merged into a {@link RemoteConference}.
1041 public List<RemoteConnection> getConferenceableConnections() {
1042 return mUnmodifiableconferenceableConnections;
1046 * Obtain the {@code RemoteConference} that this {@code RemoteConnection} may be a part
1047 * of, or {@code null} if there is no such {@code RemoteConference}.
1049 * @return A {@code RemoteConference} or {@code null};
1051 public RemoteConference getConference() {
1057 return mConnectionId;
1061 IConnectionService getConnectionService() {
1062 return mConnectionService;
1068 void setState(final int state) {
1069 if (mState != state) {
1071 for (CallbackRecord record: mCallbackRecords) {
1072 final RemoteConnection connection = this;
1073 final Callback callback = record.getCallback();
1074 record.getHandler().post(new Runnable() {
1077 callback.onStateChanged(connection, state);
1087 void setDisconnected(final DisconnectCause disconnectCause) {
1088 if (mState != Connection.STATE_DISCONNECTED) {
1089 mState = Connection.STATE_DISCONNECTED;
1090 mDisconnectCause = disconnectCause;
1092 for (CallbackRecord record : mCallbackRecords) {
1093 final RemoteConnection connection = this;
1094 final Callback callback = record.getCallback();
1095 record.getHandler().post(new Runnable() {
1098 callback.onDisconnected(connection, disconnectCause);
1108 void setRingbackRequested(final boolean ringback) {
1109 if (mRingbackRequested != ringback) {
1110 mRingbackRequested = ringback;
1111 for (CallbackRecord record : mCallbackRecords) {
1112 final RemoteConnection connection = this;
1113 final Callback callback = record.getCallback();
1114 record.getHandler().post(new Runnable() {
1117 callback.onRingbackRequested(connection, ringback);
1127 void setConnectionCapabilities(final int connectionCapabilities) {
1128 mConnectionCapabilities = connectionCapabilities;
1129 for (CallbackRecord record : mCallbackRecords) {
1130 final RemoteConnection connection = this;
1131 final Callback callback = record.getCallback();
1132 record.getHandler().post(new Runnable() {
1135 callback.onConnectionCapabilitiesChanged(connection, connectionCapabilities);
1144 void setConnectionProperties(final int connectionProperties) {
1145 mConnectionProperties = connectionProperties;
1146 for (CallbackRecord record : mCallbackRecords) {
1147 final RemoteConnection connection = this;
1148 final Callback callback = record.getCallback();
1149 record.getHandler().post(new Runnable() {
1152 callback.onConnectionPropertiesChanged(connection, connectionProperties);
1161 void setDestroyed() {
1162 if (!mCallbackRecords.isEmpty()) {
1163 // Make sure that the callbacks are notified that the call is destroyed first.
1164 if (mState != Connection.STATE_DISCONNECTED) {
1166 new DisconnectCause(DisconnectCause.ERROR, "Connection destroyed."));
1169 for (CallbackRecord record : mCallbackRecords) {
1170 final RemoteConnection connection = this;
1171 final Callback callback = record.getCallback();
1172 record.getHandler().post(new Runnable() {
1175 callback.onDestroyed(connection);
1179 mCallbackRecords.clear();
1188 void setPostDialWait(final String remainingDigits) {
1189 for (CallbackRecord record : mCallbackRecords) {
1190 final RemoteConnection connection = this;
1191 final Callback callback = record.getCallback();
1192 record.getHandler().post(new Runnable() {
1195 callback.onPostDialWait(connection, remainingDigits);
1204 void onPostDialChar(final char nextChar) {
1205 for (CallbackRecord record : mCallbackRecords) {
1206 final RemoteConnection connection = this;
1207 final Callback callback = record.getCallback();
1208 record.getHandler().post(new Runnable() {
1211 callback.onPostDialChar(connection, nextChar);
1220 void setVideoState(final int videoState) {
1221 mVideoState = videoState;
1222 for (CallbackRecord record : mCallbackRecords) {
1223 final RemoteConnection connection = this;
1224 final Callback callback = record.getCallback();
1225 record.getHandler().post(new Runnable() {
1228 callback.onVideoStateChanged(connection, videoState);
1237 void setVideoProvider(final VideoProvider videoProvider) {
1238 mVideoProvider = videoProvider;
1239 for (CallbackRecord record : mCallbackRecords) {
1240 final RemoteConnection connection = this;
1241 final Callback callback = record.getCallback();
1242 record.getHandler().post(new Runnable() {
1245 callback.onVideoProviderChanged(connection, videoProvider);
1252 void setIsVoipAudioMode(final boolean isVoip) {
1253 mIsVoipAudioMode = isVoip;
1254 for (CallbackRecord record : mCallbackRecords) {
1255 final RemoteConnection connection = this;
1256 final Callback callback = record.getCallback();
1257 record.getHandler().post(new Runnable() {
1260 callback.onVoipAudioChanged(connection, isVoip);
1267 void setStatusHints(final StatusHints statusHints) {
1268 mStatusHints = statusHints;
1269 for (CallbackRecord record : mCallbackRecords) {
1270 final RemoteConnection connection = this;
1271 final Callback callback = record.getCallback();
1272 record.getHandler().post(new Runnable() {
1275 callback.onStatusHintsChanged(connection, statusHints);
1282 void setAddress(final Uri address, final int presentation) {
1284 mAddressPresentation = presentation;
1285 for (CallbackRecord record : mCallbackRecords) {
1286 final RemoteConnection connection = this;
1287 final Callback callback = record.getCallback();
1288 record.getHandler().post(new Runnable() {
1291 callback.onAddressChanged(connection, address, presentation);
1298 void setCallerDisplayName(final String callerDisplayName, final int presentation) {
1299 mCallerDisplayName = callerDisplayName;
1300 mCallerDisplayNamePresentation = presentation;
1301 for (CallbackRecord record : mCallbackRecords) {
1302 final RemoteConnection connection = this;
1303 final Callback callback = record.getCallback();
1304 record.getHandler().post(new Runnable() {
1307 callback.onCallerDisplayNameChanged(
1308 connection, callerDisplayName, presentation);
1315 void setConferenceableConnections(final List<RemoteConnection> conferenceableConnections) {
1316 mConferenceableConnections.clear();
1317 mConferenceableConnections.addAll(conferenceableConnections);
1318 for (CallbackRecord record : mCallbackRecords) {
1319 final RemoteConnection connection = this;
1320 final Callback callback = record.getCallback();
1321 record.getHandler().post(new Runnable() {
1324 callback.onConferenceableConnectionsChanged(
1325 connection, mUnmodifiableconferenceableConnections);
1332 void setConference(final RemoteConference conference) {
1333 if (mConference != conference) {
1334 mConference = conference;
1335 for (CallbackRecord record : mCallbackRecords) {
1336 final RemoteConnection connection = this;
1337 final Callback callback = record.getCallback();
1338 record.getHandler().post(new Runnable() {
1341 callback.onConferenceChanged(connection, conference);
1349 void putExtras(final Bundle extras) {
1350 if (mExtras == null) {
1351 mExtras = new Bundle();
1353 mExtras.putAll(extras);
1355 notifyExtrasChanged();
1359 void removeExtras(List<String> keys) {
1360 if (mExtras == null || keys == null || keys.isEmpty()) {
1363 for (String key : keys) {
1364 mExtras.remove(key);
1367 notifyExtrasChanged();
1370 private void notifyExtrasChanged() {
1371 for (CallbackRecord record : mCallbackRecords) {
1372 final RemoteConnection connection = this;
1373 final Callback callback = record.getCallback();
1374 record.getHandler().post(new Runnable() {
1377 callback.onExtrasChanged(connection, mExtras);
1384 void onConnectionEvent(final String event, final Bundle extras) {
1385 for (CallbackRecord record : mCallbackRecords) {
1386 final RemoteConnection connection = this;
1387 final Callback callback = record.getCallback();
1388 record.getHandler().post(new Runnable() {
1391 callback.onConnectionEvent(connection, event, extras);
1398 * Create a RemoteConnection represents a failure, and which will be in
1399 * {@link Connection#STATE_DISCONNECTED}. Attempting to use it for anything will almost
1400 * certainly result in bad things happening. Do not do this.
1402 * @return a failed {@link RemoteConnection}
1406 public static RemoteConnection failure(DisconnectCause disconnectCause) {
1407 return new RemoteConnection(disconnectCause);
1410 private static final class CallbackRecord extends Callback {
1411 private final Callback mCallback;
1412 private final Handler mHandler;
1414 public CallbackRecord(Callback callback, Handler handler) {
1415 mCallback = callback;
1419 public Callback getCallback() {
1423 public Handler getHandler() {