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.os.SystemClock;
     20 import android.telephony.Rlog;
     21 import android.util.Log;
     22 
     23 import java.lang.Override;
     24 import java.util.ArrayList;
     25 import java.util.List;
     26 import java.util.Set;
     27 import java.util.concurrent.CopyOnWriteArraySet;
     28 
     29 /**
     30  * {@hide}
     31  */
     32 public abstract class Connection {
     33     public interface PostDialListener {
     34         void onPostDialWait();
     35     }
     36 
     37     /**
     38      * Listener interface for events related to the connection which should be reported to the
     39      * {@link android.telecom.Connection}.
     40      */
     41     public interface Listener {
     42         public void onVideoStateChanged(int videoState);
     43         public void onLocalVideoCapabilityChanged(boolean capable);
     44         public void onRemoteVideoCapabilityChanged(boolean capable);
     45         public void onVideoProviderChanged(
     46                 android.telecom.Connection.VideoProvider videoProvider);
     47         public void onAudioQualityChanged(int audioQuality);
     48     }
     49 
     50     /**
     51      * Base listener implementation.
     52      */
     53     public abstract static class ListenerBase implements Listener {
     54         @Override
     55         public void onVideoStateChanged(int videoState) {}
     56         @Override
     57         public void onLocalVideoCapabilityChanged(boolean capable) {}
     58         @Override
     59         public void onRemoteVideoCapabilityChanged(boolean capable) {}
     60         @Override
     61         public void onVideoProviderChanged(
     62                 android.telecom.Connection.VideoProvider videoProvider) {}
     63         @Override
     64         public void onAudioQualityChanged(int audioQuality) {}
     65     }
     66 
     67     public static final int AUDIO_QUALITY_STANDARD = 1;
     68     public static final int AUDIO_QUALITY_HIGH_DEFINITION = 2;
     69 
     70     //Caller Name Display
     71     protected String mCnapName;
     72     protected int mCnapNamePresentation  = PhoneConstants.PRESENTATION_ALLOWED;
     73     protected String mAddress;     // MAY BE NULL!!!
     74     protected String mDialString;          // outgoing calls only
     75     protected int mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
     76     protected boolean mIsIncoming;
     77     /*
     78      * These time/timespan values are based on System.currentTimeMillis(),
     79      * i.e., "wall clock" time.
     80      */
     81     protected long mCreateTime;
     82     protected long mConnectTime;
     83     /*
     84      * These time/timespan values are based on SystemClock.elapsedRealTime(),
     85      * i.e., time since boot.  They are appropriate for comparison and
     86      * calculating deltas.
     87      */
     88     protected long mConnectTimeReal;
     89     protected long mDuration;
     90     protected long mHoldingStartTime;  // The time when the Connection last transitioned
     91                             // into HOLDING
     92     protected Connection mOrigConnection;
     93     private List<PostDialListener> mPostDialListeners = new ArrayList<>();
     94     public Set<Listener> mListeners = new CopyOnWriteArraySet<>();
     95 
     96     protected boolean mNumberConverted = false;
     97     protected String mConvertedNumber;
     98 
     99     private static String LOG_TAG = "Connection";
    100 
    101     Object mUserData;
    102     private int mVideoState;
    103     private boolean mLocalVideoCapable;
    104     private boolean mRemoteVideoCapable;
    105     private int mAudioQuality;
    106     private android.telecom.Connection.VideoProvider mVideoProvider;
    107 
    108     /* Instance Methods */
    109 
    110     /**
    111      * Gets address (e.g. phone number) associated with connection.
    112      * TODO: distinguish reasons for unavailability
    113      *
    114      * @return address or null if unavailable
    115      */
    116 
    117     public String getAddress() {
    118         return mAddress;
    119     }
    120 
    121     /**
    122      * Gets CNAP name associated with connection.
    123      * @return cnap name or null if unavailable
    124      */
    125     public String getCnapName() {
    126         return mCnapName;
    127     }
    128 
    129     /**
    130      * Get original dial string.
    131      * @return original dial string or null if unavailable
    132      */
    133     public String getOrigDialString(){
    134         return null;
    135     }
    136 
    137     /**
    138      * Gets CNAP presentation associated with connection.
    139      * @return cnap name or null if unavailable
    140      */
    141 
    142     public int getCnapNamePresentation() {
    143        return mCnapNamePresentation;
    144     }
    145 
    146     /**
    147      * @return Call that owns this Connection, or null if none
    148      */
    149     public abstract Call getCall();
    150 
    151     /**
    152      * Connection create time in currentTimeMillis() format
    153      * Basically, set when object is created.
    154      * Effectively, when an incoming call starts ringing or an
    155      * outgoing call starts dialing
    156      */
    157     public long getCreateTime() {
    158         return mCreateTime;
    159     }
    160 
    161     /**
    162      * Connection connect time in currentTimeMillis() format.
    163      * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition.
    164      * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition.
    165      * Returns 0 before then.
    166      */
    167     public long getConnectTime() {
    168         return mConnectTime;
    169     }
    170 
    171     /**
    172      * Connection connect time in elapsedRealtime() format.
    173      * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition.
    174      * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition.
    175      * Returns 0 before then.
    176      */
    177     public long getConnectTimeReal() {
    178         return mConnectTimeReal;
    179     }
    180 
    181     /**
    182      * Disconnect time in currentTimeMillis() format.
    183      * The time when this Connection makes a transition into ENDED or FAIL.
    184      * Returns 0 before then.
    185      */
    186     public abstract long getDisconnectTime();
    187 
    188     /**
    189      * Returns the number of milliseconds the call has been connected,
    190      * or 0 if the call has never connected.
    191      * If the call is still connected, then returns the elapsed
    192      * time since connect.
    193      */
    194     public long getDurationMillis() {
    195         if (mConnectTimeReal == 0) {
    196             return 0;
    197         } else if (mDuration == 0) {
    198             return SystemClock.elapsedRealtime() - mConnectTimeReal;
    199         } else {
    200             return mDuration;
    201         }
    202     }
    203 
    204     /**
    205      * The time when this Connection last transitioned into HOLDING
    206      * in elapsedRealtime() format.
    207      * Returns 0, if it has never made a transition into HOLDING.
    208      */
    209     public long getHoldingStartTime() {
    210         return mHoldingStartTime;
    211     }
    212 
    213     /**
    214      * If this connection is HOLDING, return the number of milliseconds
    215      * that it has been on hold for (approximately).
    216      * If this connection is in any other state, return 0.
    217      */
    218 
    219     public abstract long getHoldDurationMillis();
    220 
    221     /**
    222      * Returns call disconnect cause. Values are defined in
    223      * {@link android.telephony.DisconnectCause}. If the call is not yet
    224      * disconnected, NOT_DISCONNECTED is returned.
    225      */
    226     public abstract int getDisconnectCause();
    227 
    228     /**
    229      * Returns true of this connection originated elsewhere
    230      * ("MT" or mobile terminated; another party called this terminal)
    231      * or false if this call originated here (MO or mobile originated).
    232      */
    233     public boolean isIncoming() {
    234         return mIsIncoming;
    235     }
    236 
    237     /**
    238      * If this Connection is connected, then it is associated with
    239      * a Call.
    240      *
    241      * Returns getCall().getState() or Call.State.IDLE if not
    242      * connected
    243      */
    244     public Call.State getState() {
    245         Call c;
    246 
    247         c = getCall();
    248 
    249         if (c == null) {
    250             return Call.State.IDLE;
    251         } else {
    252             return c.getState();
    253         }
    254     }
    255 
    256     /**
    257      * isAlive()
    258      *
    259      * @return true if the connection isn't disconnected
    260      * (could be active, holding, ringing, dialing, etc)
    261      */
    262     public boolean
    263     isAlive() {
    264         return getState().isAlive();
    265     }
    266 
    267     /**
    268      * Returns true if Connection is connected and is INCOMING or WAITING
    269      */
    270     public boolean
    271     isRinging() {
    272         return getState().isRinging();
    273     }
    274 
    275     /**
    276      *
    277      * @return the userdata set in setUserData()
    278      */
    279     public Object getUserData() {
    280         return mUserData;
    281     }
    282 
    283     /**
    284      *
    285      * @param userdata user can store an any userdata in the Connection object.
    286      */
    287     public void setUserData(Object userdata) {
    288         mUserData = userdata;
    289     }
    290 
    291     /**
    292      * Hangup individual Connection
    293      */
    294     public abstract void hangup() throws CallStateException;
    295 
    296     /**
    297      * Separate this call from its owner Call and assigns it to a new Call
    298      * (eg if it is currently part of a Conference call
    299      * TODO: Throw exception? Does GSM require error display on failure here?
    300      */
    301     public abstract void separate() throws CallStateException;
    302 
    303     public enum PostDialState {
    304         NOT_STARTED,    /* The post dial string playback hasn't
    305                            been started, or this call is not yet
    306                            connected, or this is an incoming call */
    307         STARTED,        /* The post dial string playback has begun */
    308         WAIT,           /* The post dial string playback is waiting for a
    309                            call to proceedAfterWaitChar() */
    310         WILD,           /* The post dial string playback is waiting for a
    311                            call to proceedAfterWildChar() */
    312         COMPLETE,       /* The post dial string playback is complete */
    313         CANCELLED,       /* The post dial string playback was cancelled
    314                            with cancelPostDial() */
    315         PAUSE           /* The post dial string playback is pausing for a
    316                            call to processNextPostDialChar*/
    317     }
    318 
    319     public void clearUserData(){
    320         mUserData = null;
    321     }
    322 
    323     public final void addPostDialListener(PostDialListener listener) {
    324         if (!mPostDialListeners.contains(listener)) {
    325             mPostDialListeners.add(listener);
    326         }
    327     }
    328 
    329     protected final void clearPostDialListeners() {
    330         mPostDialListeners.clear();
    331     }
    332 
    333     protected final void notifyPostDialListeners() {
    334         if (getPostDialState() == PostDialState.WAIT) {
    335             for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) {
    336                 listener.onPostDialWait();
    337             }
    338         }
    339     }
    340 
    341     public abstract PostDialState getPostDialState();
    342 
    343     /**
    344      * Returns the portion of the post dial string that has not
    345      * yet been dialed, or "" if none
    346      */
    347     public abstract String getRemainingPostDialString();
    348 
    349     /**
    350      * See Phone.setOnPostDialWaitCharacter()
    351      */
    352 
    353     public abstract void proceedAfterWaitChar();
    354 
    355     /**
    356      * See Phone.setOnPostDialWildCharacter()
    357      */
    358     public abstract void proceedAfterWildChar(String str);
    359     /**
    360      * Cancel any post
    361      */
    362     public abstract void cancelPostDial();
    363 
    364     /**
    365      * Returns the caller id presentation type for incoming and waiting calls
    366      * @return one of PRESENTATION_*
    367      */
    368     public abstract int getNumberPresentation();
    369 
    370     /**
    371      * Returns the User to User Signaling (UUS) information associated with
    372      * incoming and waiting calls
    373      * @return UUSInfo containing the UUS userdata.
    374      */
    375     public abstract UUSInfo getUUSInfo();
    376 
    377     /**
    378      * Returns the CallFail reason provided by the RIL with the result of
    379      * RIL_REQUEST_LAST_CALL_FAIL_CAUSE
    380      */
    381     public abstract int getPreciseDisconnectCause();
    382 
    383     /**
    384      * Returns the original Connection instance associated with
    385      * this Connection
    386      */
    387     public Connection getOrigConnection() {
    388         return mOrigConnection;
    389     }
    390 
    391     /**
    392      * Returns whether the original ImsPhoneConnection was a member
    393      * of a conference call
    394      * @return valid only when getOrigConnection() is not null
    395      */
    396     public abstract boolean isMultiparty();
    397 
    398     public void migrateFrom(Connection c) {
    399         if (c == null) return;
    400         mListeners = c.mListeners;
    401         mAddress = c.getAddress();
    402         mNumberPresentation = c.getNumberPresentation();
    403         mDialString = c.getOrigDialString();
    404         mCnapName = c.getCnapName();
    405         mCnapNamePresentation = c.getCnapNamePresentation();
    406         mIsIncoming = c.isIncoming();
    407         mCreateTime = c.getCreateTime();
    408         mConnectTime = c.getConnectTime();
    409         mConnectTimeReal = c.getConnectTimeReal();
    410         mHoldingStartTime = c.getHoldingStartTime();
    411         mOrigConnection = c.getOrigConnection();
    412     }
    413 
    414     /**
    415      * Assign a listener to be notified of state changes.
    416      *
    417      * @param listener A listener.
    418      */
    419     public final void addListener(Listener listener) {
    420         mListeners.add(listener);
    421     }
    422 
    423     /**
    424      * Removes a listener.
    425      *
    426      * @param listener A listener.
    427      */
    428     public final void removeListener(Listener listener) {
    429         mListeners.remove(listener);
    430     }
    431 
    432     /**
    433      * Returns the current video state of the connection.
    434      *
    435      * @return The video state of the connection.
    436      */
    437     public int getVideoState() {
    438         return mVideoState;
    439     }
    440 
    441     /**
    442      * Returns the local video capability state for the connection.
    443      *
    444      * @return {@code True} if the connection has local video capabilities.
    445      */
    446     public boolean isLocalVideoCapable() {
    447         return mLocalVideoCapable;
    448     }
    449 
    450     /**
    451      * Returns the remote video capability state for the connection.
    452      *
    453      * @return {@code True} if the connection has remote video capabilities.
    454      */
    455     public boolean isRemoteVideoCapable() {
    456         return mRemoteVideoCapable;
    457     }
    458 
    459     /**
    460      * Returns the {@link android.telecom.Connection.VideoProvider} for the connection.
    461      *
    462      * @return The {@link android.telecom.Connection.VideoProvider}.
    463      */
    464     public android.telecom.Connection.VideoProvider getVideoProvider() {
    465         return mVideoProvider;
    466     }
    467 
    468     /**
    469      * Returns the audio-quality for the connection.
    470      *
    471      * @return The audio quality for the connection.
    472      */
    473     public int getAudioQuality() {
    474         return mAudioQuality;
    475     }
    476 
    477     /**
    478      * Sets the videoState for the current connection and reports the changes to all listeners.
    479      * Valid video states are defined in {@link android.telecom.VideoProfile}.
    480      *
    481      * @return The video state.
    482      */
    483     public void setVideoState(int videoState) {
    484         mVideoState = videoState;
    485         for (Listener l : mListeners) {
    486             l.onVideoStateChanged(mVideoState);
    487         }
    488     }
    489 
    490     /**
    491      * Sets whether video capability is present locally.
    492      *
    493      * @param capable {@code True} if video capable.
    494      */
    495     public void setLocalVideoCapable(boolean capable) {
    496         mLocalVideoCapable = capable;
    497         for (Listener l : mListeners) {
    498             l.onLocalVideoCapabilityChanged(mLocalVideoCapable);
    499         }
    500     }
    501 
    502     /**
    503      * Sets whether video capability is present remotely.
    504      *
    505      * @param capable {@code True} if video capable.
    506      */
    507     public void setRemoteVideoCapable(boolean capable) {
    508         mRemoteVideoCapable = capable;
    509         for (Listener l : mListeners) {
    510             l.onRemoteVideoCapabilityChanged(mRemoteVideoCapable);
    511         }
    512     }
    513 
    514     /**
    515      * Set the audio quality for the connection.
    516      *
    517      * @param audioQuality The audio quality.
    518      */
    519     public void setAudioQuality(int audioQuality) {
    520         mAudioQuality = audioQuality;
    521         for (Listener l : mListeners) {
    522             l.onAudioQualityChanged(mAudioQuality);
    523         }
    524     }
    525 
    526     /**
    527      * Sets the {@link android.telecom.Connection.VideoProvider} for the connection.
    528      *
    529      * @param videoProvider The video call provider.
    530      */
    531     public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) {
    532         mVideoProvider = videoProvider;
    533         for (Listener l : mListeners) {
    534             l.onVideoProviderChanged(mVideoProvider);
    535         }
    536     }
    537 
    538     public void setConverted(String oriNumber) {
    539         mNumberConverted = true;
    540         mConvertedNumber = mAddress;
    541         mAddress = oriNumber;
    542         mDialString = oriNumber;
    543     }
    544 
    545     /**
    546      * Build a human representation of a connection instance, suitable for debugging.
    547      * Don't log personal stuff unless in debug mode.
    548      * @return a string representing the internal state of this connection.
    549      */
    550     public String toString() {
    551         StringBuilder str = new StringBuilder(128);
    552 
    553         if (Rlog.isLoggable(LOG_TAG, Log.DEBUG)) {
    554             str.append("addr: " + getAddress())
    555                     .append(" pres.: " + getNumberPresentation())
    556                     .append(" dial: " + getOrigDialString())
    557                     .append(" postdial: " + getRemainingPostDialString())
    558                     .append(" cnap name: " + getCnapName())
    559                     .append("(" + getCnapNamePresentation() + ")");
    560         }
    561         str.append(" incoming: " + isIncoming())
    562                 .append(" state: " + getState())
    563                 .append(" post dial state: " + getPostDialState());
    564         return str.toString();
    565     }
    566 }
    567