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