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