• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.annotation.UnsupportedAppUsage;
20 import android.net.Uri;
21 import android.os.Bundle;
22 import android.os.SystemClock;
23 import android.telecom.ConferenceParticipant;
24 import android.telephony.DisconnectCause;
25 import android.telephony.Rlog;
26 import android.telephony.ServiceState;
27 import android.telephony.emergency.EmergencyNumber;
28 import android.util.Log;
29 
30 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
31 
32 import java.util.ArrayList;
33 import java.util.List;
34 import java.util.Set;
35 import java.util.concurrent.CopyOnWriteArraySet;
36 
37 /**
38  * {@hide}
39  */
40 public abstract class Connection {
41     private static final String TAG = "Connection";
42 
43     public interface PostDialListener {
onPostDialWait()44         void onPostDialWait();
onPostDialChar(char c)45         void onPostDialChar(char c);
46     }
47 
48     /**
49      * Capabilities that will be mapped to telecom connection
50      * capabilities.
51      */
52     public static class Capability {
53 
54         /**
55          * For an IMS video call, indicates that the local side of the call supports downgrading
56          * from a video call to an audio-only call.
57          */
58         public static final int SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL = 0x00000001;
59 
60         /**
61          * For an IMS video call, indicates that the peer supports downgrading to an audio-only
62          * call.
63          */
64         public static final int SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE = 0x00000002;
65 
66         /**
67          * For an IMS call, indicates that the call supports video locally.
68          */
69         public static final int SUPPORTS_VT_LOCAL_BIDIRECTIONAL = 0x00000004;
70 
71         /**
72          * For an IMS call, indicates that the peer supports video.
73          */
74         public static final int SUPPORTS_VT_REMOTE_BIDIRECTIONAL = 0x00000008;
75 
76         /**
77          * Indicates that the connection is an external connection (e.g. an instance of the class
78          * {@link com.android.internal.telephony.imsphone.ImsExternalConnection}.
79          */
80         public static final int IS_EXTERNAL_CONNECTION = 0x00000010;
81 
82         /**
83          * Indicates that this external connection can be pulled from the remote device to the
84          * local device.
85          */
86         public static final int IS_PULLABLE = 0x00000020;
87     }
88 
89     /**
90      * Listener interface for events related to the connection which should be reported to the
91      * {@link android.telecom.Connection}.
92      */
93     public interface Listener {
onVideoStateChanged(int videoState)94         public void onVideoStateChanged(int videoState);
onConnectionCapabilitiesChanged(int capability)95         public void onConnectionCapabilitiesChanged(int capability);
onCallRadioTechChanged(@erviceState.RilRadioTechnology int vrat)96         public void onCallRadioTechChanged(@ServiceState.RilRadioTechnology int vrat);
onVideoProviderChanged( android.telecom.Connection.VideoProvider videoProvider)97         public void onVideoProviderChanged(
98                 android.telecom.Connection.VideoProvider videoProvider);
onAudioQualityChanged(int audioQuality)99         public void onAudioQualityChanged(int audioQuality);
onConferenceParticipantsChanged(List<ConferenceParticipant> participants)100         public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants);
onCallSubstateChanged(int callSubstate)101         public void onCallSubstateChanged(int callSubstate);
onMultipartyStateChanged(boolean isMultiParty)102         public void onMultipartyStateChanged(boolean isMultiParty);
onConferenceMergedFailed()103         public void onConferenceMergedFailed();
onExtrasChanged(Bundle extras)104         public void onExtrasChanged(Bundle extras);
onExitedEcmMode()105         public void onExitedEcmMode();
onCallPullFailed(Connection externalConnection)106         public void onCallPullFailed(Connection externalConnection);
onHandoverToWifiFailed()107         public void onHandoverToWifiFailed();
onConnectionEvent(String event, Bundle extras)108         public void onConnectionEvent(String event, Bundle extras);
onRttModifyRequestReceived()109         public void onRttModifyRequestReceived();
onRttModifyResponseReceived(int status)110         public void onRttModifyResponseReceived(int status);
onDisconnect(int cause)111         public void onDisconnect(int cause);
onRttInitiated()112         public void onRttInitiated();
onRttTerminated()113         public void onRttTerminated();
onOriginalConnectionReplaced(Connection newConnection)114         public void onOriginalConnectionReplaced(Connection newConnection);
onIsNetworkEmergencyCallChanged(boolean isEmergencyCall)115         public void onIsNetworkEmergencyCallChanged(boolean isEmergencyCall);
116     }
117 
118     /**
119      * Base listener implementation.
120      */
121     public abstract static class ListenerBase implements Listener {
122         @Override
onVideoStateChanged(int videoState)123         public void onVideoStateChanged(int videoState) {}
124         @Override
onConnectionCapabilitiesChanged(int capability)125         public void onConnectionCapabilitiesChanged(int capability) {}
126         @Override
onCallRadioTechChanged(@erviceState.RilRadioTechnology int vrat)127         public void onCallRadioTechChanged(@ServiceState.RilRadioTechnology int vrat) {}
128         @Override
onVideoProviderChanged( android.telecom.Connection.VideoProvider videoProvider)129         public void onVideoProviderChanged(
130                 android.telecom.Connection.VideoProvider videoProvider) {}
131         @Override
onAudioQualityChanged(int audioQuality)132         public void onAudioQualityChanged(int audioQuality) {}
133         @Override
onConferenceParticipantsChanged(List<ConferenceParticipant> participants)134         public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants) {}
135         @Override
onCallSubstateChanged(int callSubstate)136         public void onCallSubstateChanged(int callSubstate) {}
137         @Override
onMultipartyStateChanged(boolean isMultiParty)138         public void onMultipartyStateChanged(boolean isMultiParty) {}
139         @Override
onConferenceMergedFailed()140         public void onConferenceMergedFailed() {}
141         @Override
onExtrasChanged(Bundle extras)142         public void onExtrasChanged(Bundle extras) {}
143         @Override
onExitedEcmMode()144         public void onExitedEcmMode() {}
145         @Override
onCallPullFailed(Connection externalConnection)146         public void onCallPullFailed(Connection externalConnection) {}
147         @Override
onHandoverToWifiFailed()148         public void onHandoverToWifiFailed() {}
149         @Override
onConnectionEvent(String event, Bundle extras)150         public void onConnectionEvent(String event, Bundle extras) {}
151         @Override
onRttModifyRequestReceived()152         public void onRttModifyRequestReceived() {}
153         @Override
onRttModifyResponseReceived(int status)154         public void onRttModifyResponseReceived(int status) {}
155         @Override
onDisconnect(int cause)156         public void onDisconnect(int cause) {}
157         @Override
onRttInitiated()158         public void onRttInitiated() {}
159         @Override
onRttTerminated()160         public void onRttTerminated() {}
161         @Override
onOriginalConnectionReplaced(Connection newConnection)162         public void onOriginalConnectionReplaced(Connection newConnection) {}
163         @Override
onIsNetworkEmergencyCallChanged(boolean isEmergencyCall)164         public void onIsNetworkEmergencyCallChanged(boolean isEmergencyCall) {}
165     }
166 
167     public static final int AUDIO_QUALITY_STANDARD = 1;
168     public static final int AUDIO_QUALITY_HIGH_DEFINITION = 2;
169 
170     /**
171      * The telecom internal call ID associated with this connection.  Only to be used for debugging
172      * purposes.
173      */
174     private String mTelecomCallId;
175 
176     //Caller Name Display
177     @UnsupportedAppUsage
178     protected String mCnapName;
179     @UnsupportedAppUsage
180     protected int mCnapNamePresentation  = PhoneConstants.PRESENTATION_ALLOWED;
181     @UnsupportedAppUsage
182     protected String mAddress;     // MAY BE NULL!!!
183     @UnsupportedAppUsage
184     protected String mDialString;          // outgoing calls only
185     @UnsupportedAppUsage
186     protected int mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
187     @UnsupportedAppUsage
188     protected boolean mIsIncoming;
189     /*
190      * These time/timespan values are based on System.currentTimeMillis(),
191      * i.e., "wall clock" time.
192      */
193     protected long mCreateTime;
194     protected long mConnectTime;
195     /*
196      * These time/timespan values are based on SystemClock.elapsedRealTime(),
197      * i.e., time since boot.  They are appropriate for comparison and
198      * calculating deltas.
199      */
200     protected long mConnectTimeReal;
201     @UnsupportedAppUsage
202     protected long mDuration;
203     protected long mHoldingStartTime;  // The time when the Connection last transitioned
204                             // into HOLDING
205     protected Connection mOrigConnection;
206     private List<PostDialListener> mPostDialListeners = new ArrayList<>();
207     public Set<Listener> mListeners = new CopyOnWriteArraySet<>();
208 
209     protected boolean mNumberConverted = false;
210     protected String mConvertedNumber;
211 
212     protected String mPostDialString;      // outgoing calls only
213     protected int mNextPostDialChar;       // index into postDialString
214 
215     protected int mCause = DisconnectCause.NOT_DISCONNECTED;
216     protected PostDialState mPostDialState = PostDialState.NOT_STARTED;
217 
218     @UnsupportedAppUsage
219     private static String LOG_TAG = "Connection";
220 
221     Object mUserData;
222     private int mVideoState;
223     private int mConnectionCapabilities;
224     /**
225      * Determines the call radio technology for current connection.
226      *
227      * This is used to propagate the call radio technology to upper layer.
228      */
229     private @ServiceState.RilRadioTechnology int mCallRadioTech =
230             ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
231     private boolean mAudioModeIsVoip;
232     private int mAudioQuality;
233     private int mCallSubstate;
234     private android.telecom.Connection.VideoProvider mVideoProvider;
235     public Call.State mPreHandoverState = Call.State.IDLE;
236     private Bundle mExtras;
237     private int mPhoneType;
238     private boolean mAnsweringDisconnectsActiveCall;
239     private boolean mAllowAddCallDuringVideoCall;
240 
241     private boolean mIsEmergencyCall;
242 
243     /**
244      * The emergency number information, only valid if {@link #isEmergencyCall} returns
245      * {@code true}.
246      */
247     private EmergencyNumber mEmergencyNumberInfo;
248 
249     /**
250      * Whether the call is from emergency dialer, only valid if {@link #isEmergencyCall} returns
251      * {@code true}.
252      */
253     private boolean mHasKnownUserIntentEmergency;
254 
255     /**
256      * When {@code true}, the network has indicated that this is an emergency call.
257      */
258     private boolean mIsNetworkIdentifiedEmergencyCall;
259 
260     /**
261      * Used to indicate that this originated from pulling a {@link android.telecom.Connection} with
262      * {@link android.telecom.Connection#PROPERTY_IS_EXTERNAL_CALL}.
263      */
264     private boolean mIsPulledCall = false;
265 
266     /**
267      * Where {@link #mIsPulledCall} is {@code true}, contains the dialog Id of the external call
268      * which is being pulled (e.g.
269      * {@link com.android.internal.telephony.imsphone.ImsExternalConnection#getCallId()}).
270      */
271     private int mPulledDialogId;
272 
273     @UnsupportedAppUsage
Connection(int phoneType)274     protected Connection(int phoneType) {
275         mPhoneType = phoneType;
276     }
277 
278     /* Instance Methods */
279 
280     /**
281      * @return The telecom internal call ID associated with this connection.  Only to be used for
282      * debugging purposes.
283      */
getTelecomCallId()284     public String getTelecomCallId() {
285         return mTelecomCallId;
286     }
287 
288     /**
289      * Sets the telecom call ID associated with this connection.
290      *
291      * @param telecomCallId The telecom call ID.
292      */
setTelecomCallId(String telecomCallId)293     public void setTelecomCallId(String telecomCallId) {
294         mTelecomCallId = telecomCallId;
295     }
296 
297     /**
298      * Gets address (e.g. phone number) associated with connection.
299      * TODO: distinguish reasons for unavailability
300      *
301      * @return address or null if unavailable
302      */
303 
304     @UnsupportedAppUsage
getAddress()305     public String getAddress() {
306         return mAddress;
307     }
308 
309     /**
310      * Gets CNAP name associated with connection.
311      * @return cnap name or null if unavailable
312      */
getCnapName()313     public String getCnapName() {
314         return mCnapName;
315     }
316 
317     /**
318      * Get original dial string.
319      * @return original dial string or null if unavailable
320      */
getOrigDialString()321     public String getOrigDialString(){
322         return null;
323     }
324 
325     /**
326      * Gets CNAP presentation associated with connection.
327      * @return cnap name or null if unavailable
328      */
329 
getCnapNamePresentation()330     public int getCnapNamePresentation() {
331        return mCnapNamePresentation;
332     }
333 
334     /**
335      * @return Call that owns this Connection, or null if none
336      */
337     @UnsupportedAppUsage
getCall()338     public abstract Call getCall();
339 
340     /**
341      * Connection create time in currentTimeMillis() format
342      * Basically, set when object is created.
343      * Effectively, when an incoming call starts ringing or an
344      * outgoing call starts dialing
345      */
346     @UnsupportedAppUsage
getCreateTime()347     public long getCreateTime() {
348         return mCreateTime;
349     }
350 
351     /**
352      * Connection connect time in currentTimeMillis() format.
353      * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition.
354      * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition.
355      * Returns 0 before then.
356      */
357     @UnsupportedAppUsage
getConnectTime()358     public long getConnectTime() {
359         return mConnectTime;
360     }
361 
362     /**
363      * Sets the Connection connect time in currentTimeMillis() format.
364      *
365      * @param connectTime the new connect time.
366      */
setConnectTime(long connectTime)367     public void setConnectTime(long connectTime) {
368         mConnectTime = connectTime;
369     }
370 
371     /**
372      * Sets the Connection connect time in {@link SystemClock#elapsedRealtime()} format.
373      *
374      * @param connectTimeReal the new connect time.
375      */
setConnectTimeReal(long connectTimeReal)376     public void setConnectTimeReal(long connectTimeReal) {
377         mConnectTimeReal = connectTimeReal;
378     }
379 
380     /**
381      * Connection connect time in elapsedRealtime() format.
382      * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition.
383      * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition.
384      * Returns 0 before then.
385      */
getConnectTimeReal()386     public long getConnectTimeReal() {
387         return mConnectTimeReal;
388     }
389 
390     /**
391      * Disconnect time in currentTimeMillis() format.
392      * The time when this Connection makes a transition into ENDED or FAIL.
393      * Returns 0 before then.
394      */
395     @UnsupportedAppUsage
getDisconnectTime()396     public abstract long getDisconnectTime();
397 
398     /**
399      * Returns the number of milliseconds the call has been connected,
400      * or 0 if the call has never connected.
401      * If the call is still connected, then returns the elapsed
402      * time since connect.
403      */
404     @UnsupportedAppUsage
getDurationMillis()405     public long getDurationMillis() {
406         if (mConnectTimeReal == 0) {
407             return 0;
408         } else if (mDuration == 0) {
409             return SystemClock.elapsedRealtime() - mConnectTimeReal;
410         } else {
411             return mDuration;
412         }
413     }
414 
415     /**
416      * The time when this Connection last transitioned into HOLDING
417      * in elapsedRealtime() format.
418      * Returns 0, if it has never made a transition into HOLDING.
419      */
getHoldingStartTime()420     public long getHoldingStartTime() {
421         return mHoldingStartTime;
422     }
423 
424     /**
425      * If this connection is HOLDING, return the number of milliseconds
426      * that it has been on hold for (approximately).
427      * If this connection is in any other state, return 0.
428      */
429 
getHoldDurationMillis()430     public abstract long getHoldDurationMillis();
431 
432     /**
433      * Returns call disconnect cause. Values are defined in
434      * {@link android.telephony.DisconnectCause}. If the call is not yet
435      * disconnected, NOT_DISCONNECTED is returned.
436      */
437     @UnsupportedAppUsage
getDisconnectCause()438     public int getDisconnectCause() {
439         return mCause;
440     }
441 
442     /**
443      * Returns a string disconnect cause which is from vendor.
444      * Vendors may use this string to explain the underline causes of failed calls.
445      * There is no guarantee that it is non-null nor it'll have meaningful stable values.
446      * Only use it when getDisconnectCause() returns a value that is not specific enough, like
447      * ERROR_UNSPECIFIED.
448      */
getVendorDisconnectCause()449     public abstract String getVendorDisconnectCause();
450 
451     /**
452      * Returns true of this connection originated elsewhere
453      * ("MT" or mobile terminated; another party called this terminal)
454      * or false if this call originated here (MO or mobile originated).
455      */
456     @UnsupportedAppUsage
isIncoming()457     public boolean isIncoming() {
458         return mIsIncoming;
459     }
460 
461     /**
462      * Sets whether this call is an incoming call or not.
463      * @param isIncoming {@code true} if the call is an incoming call, {@code false} if it is an
464      *                               outgoing call.
465      */
setIsIncoming(boolean isIncoming)466     public void setIsIncoming(boolean isIncoming) {
467         mIsIncoming = isIncoming;
468     }
469 
470     /**
471      * Checks if the connection is for an emergency call.
472      *
473      * @return {@code true} if the call is an emergency call
474      *         or {@code false} otherwise.
475      */
isEmergencyCall()476     public boolean isEmergencyCall() {
477         return mIsEmergencyCall;
478     }
479 
480     /**
481      * Get the emergency number info. The value is valid only if {@link #isEmergencyCall()}
482      * returns {@code true}.
483      *
484      * @return the emergency number info
485      */
getEmergencyNumberInfo()486     public EmergencyNumber getEmergencyNumberInfo() {
487         return mEmergencyNumberInfo;
488     }
489 
490     /**
491      * Checks if we have known the user's intent for the call is emergency.
492      *
493      * This is only used to specify when the dialed number is ambiguous, identified as both
494      * emergency number and any other non-emergency number; e.g. in some situation, 611 could
495      * be both an emergency number in a country and a non-emergency number of a carrier's
496      * customer service hotline.
497      *
498      * @return whether the call is from emergency dialer
499      */
hasKnownUserIntentEmergency()500     public boolean hasKnownUserIntentEmergency() {
501         return mHasKnownUserIntentEmergency;
502     }
503 
504     /**
505      * Set the emergency number information if it is an emergency call.
506      *
507      * @hide
508      */
setEmergencyCallInfo(CallTracker ct)509     public void setEmergencyCallInfo(CallTracker ct) {
510         if (ct != null) {
511             Phone phone = ct.getPhone();
512             if (phone != null) {
513                 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
514                 if (tracker != null) {
515                     EmergencyNumber num = tracker.getEmergencyNumber(mAddress);
516                     if (num != null) {
517                         mIsEmergencyCall = true;
518                         mEmergencyNumberInfo = num;
519                     } else {
520                         Rlog.e(TAG, "setEmergencyCallInfo: emergency number is null");
521                     }
522                 } else {
523                     Rlog.e(TAG, "setEmergencyCallInfo: emergency number tracker is null");
524                 }
525             } else {
526                 Rlog.e(TAG, "setEmergencyCallInfo: phone is null");
527             }
528         } else {
529             Rlog.e(TAG, "setEmergencyCallInfo: call tracker is null");
530         }
531     }
532 
533     /**
534      * Set if we have known the user's intent for the call is emergency.
535      *
536      * This is only used to specify when the dialed number is ambiguous, identified as both
537      * emergency number and any other non-emergency number; e.g. in some situation, 611 could
538      * be both an emergency number in a country and a non-emergency number of a carrier's
539      * customer service hotline.
540      *
541      * @hide
542      */
setHasKnownUserIntentEmergency(boolean hasKnownUserIntentEmergency)543     public void setHasKnownUserIntentEmergency(boolean hasKnownUserIntentEmergency) {
544         mHasKnownUserIntentEmergency = hasKnownUserIntentEmergency;
545     }
546 
547     /**
548      * If this Connection is connected, then it is associated with
549      * a Call.
550      *
551      * Returns getCall().getState() or Call.State.IDLE if not
552      * connected
553      */
554     @UnsupportedAppUsage
getState()555     public Call.State getState() {
556         Call c;
557 
558         c = getCall();
559 
560         if (c == null) {
561             return Call.State.IDLE;
562         } else {
563             return c.getState();
564         }
565     }
566 
567     /**
568      * If this connection went through handover return the state of the
569      * call that contained this connection before handover.
570      */
getStateBeforeHandover()571     public Call.State getStateBeforeHandover() {
572         return mPreHandoverState;
573    }
574 
575     /**
576      * Get the details of conference participants. Expected to be
577      * overwritten by the Connection subclasses.
578      */
getConferenceParticipants()579     public List<ConferenceParticipant> getConferenceParticipants() {
580         Call c;
581 
582         c = getCall();
583 
584         if (c == null) {
585             return null;
586         } else {
587             return c.getConferenceParticipants();
588         }
589     }
590 
591     /**
592      * isAlive()
593      *
594      * @return true if the connection isn't disconnected
595      * (could be active, holding, ringing, dialing, etc)
596      */
597     @UnsupportedAppUsage
598     public boolean
isAlive()599     isAlive() {
600         return getState().isAlive();
601     }
602 
603     /**
604      * Returns true if Connection is connected and is INCOMING or WAITING
605      */
606     public boolean
isRinging()607     isRinging() {
608         return getState().isRinging();
609     }
610 
611     /**
612      *
613      * @return the userdata set in setUserData()
614      */
615     @UnsupportedAppUsage
getUserData()616     public Object getUserData() {
617         return mUserData;
618     }
619 
620     /**
621      *
622      * @param userdata user can store an any userdata in the Connection object.
623      */
setUserData(Object userdata)624     public void setUserData(Object userdata) {
625         mUserData = userdata;
626     }
627 
628     /**
629      * Deflect individual Connection
630      */
deflect(String number)631     public abstract void deflect(String number) throws CallStateException;
632 
633     /**
634      * Hangup individual Connection
635      */
636     @UnsupportedAppUsage
hangup()637     public abstract void hangup() throws CallStateException;
638 
639     /**
640      * Separate this call from its owner Call and assigns it to a new Call
641      * (eg if it is currently part of a Conference call
642      * TODO: Throw exception? Does GSM require error display on failure here?
643      */
separate()644     public abstract void separate() throws CallStateException;
645 
646     public enum PostDialState {
647         @UnsupportedAppUsage
648         NOT_STARTED,    /* The post dial string playback hasn't
649                            been started, or this call is not yet
650                            connected, or this is an incoming call */
651         @UnsupportedAppUsage
652         STARTED,        /* The post dial string playback has begun */
653         @UnsupportedAppUsage
654         WAIT,           /* The post dial string playback is waiting for a
655                            call to proceedAfterWaitChar() */
656         @UnsupportedAppUsage
657         WILD,           /* The post dial string playback is waiting for a
658                            call to proceedAfterWildChar() */
659         @UnsupportedAppUsage
660         COMPLETE,       /* The post dial string playback is complete */
661         @UnsupportedAppUsage
662         CANCELLED,       /* The post dial string playback was cancelled
663                            with cancelPostDial() */
664         PAUSE           /* The post dial string playback is pausing for a
665                            call to processNextPostDialChar*/
666     }
667 
clearUserData()668     public void clearUserData(){
669         mUserData = null;
670     }
671 
addPostDialListener(PostDialListener listener)672     public void addPostDialListener(PostDialListener listener) {
673         if (!mPostDialListeners.contains(listener)) {
674             mPostDialListeners.add(listener);
675         }
676     }
677 
removePostDialListener(PostDialListener listener)678     public final void removePostDialListener(PostDialListener listener) {
679         mPostDialListeners.remove(listener);
680     }
681 
clearPostDialListeners()682     protected final void clearPostDialListeners() {
683         if (mPostDialListeners != null) {
684             mPostDialListeners.clear();
685         }
686     }
687 
notifyPostDialListeners()688     protected final void notifyPostDialListeners() {
689         if (getPostDialState() == PostDialState.WAIT) {
690             for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) {
691                 listener.onPostDialWait();
692             }
693         }
694     }
695 
notifyPostDialListenersNextChar(char c)696     protected final void notifyPostDialListenersNextChar(char c) {
697         for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) {
698             listener.onPostDialChar(c);
699         }
700     }
701 
getPostDialState()702     public PostDialState getPostDialState() {
703         return mPostDialState;
704     }
705 
706     /**
707      * Returns the portion of the post dial string that has not
708      * yet been dialed, or "" if none
709      */
getRemainingPostDialString()710     public String getRemainingPostDialString() {
711         if (mPostDialState == PostDialState.CANCELLED
712                 || mPostDialState == PostDialState.COMPLETE
713                 || mPostDialString == null
714                 || mPostDialString.length() <= mNextPostDialChar) {
715             return "";
716         }
717 
718         return mPostDialString.substring(mNextPostDialChar);
719     }
720 
721     /**
722      * See Phone.setOnPostDialWaitCharacter()
723      */
724 
proceedAfterWaitChar()725     public abstract void proceedAfterWaitChar();
726 
727     /**
728      * See Phone.setOnPostDialWildCharacter()
729      */
proceedAfterWildChar(String str)730     public abstract void proceedAfterWildChar(String str);
731     /**
732      * Cancel any post
733      */
cancelPostDial()734     public abstract void cancelPostDial();
735 
736     /** Called when the connection has been disconnected */
onDisconnect(int cause)737     public boolean onDisconnect(int cause) {
738         return false;
739     }
740 
741     /**
742      * Returns the caller id presentation type for incoming and waiting calls
743      * @return one of PRESENTATION_*
744      */
getNumberPresentation()745     public abstract int getNumberPresentation();
746 
747     /**
748      * Returns the User to User Signaling (UUS) information associated with
749      * incoming and waiting calls
750      * @return UUSInfo containing the UUS userdata.
751      */
getUUSInfo()752     public abstract UUSInfo getUUSInfo();
753 
754     /**
755      * Returns the CallFail reason provided by the RIL with the result of
756      * RIL_REQUEST_LAST_CALL_FAIL_CAUSE
757      */
getPreciseDisconnectCause()758     public abstract int getPreciseDisconnectCause();
759 
760     /**
761      * Returns the original Connection instance associated with
762      * this Connection
763      */
getOrigConnection()764     public Connection getOrigConnection() {
765         return mOrigConnection;
766     }
767 
768     /**
769      * Returns whether the original ImsPhoneConnection was a member
770      * of a conference call
771      * @return valid only when getOrigConnection() is not null
772      */
isMultiparty()773     public abstract boolean isMultiparty();
774 
775     /**
776      * Applicable only for IMS Call. Determines if this call is the origin of the conference call
777      * (i.e. {@code #isConferenceHost()} is {@code true}), or if it is a member of a conference
778      * hosted on another device.
779      *
780      * @return {@code true} if this call is the origin of the conference call it is a member of,
781      *      {@code false} otherwise.
782      */
isConferenceHost()783     public boolean isConferenceHost() {
784         return false;
785     }
786 
787     /**
788      * Applicable only for IMS Call. Determines if a connection is a member of a conference hosted
789      * on another device.
790      *
791      * @return {@code true} if the connection is a member of a conference hosted on another device.
792      */
isMemberOfPeerConference()793     public boolean isMemberOfPeerConference() {
794         return false;
795     }
796 
migrateFrom(Connection c)797     public void migrateFrom(Connection c) {
798         if (c == null) return;
799         mListeners = c.mListeners;
800         mDialString = c.getOrigDialString();
801         mCreateTime = c.getCreateTime();
802         mConnectTime = c.getConnectTime();
803         mConnectTimeReal = c.getConnectTimeReal();
804         mHoldingStartTime = c.getHoldingStartTime();
805         mOrigConnection = c.getOrigConnection();
806         mPostDialString = c.mPostDialString;
807         mNextPostDialChar = c.mNextPostDialChar;
808         mPostDialState = c.mPostDialState;
809 
810         // Migrate Emergency call parameters
811         mIsEmergencyCall = c.isEmergencyCall();
812         mEmergencyNumberInfo = c.getEmergencyNumberInfo();
813         mHasKnownUserIntentEmergency = c.hasKnownUserIntentEmergency();
814     }
815 
816     /**
817      * Assign a listener to be notified of state changes.
818      *
819      * @param listener A listener.
820      */
addListener(Listener listener)821     public void addListener(Listener listener) {
822         mListeners.add(listener);
823     }
824 
825     /**
826      * Removes a listener.
827      *
828      * @param listener A listener.
829      */
removeListener(Listener listener)830     public final void removeListener(Listener listener) {
831         mListeners.remove(listener);
832     }
833 
834     /**
835      * Returns the current video state of the connection.
836      *
837      * @return The video state of the connection.
838      */
getVideoState()839     public int getVideoState() {
840         return mVideoState;
841     }
842 
843     /**
844      * Called to get Connection capabilities.Returns Capabilities bitmask.
845      * @See Connection.Capability.
846      */
getConnectionCapabilities()847     public int getConnectionCapabilities() {
848         return mConnectionCapabilities;
849     }
850 
851     /**
852      * @return {@code} true if the connection has the specified capabilities.
853      */
hasCapabilities(int connectionCapabilities)854     public boolean hasCapabilities(int connectionCapabilities) {
855         return (mConnectionCapabilities & connectionCapabilities) == connectionCapabilities;
856     }
857 
858     /**
859      * Applies a capability to a capabilities bit-mask.
860      *
861      * @param capabilities The capabilities bit-mask.
862      * @param capability The capability to apply.
863      * @return The capabilities bit-mask with the capability applied.
864      */
addCapability(int capabilities, int capability)865     public static int addCapability(int capabilities, int capability) {
866         return capabilities | capability;
867     }
868 
869     /**
870      * Removes a capability to a capabilities bit-mask.
871      *
872      * @param capabilities The capabilities bit-mask.
873      * @param capability The capability to remove.
874      * @return The capabilities bit-mask with the capability removed.
875      */
removeCapability(int capabilities, int capability)876     public static int removeCapability(int capabilities, int capability) {
877         return capabilities & ~capability;
878     }
879 
880     /**
881      * Returns whether the connection is using a wifi network.
882      *
883      * @return {@code True} if the connection is using a wifi network.
884      */
isWifi()885     public boolean isWifi() {
886         return getCallRadioTech() == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
887     }
888 
889     /**
890      * Returns radio technology is used for the connection.
891      *
892      * @return the RIL Voice Radio Technology used for current connection,
893      *         see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
894      */
getCallRadioTech()895     public @ServiceState.RilRadioTechnology int getCallRadioTech() {
896         return mCallRadioTech;
897     }
898 
899     /**
900      * Returns whether the connection uses voip audio mode
901      *
902      * @return {@code True} if the connection uses voip audio mode
903      */
getAudioModeIsVoip()904     public boolean getAudioModeIsVoip() {
905         return mAudioModeIsVoip;
906     }
907 
908     /**
909      * Returns the {@link android.telecom.Connection.VideoProvider} for the connection.
910      *
911      * @return The {@link android.telecom.Connection.VideoProvider}.
912      */
getVideoProvider()913     public android.telecom.Connection.VideoProvider getVideoProvider() {
914         return mVideoProvider;
915     }
916 
917     /**
918      * Returns the audio-quality for the connection.
919      *
920      * @return The audio quality for the connection.
921      */
getAudioQuality()922     public int getAudioQuality() {
923         return mAudioQuality;
924     }
925 
926 
927     /**
928      * Returns the current call substate of the connection.
929      *
930      * @return The call substate of the connection.
931      */
getCallSubstate()932     public int getCallSubstate() {
933         return mCallSubstate;
934     }
935 
936 
937     /**
938      * Sets the videoState for the current connection and reports the changes to all listeners.
939      * Valid video states are defined in {@link android.telecom.VideoProfile}.
940      *
941      * @return The video state.
942      */
943     @UnsupportedAppUsage
setVideoState(int videoState)944     public void setVideoState(int videoState) {
945         mVideoState = videoState;
946         for (Listener l : mListeners) {
947             l.onVideoStateChanged(mVideoState);
948         }
949     }
950 
951     /**
952      * Called to set Connection capabilities.  This will take Capabilities bitmask as input which is
953      * converted from Capabilities constants.
954      *
955      * @See Connection.Capability.
956      * @param capabilities The Capabilities bitmask.
957      */
setConnectionCapabilities(int capabilities)958     public void setConnectionCapabilities(int capabilities) {
959         if (mConnectionCapabilities != capabilities) {
960             mConnectionCapabilities = capabilities;
961             for (Listener l : mListeners) {
962                 l.onConnectionCapabilitiesChanged(mConnectionCapabilities);
963             }
964         }
965     }
966 
967     /**
968      * Sets RIL voice radio technology used for current connection.
969      *
970      * @param vrat the RIL voice radio technology for current connection,
971      *             see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
972      */
setCallRadioTech(@erviceState.RilRadioTechnology int vrat)973     public void setCallRadioTech(@ServiceState.RilRadioTechnology int vrat) {
974         if (mCallRadioTech == vrat) {
975             return;
976         }
977         mCallRadioTech = vrat;
978         for (Listener l : mListeners) {
979             l.onCallRadioTechChanged(vrat);
980         }
981     }
982 
983     /**
984      * Set the voip audio mode for the connection
985      *
986      * @param isVoip {@code True} if voip audio mode is being used.
987      */
setAudioModeIsVoip(boolean isVoip)988     public void setAudioModeIsVoip(boolean isVoip) {
989         mAudioModeIsVoip = isVoip;
990     }
991 
992     /**
993      * Set the audio quality for the connection.
994      *
995      * @param audioQuality The audio quality.
996      */
setAudioQuality(int audioQuality)997     public void setAudioQuality(int audioQuality) {
998         mAudioQuality = audioQuality;
999         for (Listener l : mListeners) {
1000             l.onAudioQualityChanged(mAudioQuality);
1001         }
1002     }
1003 
1004     /**
1005      * Notifies listeners that connection extras has changed.
1006      * @param extras New connection extras. This Bundle will be cloned to ensure that any concurrent
1007      * modifications to the extras Bundle do not affect Bundle operations in the onExtrasChanged
1008      * listeners.
1009      */
setConnectionExtras(Bundle extras)1010     public void setConnectionExtras(Bundle extras) {
1011         if (extras != null) {
1012             mExtras = new Bundle(extras);
1013 
1014             int previousCount = mExtras.size();
1015             // Prevent vendors from passing in extras other than primitive types and android API
1016             // parcelables.
1017             mExtras = mExtras.filterValues();
1018             int filteredCount = mExtras.size();
1019             if (filteredCount != previousCount) {
1020                 Rlog.i(TAG, "setConnectionExtras: filtering " + (previousCount - filteredCount)
1021                         + " invalid extras.");
1022             }
1023         } else {
1024             mExtras = null;
1025         }
1026 
1027         for (Listener l : mListeners) {
1028             l.onExtrasChanged(mExtras);
1029         }
1030     }
1031 
1032     /**
1033      * Retrieves the current connection extras.
1034      * @return the connection extras.
1035      */
getConnectionExtras()1036     public Bundle getConnectionExtras() {
1037         return mExtras == null ? null : new Bundle(mExtras);
1038     }
1039 
1040     /**
1041      * @return {@code true} if answering the call will cause the current active call to be
1042      *      disconnected, {@code false} otherwise.
1043      */
isActiveCallDisconnectedOnAnswer()1044     public boolean isActiveCallDisconnectedOnAnswer() {
1045         return mAnsweringDisconnectsActiveCall;
1046     }
1047 
1048     /**
1049      * Sets whether answering this call will cause the active call to be disconnected.
1050      * <p>
1051      * Should only be set {@code true} if there is an active call and this call is ringing.
1052      *
1053      * @param answeringDisconnectsActiveCall {@code true} if answering the call will call the active
1054      *      call to be disconnected.
1055      */
setActiveCallDisconnectedOnAnswer(boolean answeringDisconnectsActiveCall)1056     public void setActiveCallDisconnectedOnAnswer(boolean answeringDisconnectsActiveCall) {
1057         mAnsweringDisconnectsActiveCall = answeringDisconnectsActiveCall;
1058     }
1059 
shouldAllowAddCallDuringVideoCall()1060     public boolean shouldAllowAddCallDuringVideoCall() {
1061         return mAllowAddCallDuringVideoCall;
1062     }
1063 
setAllowAddCallDuringVideoCall(boolean allowAddCallDuringVideoCall)1064     public void setAllowAddCallDuringVideoCall(boolean allowAddCallDuringVideoCall) {
1065         mAllowAddCallDuringVideoCall = allowAddCallDuringVideoCall;
1066     }
1067 
1068     /**
1069      * Sets whether the connection is the result of an external call which was pulled to the local
1070      * device.
1071      *
1072      * @param isPulledCall {@code true} if this connection is the result of pulling an external call
1073      *      to the local device.
1074      */
setIsPulledCall(boolean isPulledCall)1075     public void setIsPulledCall(boolean isPulledCall) {
1076         mIsPulledCall = isPulledCall;
1077     }
1078 
isPulledCall()1079     public boolean isPulledCall() {
1080         return mIsPulledCall;
1081     }
1082 
1083     /**
1084      * For an external call which is being pulled (e.g. {@link #isPulledCall()} is {@code true}),
1085      * sets the dialog Id for the external call.  Used to handle failures to pull a call so that the
1086      * pulled call can be reconciled with its original external connection.
1087      *
1088      * @param pulledDialogId The dialog id associated with a pulled call.
1089      */
setPulledDialogId(int pulledDialogId)1090     public void setPulledDialogId(int pulledDialogId) {
1091         mPulledDialogId = pulledDialogId;
1092     }
1093 
getPulledDialogId()1094     public int getPulledDialogId() {
1095         return mPulledDialogId;
1096     }
1097 
1098     /**
1099      * Sets the call substate for the current connection and reports the changes to all listeners.
1100      * Valid call substates are defined in {@link android.telecom.Connection}.
1101      *
1102      * @return The call substate.
1103      */
setCallSubstate(int callSubstate)1104     public void setCallSubstate(int callSubstate) {
1105         mCallSubstate = callSubstate;
1106         for (Listener l : mListeners) {
1107             l.onCallSubstateChanged(mCallSubstate);
1108         }
1109     }
1110 
1111     /**
1112      * Sets the {@link android.telecom.Connection.VideoProvider} for the connection.
1113      *
1114      * @param videoProvider The video call provider.
1115      */
setVideoProvider(android.telecom.Connection.VideoProvider videoProvider)1116     public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) {
1117         mVideoProvider = videoProvider;
1118         for (Listener l : mListeners) {
1119             l.onVideoProviderChanged(mVideoProvider);
1120         }
1121     }
1122 
setConverted(String oriNumber)1123     public void setConverted(String oriNumber) {
1124         mNumberConverted = true;
1125         mConvertedNumber = mAddress;
1126         mAddress = oriNumber;
1127         mDialString = oriNumber;
1128     }
1129 
1130     /**
1131      * Changes the address and presentation for this call.
1132      * @param newAddress The new address.
1133      * @param numberPresentation The number presentation for the address.
1134      */
setAddress(String newAddress, int numberPresentation)1135     public void setAddress(String newAddress, int numberPresentation) {
1136         Rlog.i(TAG, "setAddress = " + newAddress);
1137         mAddress = newAddress;
1138         mNumberPresentation = numberPresentation;
1139     }
1140 
setDialString(String newDialString)1141     public void setDialString(String newDialString) {
1142         mDialString = newDialString;
1143     }
1144 
1145     /**
1146      * Notifies listeners of a change to conference participant(s).
1147      *
1148      * @param conferenceParticipants The participant(s).
1149      */
updateConferenceParticipants(List<ConferenceParticipant> conferenceParticipants)1150     public void updateConferenceParticipants(List<ConferenceParticipant> conferenceParticipants) {
1151         for (Listener l : mListeners) {
1152             l.onConferenceParticipantsChanged(conferenceParticipants);
1153         }
1154     }
1155 
1156     /**
1157      * Notifies listeners of a change to the multiparty state of the connection.
1158      *
1159      * @param isMultiparty The participant(s).
1160      */
updateMultipartyState(boolean isMultiparty)1161     public void updateMultipartyState(boolean isMultiparty) {
1162         for (Listener l : mListeners) {
1163             l.onMultipartyStateChanged(isMultiparty);
1164         }
1165     }
1166 
1167     /**
1168      * Notifies listeners of a failure in merging this connection with the background connection.
1169      */
onConferenceMergeFailed()1170     public void onConferenceMergeFailed() {
1171         for (Listener l : mListeners) {
1172             l.onConferenceMergedFailed();
1173         }
1174     }
1175 
1176     /**
1177      * Notifies that the underlying phone has exited ECM mode.
1178      */
onExitedEcmMode()1179     public void onExitedEcmMode() {
1180         for (Listener l : mListeners) {
1181             l.onExitedEcmMode();
1182         }
1183     }
1184 
1185     /**
1186      * Notifies the connection that a call to {@link #pullExternalCall()} has failed to pull the
1187      * call to the local device.
1188      *
1189      * @param externalConnection The original
1190      *      {@link com.android.internal.telephony.imsphone.ImsExternalConnection} from which the
1191      *      pull was initiated.
1192      */
onCallPullFailed(Connection externalConnection)1193     public void onCallPullFailed(Connection externalConnection) {
1194         for (Listener l : mListeners) {
1195             l.onCallPullFailed(externalConnection);
1196         }
1197     }
1198 
onOriginalConnectionReplaced(Connection newConnection)1199     public void onOriginalConnectionReplaced(Connection newConnection) {
1200         for (Listener l : mListeners) {
1201             l.onOriginalConnectionReplaced(newConnection);
1202         }
1203     }
1204     /**
1205      * Notifies the connection that there was a failure while handing over to WIFI.
1206      */
onHandoverToWifiFailed()1207     public void onHandoverToWifiFailed() {
1208         for (Listener l : mListeners) {
1209             l.onHandoverToWifiFailed();
1210         }
1211     }
1212 
1213     /**
1214      * Notifies the connection of a connection event.
1215      */
onConnectionEvent(String event, Bundle extras)1216     public void onConnectionEvent(String event, Bundle extras) {
1217         for (Listener l : mListeners) {
1218             l.onConnectionEvent(event, extras);
1219         }
1220     }
1221 
1222     /**
1223      * Notifies this Connection of a request to disconnect a participant of the conference managed
1224      * by the connection.
1225      *
1226      * @param endpoint the {@link Uri} of the participant to disconnect.
1227      */
onDisconnectConferenceParticipant(Uri endpoint)1228     public void onDisconnectConferenceParticipant(Uri endpoint) {
1229     }
1230 
1231     /**
1232      * Called by a {@link android.telecom.Connection} to indicate that this call should be pulled
1233      * to the local device.
1234      */
pullExternalCall()1235     public void pullExternalCall() {
1236     }
1237 
onRttModifyRequestReceived()1238     public void onRttModifyRequestReceived() {
1239         for (Listener l : mListeners) {
1240             l.onRttModifyRequestReceived();
1241         }
1242     }
1243 
onRttModifyResponseReceived(int status)1244     public void onRttModifyResponseReceived(int status) {
1245         for (Listener l : mListeners) {
1246             l.onRttModifyResponseReceived(status);
1247         }
1248     }
1249 
onRttInitiated()1250     public void onRttInitiated() {
1251         for (Listener l : mListeners) {
1252             l.onRttInitiated();
1253         }
1254     }
1255 
onRttTerminated()1256     public void onRttTerminated() {
1257         for (Listener l : mListeners) {
1258             l.onRttTerminated();
1259         }
1260     }
1261     /**
1262      * Notify interested parties that this connection disconnected.
1263      * {@code TelephonyConnection}, for example, uses this.
1264      * @param reason the disconnect code, per {@link DisconnectCause}.
1265      */
notifyDisconnect(int reason)1266     protected void notifyDisconnect(int reason) {
1267         Rlog.i(TAG, "notifyDisconnect: callId=" + getTelecomCallId() + ", reason=" + reason);
1268         for (Listener l : mListeners) {
1269             l.onDisconnect(reason);
1270         }
1271     }
1272 
1273     /**
1274      *
1275      */
getPhoneType()1276     public int getPhoneType() {
1277         return mPhoneType;
1278     }
1279 
1280     /**
1281      * Reset the Connection time and Duration
1282      */
resetConnectionTime()1283     public void resetConnectionTime() {
1284         if (mPhoneType == PhoneConstants.PHONE_TYPE_CDMA_LTE ||
1285                 mPhoneType == PhoneConstants.PHONE_TYPE_CDMA) {
1286             mConnectTime = System.currentTimeMillis();
1287             mConnectTimeReal = SystemClock.elapsedRealtime();
1288             mDuration = 0;
1289         }
1290     }
1291 
1292     /**
1293      * Sets whether this {@link Connection} has been identified by the network as an emergency call.
1294      * @param isNetworkIdentifiedEmergencyCall {@code true} if ecall, {@code false} otherwise.
1295      */
setIsNetworkIdentifiedEmergencyCall(boolean isNetworkIdentifiedEmergencyCall)1296     public void setIsNetworkIdentifiedEmergencyCall(boolean isNetworkIdentifiedEmergencyCall) {
1297         mIsNetworkIdentifiedEmergencyCall = isNetworkIdentifiedEmergencyCall;
1298         for (Listener l : mListeners) {
1299             l.onIsNetworkEmergencyCallChanged(isNetworkIdentifiedEmergencyCall);
1300         }
1301     }
1302 
1303     /**
1304      * @return Whether this {@link Connection} has been identified by the network as an emergency
1305      * call.
1306      */
isNetworkIdentifiedEmergencyCall()1307     public boolean isNetworkIdentifiedEmergencyCall() {
1308         return mIsNetworkIdentifiedEmergencyCall;
1309     }
1310 
1311     /**
1312      * Build a human representation of a connection instance, suitable for debugging.
1313      * Don't log personal stuff unless in debug mode.
1314      * @return a string representing the internal state of this connection.
1315      */
toString()1316     public String toString() {
1317         StringBuilder str = new StringBuilder(128);
1318 
1319         str.append(" callId: " + getTelecomCallId());
1320         str.append(" isExternal: " + (((mConnectionCapabilities & Capability.IS_EXTERNAL_CONNECTION)
1321                 == Capability.IS_EXTERNAL_CONNECTION) ? "Y" : "N"));
1322         if (Rlog.isLoggable(LOG_TAG, Log.DEBUG)) {
1323             str.append("addr: " + getAddress())
1324                     .append(" pres.: " + getNumberPresentation())
1325                     .append(" dial: " + getOrigDialString())
1326                     .append(" postdial: " + getRemainingPostDialString())
1327                     .append(" cnap name: " + getCnapName())
1328                     .append("(" + getCnapNamePresentation() + ")");
1329         }
1330         str.append(" incoming: " + isIncoming())
1331                 .append(" state: " + getState())
1332                 .append(" post dial state: " + getPostDialState());
1333         return str.toString();
1334     }
1335 }
1336