1/*
2 * Copyright (C) 2006 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 com.android.internal.telephony;
18
19import android.net.Uri;
20import android.os.Bundle;
21import android.os.SystemClock;
22import android.telecom.ConferenceParticipant;
23import android.telephony.DisconnectCause;
24import android.telephony.Rlog;
25import android.util.Log;
26
27import java.lang.Override;
28import java.util.ArrayList;
29import java.util.List;
30import java.util.Set;
31import java.util.concurrent.CopyOnWriteArraySet;
32
33/**
34 * {@hide}
35 */
36public abstract class Connection {
37
38    public interface PostDialListener {
39        void onPostDialWait();
40        void onPostDialChar(char c);
41    }
42
43    /**
44     * Capabilities that will be mapped to telecom connection
45     * capabilities.
46     */
47    public static class Capability {
48
49        /**
50         * For an IMS video call, indicates that the local side of the call supports downgrading
51         * from a video call to an audio-only call.
52         */
53        public static final int SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL = 0x00000001;
54
55        /**
56         * For an IMS video call, indicates that the peer supports downgrading to an audio-only
57         * call.
58         */
59        public static final int SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE = 0x00000002;
60
61        /**
62         * For an IMS call, indicates that the call supports video locally.
63         */
64        public static final int SUPPORTS_VT_LOCAL_BIDIRECTIONAL = 0x00000004;
65
66        /**
67         * For an IMS call, indicates that the peer supports video.
68         */
69        public static final int SUPPORTS_VT_REMOTE_BIDIRECTIONAL = 0x00000008;
70
71        /**
72         * Indicates that the connection is an external connection (e.g. an instance of the class
73         * {@link com.android.internal.telephony.imsphone.ImsExternalConnection}.
74         */
75        public static final int IS_EXTERNAL_CONNECTION = 0x00000010;
76
77        /**
78         * Indicates that this external connection can be pulled from the remote device to the
79         * local device.
80         */
81        public static final int IS_PULLABLE = 0x00000020;
82    }
83
84    /**
85     * Listener interface for events related to the connection which should be reported to the
86     * {@link android.telecom.Connection}.
87     */
88    public interface Listener {
89        public void onVideoStateChanged(int videoState);
90        public void onConnectionCapabilitiesChanged(int capability);
91        public void onWifiChanged(boolean isWifi);
92        public void onVideoProviderChanged(
93                android.telecom.Connection.VideoProvider videoProvider);
94        public void onAudioQualityChanged(int audioQuality);
95        public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants);
96        public void onCallSubstateChanged(int callSubstate);
97        public void onMultipartyStateChanged(boolean isMultiParty);
98        public void onConferenceMergedFailed();
99        public void onExtrasChanged(Bundle extras);
100        public void onExitedEcmMode();
101        public void onCallPullFailed(Connection externalConnection);
102        public void onHandoverToWifiFailed();
103        public void onConnectionEvent(String event, Bundle extras);
104    }
105
106    /**
107     * Base listener implementation.
108     */
109    public abstract static class ListenerBase implements Listener {
110        @Override
111        public void onVideoStateChanged(int videoState) {}
112        @Override
113        public void onConnectionCapabilitiesChanged(int capability) {}
114        @Override
115        public void onWifiChanged(boolean isWifi) {}
116        @Override
117        public void onVideoProviderChanged(
118                android.telecom.Connection.VideoProvider videoProvider) {}
119        @Override
120        public void onAudioQualityChanged(int audioQuality) {}
121        @Override
122        public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants) {}
123        @Override
124        public void onCallSubstateChanged(int callSubstate) {}
125        @Override
126        public void onMultipartyStateChanged(boolean isMultiParty) {}
127        @Override
128        public void onConferenceMergedFailed() {}
129        @Override
130        public void onExtrasChanged(Bundle extras) {}
131        @Override
132        public void onExitedEcmMode() {}
133        @Override
134        public void onCallPullFailed(Connection externalConnection) {}
135        @Override
136        public void onHandoverToWifiFailed() {}
137        @Override
138        public void onConnectionEvent(String event, Bundle extras) {}
139    }
140
141    public static final int AUDIO_QUALITY_STANDARD = 1;
142    public static final int AUDIO_QUALITY_HIGH_DEFINITION = 2;
143
144    /**
145     * The telecom internal call ID associated with this connection.  Only to be used for debugging
146     * purposes.
147     */
148    private String mTelecomCallId;
149
150    //Caller Name Display
151    protected String mCnapName;
152    protected int mCnapNamePresentation  = PhoneConstants.PRESENTATION_ALLOWED;
153    protected String mAddress;     // MAY BE NULL!!!
154    protected String mDialString;          // outgoing calls only
155    protected int mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
156    protected boolean mIsIncoming;
157    /*
158     * These time/timespan values are based on System.currentTimeMillis(),
159     * i.e., "wall clock" time.
160     */
161    protected long mCreateTime;
162    protected long mConnectTime;
163    /*
164     * These time/timespan values are based on SystemClock.elapsedRealTime(),
165     * i.e., time since boot.  They are appropriate for comparison and
166     * calculating deltas.
167     */
168    protected long mConnectTimeReal;
169    protected long mDuration;
170    protected long mHoldingStartTime;  // The time when the Connection last transitioned
171                            // into HOLDING
172    protected Connection mOrigConnection;
173    private List<PostDialListener> mPostDialListeners = new ArrayList<>();
174    public Set<Listener> mListeners = new CopyOnWriteArraySet<>();
175
176    protected boolean mNumberConverted = false;
177    protected String mConvertedNumber;
178
179    protected String mPostDialString;      // outgoing calls only
180    protected int mNextPostDialChar;       // index into postDialString
181
182    protected int mCause = DisconnectCause.NOT_DISCONNECTED;
183    protected PostDialState mPostDialState = PostDialState.NOT_STARTED;
184
185    private static String LOG_TAG = "Connection";
186
187    Object mUserData;
188    private int mVideoState;
189    private int mConnectionCapabilities;
190    private boolean mIsWifi;
191    private boolean mAudioModeIsVoip;
192    private int mAudioQuality;
193    private int mCallSubstate;
194    private android.telecom.Connection.VideoProvider mVideoProvider;
195    public Call.State mPreHandoverState = Call.State.IDLE;
196    private Bundle mExtras;
197    private int mPhoneType;
198    private boolean mAnsweringDisconnectsActiveCall;
199    private boolean mAllowAddCallDuringVideoCall;
200
201    /**
202     * Used to indicate that this originated from pulling a {@link android.telecom.Connection} with
203     * {@link android.telecom.Connection#PROPERTY_IS_EXTERNAL_CALL}.
204     */
205    private boolean mIsPulledCall = false;
206
207    /**
208     * Where {@link #mIsPulledCall} is {@code true}, contains the dialog Id of the external call
209     * which is being pulled (e.g.
210     * {@link com.android.internal.telephony.imsphone.ImsExternalConnection#getCallId()}).
211     */
212    private int mPulledDialogId;
213
214    protected Connection(int phoneType) {
215        mPhoneType = phoneType;
216    }
217
218    /* Instance Methods */
219
220    /**
221     * @return The telecom internal call ID associated with this connection.  Only to be used for
222     * debugging purposes.
223     */
224    public String getTelecomCallId() {
225        return mTelecomCallId;
226    }
227
228    /**
229     * Sets the telecom call ID associated with this connection.
230     *
231     * @param telecomCallId The telecom call ID.
232     */
233    public void setTelecomCallId(String telecomCallId) {
234        mTelecomCallId = telecomCallId;
235    }
236
237    /**
238     * Gets address (e.g. phone number) associated with connection.
239     * TODO: distinguish reasons for unavailability
240     *
241     * @return address or null if unavailable
242     */
243
244    public String getAddress() {
245        return mAddress;
246    }
247
248    /**
249     * Gets CNAP name associated with connection.
250     * @return cnap name or null if unavailable
251     */
252    public String getCnapName() {
253        return mCnapName;
254    }
255
256    /**
257     * Get original dial string.
258     * @return original dial string or null if unavailable
259     */
260    public String getOrigDialString(){
261        return null;
262    }
263
264    /**
265     * Gets CNAP presentation associated with connection.
266     * @return cnap name or null if unavailable
267     */
268
269    public int getCnapNamePresentation() {
270       return mCnapNamePresentation;
271    }
272
273    /**
274     * @return Call that owns this Connection, or null if none
275     */
276    public abstract Call getCall();
277
278    /**
279     * Connection create time in currentTimeMillis() format
280     * Basically, set when object is created.
281     * Effectively, when an incoming call starts ringing or an
282     * outgoing call starts dialing
283     */
284    public long getCreateTime() {
285        return mCreateTime;
286    }
287
288    /**
289     * Connection connect time in currentTimeMillis() format.
290     * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition.
291     * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition.
292     * Returns 0 before then.
293     */
294    public long getConnectTime() {
295        return mConnectTime;
296    }
297
298    /**
299     * Sets the Connection connect time in currentTimeMillis() format.
300     *
301     * @param connectTime the new connect time.
302     */
303    public void setConnectTime(long connectTime) {
304        mConnectTime = connectTime;
305    }
306
307    /**
308     * Connection connect time in elapsedRealtime() format.
309     * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition.
310     * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition.
311     * Returns 0 before then.
312     */
313    public long getConnectTimeReal() {
314        return mConnectTimeReal;
315    }
316
317    /**
318     * Disconnect time in currentTimeMillis() format.
319     * The time when this Connection makes a transition into ENDED or FAIL.
320     * Returns 0 before then.
321     */
322    public abstract long getDisconnectTime();
323
324    /**
325     * Returns the number of milliseconds the call has been connected,
326     * or 0 if the call has never connected.
327     * If the call is still connected, then returns the elapsed
328     * time since connect.
329     */
330    public long getDurationMillis() {
331        if (mConnectTimeReal == 0) {
332            return 0;
333        } else if (mDuration == 0) {
334            return SystemClock.elapsedRealtime() - mConnectTimeReal;
335        } else {
336            return mDuration;
337        }
338    }
339
340    /**
341     * The time when this Connection last transitioned into HOLDING
342     * in elapsedRealtime() format.
343     * Returns 0, if it has never made a transition into HOLDING.
344     */
345    public long getHoldingStartTime() {
346        return mHoldingStartTime;
347    }
348
349    /**
350     * If this connection is HOLDING, return the number of milliseconds
351     * that it has been on hold for (approximately).
352     * If this connection is in any other state, return 0.
353     */
354
355    public abstract long getHoldDurationMillis();
356
357    /**
358     * Returns call disconnect cause. Values are defined in
359     * {@link android.telephony.DisconnectCause}. If the call is not yet
360     * disconnected, NOT_DISCONNECTED is returned.
361     */
362    public int getDisconnectCause() {
363        return mCause;
364    }
365
366    /**
367     * Returns a string disconnect cause which is from vendor.
368     * Vendors may use this string to explain the underline causes of failed calls.
369     * There is no guarantee that it is non-null nor it'll have meaningful stable values.
370     * Only use it when getDisconnectCause() returns a value that is not specific enough, like
371     * ERROR_UNSPECIFIED.
372     */
373    public abstract String getVendorDisconnectCause();
374
375    /**
376     * Returns true of this connection originated elsewhere
377     * ("MT" or mobile terminated; another party called this terminal)
378     * or false if this call originated here (MO or mobile originated).
379     */
380    public boolean isIncoming() {
381        return mIsIncoming;
382    }
383
384    /**
385     * If this Connection is connected, then it is associated with
386     * a Call.
387     *
388     * Returns getCall().getState() or Call.State.IDLE if not
389     * connected
390     */
391    public Call.State getState() {
392        Call c;
393
394        c = getCall();
395
396        if (c == null) {
397            return Call.State.IDLE;
398        } else {
399            return c.getState();
400        }
401    }
402
403    /**
404     * If this connection went through handover return the state of the
405     * call that contained this connection before handover.
406     */
407    public Call.State getStateBeforeHandover() {
408        return mPreHandoverState;
409   }
410
411    /**
412     * Get the details of conference participants. Expected to be
413     * overwritten by the Connection subclasses.
414     */
415    public List<ConferenceParticipant> getConferenceParticipants() {
416        Call c;
417
418        c = getCall();
419
420        if (c == null) {
421            return null;
422        } else {
423            return c.getConferenceParticipants();
424        }
425    }
426
427    /**
428     * isAlive()
429     *
430     * @return true if the connection isn't disconnected
431     * (could be active, holding, ringing, dialing, etc)
432     */
433    public boolean
434    isAlive() {
435        return getState().isAlive();
436    }
437
438    /**
439     * Returns true if Connection is connected and is INCOMING or WAITING
440     */
441    public boolean
442    isRinging() {
443        return getState().isRinging();
444    }
445
446    /**
447     *
448     * @return the userdata set in setUserData()
449     */
450    public Object getUserData() {
451        return mUserData;
452    }
453
454    /**
455     *
456     * @param userdata user can store an any userdata in the Connection object.
457     */
458    public void setUserData(Object userdata) {
459        mUserData = userdata;
460    }
461
462    /**
463     * Hangup individual Connection
464     */
465    public abstract void hangup() throws CallStateException;
466
467    /**
468     * Separate this call from its owner Call and assigns it to a new Call
469     * (eg if it is currently part of a Conference call
470     * TODO: Throw exception? Does GSM require error display on failure here?
471     */
472    public abstract void separate() throws CallStateException;
473
474    public enum PostDialState {
475        NOT_STARTED,    /* The post dial string playback hasn't
476                           been started, or this call is not yet
477                           connected, or this is an incoming call */
478        STARTED,        /* The post dial string playback has begun */
479        WAIT,           /* The post dial string playback is waiting for a
480                           call to proceedAfterWaitChar() */
481        WILD,           /* The post dial string playback is waiting for a
482                           call to proceedAfterWildChar() */
483        COMPLETE,       /* The post dial string playback is complete */
484        CANCELLED,       /* The post dial string playback was cancelled
485                           with cancelPostDial() */
486        PAUSE           /* The post dial string playback is pausing for a
487                           call to processNextPostDialChar*/
488    }
489
490    public void clearUserData(){
491        mUserData = null;
492    }
493
494    public final void addPostDialListener(PostDialListener listener) {
495        if (!mPostDialListeners.contains(listener)) {
496            mPostDialListeners.add(listener);
497        }
498    }
499
500    public final void removePostDialListener(PostDialListener listener) {
501        mPostDialListeners.remove(listener);
502    }
503
504    protected final void clearPostDialListeners() {
505        if (mPostDialListeners != null) {
506            mPostDialListeners.clear();
507        }
508    }
509
510    protected final void notifyPostDialListeners() {
511        if (getPostDialState() == PostDialState.WAIT) {
512            for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) {
513                listener.onPostDialWait();
514            }
515        }
516    }
517
518    protected final void notifyPostDialListenersNextChar(char c) {
519        for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) {
520            listener.onPostDialChar(c);
521        }
522    }
523
524    public PostDialState getPostDialState() {
525        return mPostDialState;
526    }
527
528    /**
529     * Returns the portion of the post dial string that has not
530     * yet been dialed, or "" if none
531     */
532    public String getRemainingPostDialString() {
533        if (mPostDialState == PostDialState.CANCELLED
534                || mPostDialState == PostDialState.COMPLETE
535                || mPostDialString == null
536                || mPostDialString.length() <= mNextPostDialChar) {
537            return "";
538        }
539
540        return mPostDialString.substring(mNextPostDialChar);
541    }
542
543    /**
544     * See Phone.setOnPostDialWaitCharacter()
545     */
546
547    public abstract void proceedAfterWaitChar();
548
549    /**
550     * See Phone.setOnPostDialWildCharacter()
551     */
552    public abstract void proceedAfterWildChar(String str);
553    /**
554     * Cancel any post
555     */
556    public abstract void cancelPostDial();
557
558    /** Called when the connection has been disconnected */
559    public boolean onDisconnect(int cause) {
560        return false;
561    }
562
563    /**
564     * Returns the caller id presentation type for incoming and waiting calls
565     * @return one of PRESENTATION_*
566     */
567    public abstract int getNumberPresentation();
568
569    /**
570     * Returns the User to User Signaling (UUS) information associated with
571     * incoming and waiting calls
572     * @return UUSInfo containing the UUS userdata.
573     */
574    public abstract UUSInfo getUUSInfo();
575
576    /**
577     * Returns the CallFail reason provided by the RIL with the result of
578     * RIL_REQUEST_LAST_CALL_FAIL_CAUSE
579     */
580    public abstract int getPreciseDisconnectCause();
581
582    /**
583     * Returns the original Connection instance associated with
584     * this Connection
585     */
586    public Connection getOrigConnection() {
587        return mOrigConnection;
588    }
589
590    /**
591     * Returns whether the original ImsPhoneConnection was a member
592     * of a conference call
593     * @return valid only when getOrigConnection() is not null
594     */
595    public abstract boolean isMultiparty();
596
597    /**
598     * Applicable only for IMS Call. Determines if this call is the origin of the conference call
599     * (i.e. {@code #isConferenceHost()} is {@code true}), or if it is a member of a conference
600     * hosted on another device.
601     *
602     * @return {@code true} if this call is the origin of the conference call it is a member of,
603     *      {@code false} otherwise.
604     */
605    public boolean isConferenceHost() {
606        return false;
607    }
608
609    /**
610     * Applicable only for IMS Call. Determines if a connection is a member of a conference hosted
611     * on another device.
612     *
613     * @return {@code true} if the connection is a member of a conference hosted on another device.
614     */
615    public boolean isMemberOfPeerConference() {
616        return false;
617    }
618
619    public void migrateFrom(Connection c) {
620        if (c == null) return;
621        mListeners = c.mListeners;
622        mDialString = c.getOrigDialString();
623        mCreateTime = c.getCreateTime();
624        mConnectTime = c.getConnectTime();
625        mConnectTimeReal = c.getConnectTimeReal();
626        mHoldingStartTime = c.getHoldingStartTime();
627        mOrigConnection = c.getOrigConnection();
628        mPostDialString = c.mPostDialString;
629        mNextPostDialChar = c.mNextPostDialChar;
630    }
631
632    /**
633     * Assign a listener to be notified of state changes.
634     *
635     * @param listener A listener.
636     */
637    public final void addListener(Listener listener) {
638        mListeners.add(listener);
639    }
640
641    /**
642     * Removes a listener.
643     *
644     * @param listener A listener.
645     */
646    public final void removeListener(Listener listener) {
647        mListeners.remove(listener);
648    }
649
650    /**
651     * Returns the current video state of the connection.
652     *
653     * @return The video state of the connection.
654     */
655    public int getVideoState() {
656        return mVideoState;
657    }
658
659    /**
660     * Called to get Connection capabilities.Returns Capabilities bitmask.
661     * @See Connection.Capability.
662     */
663    public int getConnectionCapabilities() {
664        return mConnectionCapabilities;
665    }
666
667    /**
668     * @return {@code} true if the connection has the specified capabilities.
669     */
670    public boolean hasCapabilities(int connectionCapabilities) {
671        return (mConnectionCapabilities & connectionCapabilities) == connectionCapabilities;
672    }
673
674    /**
675     * Applies a capability to a capabilities bit-mask.
676     *
677     * @param capabilities The capabilities bit-mask.
678     * @param capability The capability to apply.
679     * @return The capabilities bit-mask with the capability applied.
680     */
681    public static int addCapability(int capabilities, int capability) {
682        return capabilities | capability;
683    }
684
685    /**
686     * Removes a capability to a capabilities bit-mask.
687     *
688     * @param capabilities The capabilities bit-mask.
689     * @param capability The capability to remove.
690     * @return The capabilities bit-mask with the capability removed.
691     */
692    public static int removeCapability(int capabilities, int capability) {
693        return capabilities & ~capability;
694    }
695
696    /**
697     * Returns whether the connection is using a wifi network.
698     *
699     * @return {@code True} if the connection is using a wifi network.
700     */
701    public boolean isWifi() {
702        return mIsWifi;
703    }
704
705    /**
706     * Returns whether the connection uses voip audio mode
707     *
708     * @return {@code True} if the connection uses voip audio mode
709     */
710    public boolean getAudioModeIsVoip() {
711        return mAudioModeIsVoip;
712    }
713
714    /**
715     * Returns the {@link android.telecom.Connection.VideoProvider} for the connection.
716     *
717     * @return The {@link android.telecom.Connection.VideoProvider}.
718     */
719    public android.telecom.Connection.VideoProvider getVideoProvider() {
720        return mVideoProvider;
721    }
722
723    /**
724     * Returns the audio-quality for the connection.
725     *
726     * @return The audio quality for the connection.
727     */
728    public int getAudioQuality() {
729        return mAudioQuality;
730    }
731
732
733    /**
734     * Returns the current call substate of the connection.
735     *
736     * @return The call substate of the connection.
737     */
738    public int getCallSubstate() {
739        return mCallSubstate;
740    }
741
742
743    /**
744     * Sets the videoState for the current connection and reports the changes to all listeners.
745     * Valid video states are defined in {@link android.telecom.VideoProfile}.
746     *
747     * @return The video state.
748     */
749    public void setVideoState(int videoState) {
750        mVideoState = videoState;
751        for (Listener l : mListeners) {
752            l.onVideoStateChanged(mVideoState);
753        }
754    }
755
756    /**
757     * Called to set Connection capabilities.  This will take Capabilities bitmask as input which is
758     * converted from Capabilities constants.
759     *
760     * @See Connection.Capability.
761     * @param capabilities The Capabilities bitmask.
762     */
763    public void setConnectionCapabilities(int capabilities) {
764        if (mConnectionCapabilities != capabilities) {
765            mConnectionCapabilities = capabilities;
766            for (Listener l : mListeners) {
767                l.onConnectionCapabilitiesChanged(mConnectionCapabilities);
768            }
769        }
770    }
771
772    /**
773     * Sets whether a wifi network is used for the connection.
774     *
775     * @param isWifi {@code True} if wifi is being used.
776     */
777    public void setWifi(boolean isWifi) {
778        mIsWifi = isWifi;
779        for (Listener l : mListeners) {
780            l.onWifiChanged(mIsWifi);
781        }
782    }
783
784    /**
785     * Set the voip audio mode for the connection
786     *
787     * @param isVoip {@code True} if voip audio mode is being used.
788     */
789    public void setAudioModeIsVoip(boolean isVoip) {
790        mAudioModeIsVoip = isVoip;
791    }
792
793    /**
794     * Set the audio quality for the connection.
795     *
796     * @param audioQuality The audio quality.
797     */
798    public void setAudioQuality(int audioQuality) {
799        mAudioQuality = audioQuality;
800        for (Listener l : mListeners) {
801            l.onAudioQualityChanged(mAudioQuality);
802        }
803    }
804
805    /**
806     * Notifies listeners that connection extras has changed.
807     * @param extras New connection extras. This Bundle will be cloned to ensure that any concurrent
808     * modifications to the extras Bundle do not affect Bundle operations in the onExtrasChanged
809     * listeners.
810     */
811    public void setConnectionExtras(Bundle extras) {
812        if (extras != null) {
813            mExtras = new Bundle(extras);
814        } else {
815            mExtras = null;
816        }
817
818        for (Listener l : mListeners) {
819            l.onExtrasChanged(mExtras);
820        }
821    }
822
823    /**
824     * Retrieves the current connection extras.
825     * @return the connection extras.
826     */
827    public Bundle getConnectionExtras() {
828        return mExtras == null ? null : new Bundle(mExtras);
829    }
830
831    /**
832     * @return {@code true} if answering the call will cause the current active call to be
833     *      disconnected, {@code false} otherwise.
834     */
835    public boolean isActiveCallDisconnectedOnAnswer() {
836        return mAnsweringDisconnectsActiveCall;
837    }
838
839    /**
840     * Sets whether answering this call will cause the active call to be disconnected.
841     * <p>
842     * Should only be set {@code true} if there is an active call and this call is ringing.
843     *
844     * @param answeringDisconnectsActiveCall {@code true} if answering the call will call the active
845     *      call to be disconnected.
846     */
847    public void setActiveCallDisconnectedOnAnswer(boolean answeringDisconnectsActiveCall) {
848        mAnsweringDisconnectsActiveCall = answeringDisconnectsActiveCall;
849    }
850
851    public boolean shouldAllowAddCallDuringVideoCall() {
852        return mAllowAddCallDuringVideoCall;
853    }
854
855    public void setAllowAddCallDuringVideoCall(boolean allowAddCallDuringVideoCall) {
856        mAllowAddCallDuringVideoCall = allowAddCallDuringVideoCall;
857    }
858
859    /**
860     * Sets whether the connection is the result of an external call which was pulled to the local
861     * device.
862     *
863     * @param isPulledCall {@code true} if this connection is the result of pulling an external call
864     *      to the local device.
865     */
866    public void setIsPulledCall(boolean isPulledCall) {
867        mIsPulledCall = isPulledCall;
868    }
869
870    public boolean isPulledCall() {
871        return mIsPulledCall;
872    }
873
874    /**
875     * For an external call which is being pulled (e.g. {@link #isPulledCall()} is {@code true}),
876     * sets the dialog Id for the external call.  Used to handle failures to pull a call so that the
877     * pulled call can be reconciled with its original external connection.
878     *
879     * @param pulledDialogId The dialog id associated with a pulled call.
880     */
881    public void setPulledDialogId(int pulledDialogId) {
882        mPulledDialogId = pulledDialogId;
883    }
884
885    public int getPulledDialogId() {
886        return mPulledDialogId;
887    }
888
889    /**
890     * Sets the call substate for the current connection and reports the changes to all listeners.
891     * Valid call substates are defined in {@link android.telecom.Connection}.
892     *
893     * @return The call substate.
894     */
895    public void setCallSubstate(int callSubstate) {
896        mCallSubstate = callSubstate;
897        for (Listener l : mListeners) {
898            l.onCallSubstateChanged(mCallSubstate);
899        }
900    }
901
902    /**
903     * Sets the {@link android.telecom.Connection.VideoProvider} for the connection.
904     *
905     * @param videoProvider The video call provider.
906     */
907    public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) {
908        mVideoProvider = videoProvider;
909        for (Listener l : mListeners) {
910            l.onVideoProviderChanged(mVideoProvider);
911        }
912    }
913
914    public void setConverted(String oriNumber) {
915        mNumberConverted = true;
916        mConvertedNumber = mAddress;
917        mAddress = oriNumber;
918        mDialString = oriNumber;
919    }
920
921    /**
922     * Notifies listeners of a change to conference participant(s).
923     *
924     * @param conferenceParticipants The participant(s).
925     */
926    public void updateConferenceParticipants(List<ConferenceParticipant> conferenceParticipants) {
927        for (Listener l : mListeners) {
928            l.onConferenceParticipantsChanged(conferenceParticipants);
929        }
930    }
931
932    /**
933     * Notifies listeners of a change to the multiparty state of the connection.
934     *
935     * @param isMultiparty The participant(s).
936     */
937    public void updateMultipartyState(boolean isMultiparty) {
938        for (Listener l : mListeners) {
939            l.onMultipartyStateChanged(isMultiparty);
940        }
941    }
942
943    /**
944     * Notifies listeners of a failure in merging this connection with the background connection.
945     */
946    public void onConferenceMergeFailed() {
947        for (Listener l : mListeners) {
948            l.onConferenceMergedFailed();
949        }
950    }
951
952    /**
953     * Notifies that the underlying phone has exited ECM mode.
954     */
955    public void onExitedEcmMode() {
956        for (Listener l : mListeners) {
957            l.onExitedEcmMode();
958        }
959    }
960
961    /**
962     * Notifies the connection that a call to {@link #pullExternalCall()} has failed to pull the
963     * call to the local device.
964     *
965     * @param externalConnection The original
966     *      {@link com.android.internal.telephony.imsphone.ImsExternalConnection} from which the
967     *      pull was initiated.
968     */
969    public void onCallPullFailed(Connection externalConnection) {
970        for (Listener l : mListeners) {
971            l.onCallPullFailed(externalConnection);
972        }
973    }
974
975    /**
976     * Notifies the connection that there was a failure while handing over to WIFI.
977     */
978    public void onHandoverToWifiFailed() {
979        for (Listener l : mListeners) {
980            l.onHandoverToWifiFailed();
981        }
982    }
983
984    /**
985     * Notifies the connection of a connection event.
986     */
987    public void onConnectionEvent(String event, Bundle extras) {
988        for (Listener l : mListeners) {
989            l.onConnectionEvent(event, extras);
990        }
991    }
992
993    /**
994     * Notifies this Connection of a request to disconnect a participant of the conference managed
995     * by the connection.
996     *
997     * @param endpoint the {@link Uri} of the participant to disconnect.
998     */
999    public void onDisconnectConferenceParticipant(Uri endpoint) {
1000    }
1001
1002    /**
1003     * Called by a {@link android.telecom.Connection} to indicate that this call should be pulled
1004     * to the local device.
1005     */
1006    public void pullExternalCall() {
1007    }
1008
1009    /**
1010     *
1011     */
1012    public int getPhoneType() {
1013        return mPhoneType;
1014    }
1015
1016    /**
1017     * Build a human representation of a connection instance, suitable for debugging.
1018     * Don't log personal stuff unless in debug mode.
1019     * @return a string representing the internal state of this connection.
1020     */
1021    public String toString() {
1022        StringBuilder str = new StringBuilder(128);
1023
1024        str.append(" callId: " + getTelecomCallId());
1025        str.append(" isExternal: " + (((mConnectionCapabilities & Capability.IS_EXTERNAL_CONNECTION)
1026                == Capability.IS_EXTERNAL_CONNECTION) ? "Y" : "N"));
1027        if (Rlog.isLoggable(LOG_TAG, Log.DEBUG)) {
1028            str.append("addr: " + getAddress())
1029                    .append(" pres.: " + getNumberPresentation())
1030                    .append(" dial: " + getOrigDialString())
1031                    .append(" postdial: " + getRemainingPostDialString())
1032                    .append(" cnap name: " + getCnapName())
1033                    .append("(" + getCnapNamePresentation() + ")");
1034        }
1035        str.append(" incoming: " + isIncoming())
1036                .append(" state: " + getState())
1037                .append(" post dial state: " + getPostDialState());
1038        return str.toString();
1039    }
1040}
1041