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