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