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