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