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