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