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