• 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.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                 // According to 3gpp 23.167 section 7.1.2, when CS domain is selected,
698                 // emergency routing is performed only if the emergency category is provided.
699                 if (this instanceof GsmCdmaConnection
700                         && dialArgs.intentExtras.getInt(
701                                 PhoneConstants.EXTRA_EMERGENCY_SERVICE_CATEGORY,
702                                 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED)
703                                 == EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED) {
704                     Rlog.d(TAG, "setEmergencyCallInfo: specific eccCategory is required");
705                     return;
706                 }
707                 Rlog.d(TAG, "setEmergencyCallInfo: enforce emergency routing eccCategory="
708                         + eccCategory);
709                 List<String> emergencyUrns = dialArgs.intentExtras.getStringArrayList(
710                         PhoneConstants.EXTRA_EMERGENCY_URNS);
711                 if (emergencyUrns == null || emergencyUrns.isEmpty()) {
712                     emergencyUrns = mEmergencyNumberInfo.getEmergencyUrns();
713                 }
714                 mEmergencyNumberInfo = new EmergencyNumber(mEmergencyNumberInfo.getNumber(),
715                         mEmergencyNumberInfo.getCountryIso(),
716                         mEmergencyNumberInfo.getMnc(),
717                         eccCategory,
718                         emergencyUrns,
719                         getEmergencyNumberSourceForEmergencyRouting(),
720                         EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
721             }
722         }
723     }
724 
725     /**
726      * Get the emergency number source to be used for emergency routing calls.
727      * This is not getting actual source, instead its forcing the source to
728      * EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING.
729      * Even when the source is EMERGENCY_NUMBER_SOURCE_DATABASE,
730      * to allow the category information delivered by the network to be used,
731      * the source is set to EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING.
732      */
getEmergencyNumberSourceForEmergencyRouting()733     private int getEmergencyNumberSourceForEmergencyRouting() {
734         int source = mEmergencyNumberInfo.getEmergencyNumberSourceBitmask();
735         Rlog.d(TAG, "getEmergencyNumberSourceForEmergencyRouting: source=" + source);
736 
737         if (source != EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST) {
738             source = EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING;
739         }
740 
741         return source;
742     }
743 
744     /**
745      * Set the non-detectable emergency number information.
746      */
setNonDetectableEmergencyCallInfo(int eccCategory, @NonNull List<String> emergencyUrns)747     public void setNonDetectableEmergencyCallInfo(int eccCategory,
748             @NonNull List<String> emergencyUrns) {
749         Rlog.d(TAG, "setNonDetectableEmergencyCallInfo: eccCategory=" + eccCategory
750                 + ", emergencyUrns=" + emergencyUrns);
751         mIsEmergencyCall = true;
752         mEmergencyNumberInfo = new EmergencyNumber(mAddress, ""/*countryIso*/, ""/*mnc*/,
753                                 eccCategory, emergencyUrns,
754                                 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
755                                 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN);
756     }
757 
758     /**
759      * Set if we have known the user's intent for the call is emergency.
760      *
761      * This is only used to specify when the dialed number is ambiguous, identified as both
762      * emergency number and any other non-emergency number; e.g. in some situation, 611 could
763      * be both an emergency number in a country and a non-emergency number of a carrier's
764      * customer service hotline.
765      *
766      * @hide
767      */
setHasKnownUserIntentEmergency(boolean hasKnownUserIntentEmergency)768     public void setHasKnownUserIntentEmergency(boolean hasKnownUserIntentEmergency) {
769         mHasKnownUserIntentEmergency = hasKnownUserIntentEmergency;
770     }
771 
772     /**
773      * If this Connection is connected, then it is associated with
774      * a Call.
775      *
776      * Returns getCall().getState() or Call.State.IDLE if not
777      * connected
778      */
779     @UnsupportedAppUsage
getState()780     public Call.State getState() {
781         Call c;
782 
783         c = getCall();
784 
785         if (c == null) {
786             return Call.State.IDLE;
787         } else {
788             return c.getState();
789         }
790     }
791 
792     /**
793      * If this connection went through handover return the state of the
794      * call that contained this connection before handover.
795      */
getStateBeforeHandover()796     public Call.State getStateBeforeHandover() {
797         return mPreHandoverState;
798    }
799 
800     /**
801      * Get the details of conference participants. Expected to be
802      * overwritten by the Connection subclasses.
803      */
getConferenceParticipants()804     public List<ConferenceParticipant> getConferenceParticipants() {
805         Call c;
806 
807         c = getCall();
808 
809         if (c == null) {
810             return null;
811         } else {
812             return c.getConferenceParticipants();
813         }
814     }
815 
816     /**
817      * isAlive()
818      *
819      * @return true if the connection isn't disconnected
820      * (could be active, holding, ringing, dialing, etc)
821      */
822     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
823     public boolean
isAlive()824     isAlive() {
825         return getState().isAlive();
826     }
827 
828     /**
829      * Returns true if Connection is connected and is INCOMING or WAITING
830      */
831     public boolean
isRinging()832     isRinging() {
833         return getState().isRinging();
834     }
835 
836     /**
837      *
838      * @return the userdata set in setUserData()
839      */
840     @UnsupportedAppUsage
getUserData()841     public Object getUserData() {
842         return mUserData;
843     }
844 
845     /**
846      *
847      * @param userdata user can store an any userdata in the Connection object.
848      */
setUserData(Object userdata)849     public void setUserData(Object userdata) {
850         mUserData = userdata;
851     }
852 
853     /**
854      * Deflect individual Connection
855      */
deflect(String number)856     public abstract void deflect(String number) throws CallStateException;
857 
858     /**
859      * Transfer individual Connection
860      */
transfer(String number, boolean isConfirmationRequired)861     public abstract void transfer(String number, boolean isConfirmationRequired)
862             throws CallStateException;
863 
864     /**
865      * Transfer individual Connection for consultative transfer
866      */
consultativeTransfer(Connection other)867     public abstract void consultativeTransfer(Connection other) throws CallStateException;
868 
869     /**
870      * Hangup individual Connection
871      */
872     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
hangup()873     public abstract void hangup() throws CallStateException;
874 
875     /**
876      * Separate this call from its owner Call and assigns it to a new Call
877      * (eg if it is currently part of a Conference call
878      * TODO: Throw exception? Does GSM require error display on failure here?
879      */
separate()880     public abstract void separate() throws CallStateException;
881 
882     public enum PostDialState {
883         @UnsupportedAppUsage
884         NOT_STARTED,    /* The post dial string playback hasn't
885                            been started, or this call is not yet
886                            connected, or this is an incoming call */
887         @UnsupportedAppUsage
888         STARTED,        /* The post dial string playback has begun */
889         @UnsupportedAppUsage
890         WAIT,           /* The post dial string playback is waiting for a
891                            call to proceedAfterWaitChar() */
892         @UnsupportedAppUsage
893         WILD,           /* The post dial string playback is waiting for a
894                            call to proceedAfterWildChar() */
895         @UnsupportedAppUsage
896         COMPLETE,       /* The post dial string playback is complete */
897         @UnsupportedAppUsage
898         CANCELLED,       /* The post dial string playback was cancelled
899                            with cancelPostDial() */
900         PAUSE           /* The post dial string playback is pausing for a
901                            call to processNextPostDialChar*/
902     }
903 
clearUserData()904     public void clearUserData(){
905         mUserData = null;
906     }
907 
addPostDialListener(PostDialListener listener)908     public void addPostDialListener(PostDialListener listener) {
909         if (!mPostDialListeners.contains(listener)) {
910             mPostDialListeners.add(listener);
911         }
912     }
913 
removePostDialListener(PostDialListener listener)914     public final void removePostDialListener(PostDialListener listener) {
915         mPostDialListeners.remove(listener);
916     }
917 
clearPostDialListeners()918     protected final void clearPostDialListeners() {
919         if (mPostDialListeners != null) {
920             mPostDialListeners.clear();
921         }
922     }
923 
notifyPostDialListeners()924     protected final void notifyPostDialListeners() {
925         if (getPostDialState() == PostDialState.WAIT) {
926             for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) {
927                 listener.onPostDialWait();
928             }
929         }
930     }
931 
notifyPostDialListenersNextChar(char c)932     protected final void notifyPostDialListenersNextChar(char c) {
933         for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) {
934             listener.onPostDialChar(c);
935         }
936     }
937 
getPostDialState()938     public PostDialState getPostDialState() {
939         return mPostDialState;
940     }
941 
942     /**
943      * Returns the portion of the post dial string that has not
944      * yet been dialed, or "" if none
945      */
getRemainingPostDialString()946     public String getRemainingPostDialString() {
947         if (mPostDialState == PostDialState.CANCELLED
948                 || mPostDialState == PostDialState.COMPLETE
949                 || mPostDialString == null
950                 || mPostDialString.length() <= mNextPostDialChar) {
951             return "";
952         }
953 
954         return mPostDialString.substring(mNextPostDialChar);
955     }
956 
957     /**
958      * See Phone.setOnPostDialWaitCharacter()
959      */
960 
proceedAfterWaitChar()961     public abstract void proceedAfterWaitChar();
962 
963     /**
964      * See Phone.setOnPostDialWildCharacter()
965      */
proceedAfterWildChar(String str)966     public abstract void proceedAfterWildChar(String str);
967     /**
968      * Cancel any post
969      */
cancelPostDial()970     public abstract void cancelPostDial();
971 
972     /** Called when the connection has been disconnected */
onDisconnect(int cause)973     public boolean onDisconnect(int cause) {
974         return false;
975     }
976 
977     /**
978      * Returns the caller id presentation type for incoming and waiting calls
979      * @return one of PRESENTATION_*
980      */
getNumberPresentation()981     public abstract int getNumberPresentation();
982 
983     /**
984      * Returns the User to User Signaling (UUS) information associated with
985      * incoming and waiting calls
986      * @return UUSInfo containing the UUS userdata.
987      */
getUUSInfo()988     public abstract UUSInfo getUUSInfo();
989 
990     /**
991      * Returns the CallFail reason provided by the RIL with the result of
992      * RIL_REQUEST_LAST_CALL_FAIL_CAUSE
993      */
getPreciseDisconnectCause()994     public abstract int getPreciseDisconnectCause();
995 
996     /**
997      * Returns the original Connection instance associated with
998      * this Connection
999      */
getOrigConnection()1000     public Connection getOrigConnection() {
1001         return mOrigConnection;
1002     }
1003 
1004     /**
1005      * Returns whether the original ImsPhoneConnection was a member
1006      * of a conference call
1007      * @return valid only when getOrigConnection() is not null
1008      */
isMultiparty()1009     public abstract boolean isMultiparty();
1010 
1011     /**
1012      * Applicable only for IMS Call. Determines if this call is the origin of the conference call
1013      * (i.e. {@code #isConferenceHost()} is {@code true}), or if it is a member of a conference
1014      * hosted on another device.
1015      *
1016      * @return {@code true} if this call is the origin of the conference call it is a member of,
1017      *      {@code false} otherwise.
1018      */
isConferenceHost()1019     public boolean isConferenceHost() {
1020         return false;
1021     }
1022 
1023     /**
1024      * Applicable only for IMS Call. Determines if a connection is a member of a conference hosted
1025      * on another device.
1026      *
1027      * @return {@code true} if the connection is a member of a conference hosted on another device.
1028      */
isMemberOfPeerConference()1029     public boolean isMemberOfPeerConference() {
1030         return false;
1031     }
1032 
migrateFrom(Connection c)1033     public void migrateFrom(Connection c) {
1034         if (c == null) return;
1035         mListeners = c.mListeners;
1036         mDialString = c.getOrigDialString();
1037         mCreateTime = c.getCreateTime();
1038         mConnectTime = c.getConnectTime();
1039         mConnectTimeReal = c.getConnectTimeReal();
1040         mHoldingStartTime = c.getHoldingStartTime();
1041         mOrigConnection = c.getOrigConnection();
1042         mPostDialString = c.mPostDialString;
1043         mNextPostDialChar = c.mNextPostDialChar;
1044         mPostDialState = c.mPostDialState;
1045 
1046         // Migrate Emergency call parameters
1047         mIsEmergencyCall = c.isEmergencyCall();
1048         mEmergencyNumberInfo = c.getEmergencyNumberInfo();
1049         mHasKnownUserIntentEmergency = c.hasKnownUserIntentEmergency();
1050     }
1051 
1052     /**
1053      * Assign a listener to be notified of state changes.
1054      *
1055      * @param listener A listener.
1056      */
addListener(Listener listener)1057     public void addListener(Listener listener) {
1058         mListeners.add(listener);
1059     }
1060 
1061     /**
1062      * Removes a listener.
1063      *
1064      * @param listener A listener.
1065      */
removeListener(Listener listener)1066     public final void removeListener(Listener listener) {
1067         mListeners.remove(listener);
1068     }
1069 
1070     /**
1071      * Returns the current video state of the connection.
1072      *
1073      * @return The video state of the connection.
1074      */
getVideoState()1075     public int getVideoState() {
1076         return mVideoState;
1077     }
1078 
1079     /**
1080      * Called to get Connection capabilities.Returns Capabilities bitmask.
1081      * @See Connection.Capability.
1082      */
getConnectionCapabilities()1083     public int getConnectionCapabilities() {
1084         return mConnectionCapabilities;
1085     }
1086 
1087     /**
1088      * @return {@code} true if the connection has the specified capabilities.
1089      */
hasCapabilities(int connectionCapabilities)1090     public boolean hasCapabilities(int connectionCapabilities) {
1091         return (mConnectionCapabilities & connectionCapabilities) == connectionCapabilities;
1092     }
1093 
1094     /**
1095      * Applies a capability to a capabilities bit-mask.
1096      *
1097      * @param capabilities The capabilities bit-mask.
1098      * @param capability The capability to apply.
1099      * @return The capabilities bit-mask with the capability applied.
1100      */
addCapability(int capabilities, int capability)1101     public static int addCapability(int capabilities, int capability) {
1102         return capabilities | capability;
1103     }
1104 
1105     /**
1106      * Removes a capability to a capabilities bit-mask.
1107      *
1108      * @param capabilities The capabilities bit-mask.
1109      * @param capability The capability to remove.
1110      * @return The capabilities bit-mask with the capability removed.
1111      */
removeCapability(int capabilities, int capability)1112     public static int removeCapability(int capabilities, int capability) {
1113         return capabilities & ~capability;
1114     }
1115 
1116     /**
1117      * Returns whether the connection is using a wifi network.
1118      *
1119      * @return {@code True} if the connection is using a wifi network.
1120      */
isWifi()1121     public boolean isWifi() {
1122         return getCallRadioTech() == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
1123     }
1124 
1125     /**
1126      * Returns radio technology is used for the connection.
1127      *
1128      * @return the RIL Voice Radio Technology used for current connection,
1129      *         see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
1130      */
getCallRadioTech()1131     public @RilRadioTechnology int getCallRadioTech() {
1132         return mCallRadioTech;
1133     }
1134 
1135     /**
1136      * Returns whether the connection uses voip audio mode
1137      *
1138      * @return {@code True} if the connection uses voip audio mode
1139      */
getAudioModeIsVoip()1140     public boolean getAudioModeIsVoip() {
1141         return mAudioModeIsVoip;
1142     }
1143 
1144     /**
1145      * Returns the {@link android.telecom.Connection.VideoProvider} for the connection.
1146      *
1147      * @return The {@link android.telecom.Connection.VideoProvider}.
1148      */
getVideoProvider()1149     public android.telecom.Connection.VideoProvider getVideoProvider() {
1150         return mVideoProvider;
1151     }
1152 
1153     /**
1154      * Returns the audio-quality for the connection.
1155      *
1156      * @return The audio quality for the connection.
1157      */
getAudioQuality()1158     public int getAudioQuality() {
1159         return mAudioQuality;
1160     }
1161 
1162 
1163     /**
1164      * Returns the current call substate of the connection.
1165      *
1166      * @return The call substate of the connection.
1167      */
getCallSubstate()1168     public int getCallSubstate() {
1169         return mCallSubstate;
1170     }
1171 
1172 
1173     /**
1174      * Sets the videoState for the current connection and reports the changes to all listeners.
1175      * Valid video states are defined in {@link android.telecom.VideoProfile}.
1176      *
1177      * @return The video state.
1178      */
1179     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setVideoState(int videoState)1180     public void setVideoState(int videoState) {
1181         mVideoState = videoState;
1182         for (Listener l : mListeners) {
1183             l.onVideoStateChanged(mVideoState);
1184         }
1185     }
1186 
1187     /**
1188      * Called to set Connection capabilities.  This will take Capabilities bitmask as input which is
1189      * converted from Capabilities constants.
1190      *
1191      * @See Connection.Capability.
1192      * @param capabilities The Capabilities bitmask.
1193      */
setConnectionCapabilities(int capabilities)1194     public void setConnectionCapabilities(int capabilities) {
1195         if (mConnectionCapabilities != capabilities) {
1196             mConnectionCapabilities = capabilities;
1197             for (Listener l : mListeners) {
1198                 l.onConnectionCapabilitiesChanged(mConnectionCapabilities);
1199             }
1200         }
1201     }
1202 
1203     /**
1204      * Sets RIL voice radio technology used for current connection.
1205      *
1206      * @param vrat the RIL voice radio technology for current connection,
1207      *             see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
1208      */
setCallRadioTech(@ilRadioTechnology int vrat)1209     public void setCallRadioTech(@RilRadioTechnology int vrat) {
1210         if (mCallRadioTech == vrat) {
1211             return;
1212         }
1213         mCallRadioTech = vrat;
1214         for (Listener l : mListeners) {
1215             l.onCallRadioTechChanged(vrat);
1216         }
1217     }
1218 
1219     /**
1220      * Set the voip audio mode for the connection
1221      *
1222      * @param isVoip {@code True} if voip audio mode is being used.
1223      */
setAudioModeIsVoip(boolean isVoip)1224     public void setAudioModeIsVoip(boolean isVoip) {
1225         mAudioModeIsVoip = isVoip;
1226     }
1227 
1228     /**
1229      * Set the audio quality for the connection.
1230      *
1231      * @param audioQuality The audio quality.
1232      */
setAudioQuality(int audioQuality)1233     public void setAudioQuality(int audioQuality) {
1234         mAudioQuality = audioQuality;
1235         for (Listener l : mListeners) {
1236             l.onAudioQualityChanged(mAudioQuality);
1237         }
1238     }
1239 
1240     /**
1241      * Notifies interested parties of changes to the media attributes of the call.
1242      */
notifyMediaAttributesChanged()1243     public void notifyMediaAttributesChanged() {
1244         for (Listener l: mListeners) {
1245             l.onMediaAttributesChanged();
1246         }
1247     }
1248 
1249     /**
1250      * Notifies listeners that connection extras has changed.
1251      * @param extras New connection extras. This Bundle will be cloned to ensure that any concurrent
1252      * modifications to the extras Bundle do not affect Bundle operations in the onExtrasChanged
1253      * listeners.
1254      */
setConnectionExtras(Bundle extras)1255     public void setConnectionExtras(Bundle extras) {
1256         if (extras != null) {
1257             mExtras = new Bundle(extras);
1258 
1259             int previousCount = mExtras.size();
1260             // Prevent vendors from passing in extras other than primitive types and android API
1261             // parcelables.
1262             mExtras = TelephonyUtils.filterValues(mExtras);
1263             int filteredCount = mExtras.size();
1264             if (filteredCount != previousCount) {
1265                 Rlog.i(TAG, "setConnectionExtras: filtering " + (previousCount - filteredCount)
1266                         + " invalid extras.");
1267             }
1268         } else {
1269             mExtras = null;
1270         }
1271 
1272         for (Listener l : mListeners) {
1273             l.onExtrasChanged(mExtras);
1274         }
1275     }
1276 
1277     /**
1278      * Retrieves the current connection extras.
1279      * @return the connection extras.
1280      */
getConnectionExtras()1281     public Bundle getConnectionExtras() {
1282         return mExtras == null ? null : new Bundle(mExtras);
1283     }
1284 
1285     /**
1286      * @return {@code true} if answering the call will cause the current active call to be
1287      *      disconnected, {@code false} otherwise.
1288      */
isActiveCallDisconnectedOnAnswer()1289     public boolean isActiveCallDisconnectedOnAnswer() {
1290         return mAnsweringDisconnectsActiveCall;
1291     }
1292 
1293     /**
1294      * Sets whether answering this call will cause the active call to be disconnected.
1295      * <p>
1296      * Should only be set {@code true} if there is an active call and this call is ringing.
1297      *
1298      * @param answeringDisconnectsActiveCall {@code true} if answering the call will call the active
1299      *      call to be disconnected.
1300      */
setActiveCallDisconnectedOnAnswer(boolean answeringDisconnectsActiveCall)1301     public void setActiveCallDisconnectedOnAnswer(boolean answeringDisconnectsActiveCall) {
1302         mAnsweringDisconnectsActiveCall = answeringDisconnectsActiveCall;
1303     }
1304 
shouldAllowAddCallDuringVideoCall()1305     public boolean shouldAllowAddCallDuringVideoCall() {
1306         return mAllowAddCallDuringVideoCall;
1307     }
1308 
setAllowAddCallDuringVideoCall(boolean allowAddCallDuringVideoCall)1309     public void setAllowAddCallDuringVideoCall(boolean allowAddCallDuringVideoCall) {
1310         mAllowAddCallDuringVideoCall = allowAddCallDuringVideoCall;
1311     }
1312 
shouldAllowHoldingVideoCall()1313     public boolean shouldAllowHoldingVideoCall() {
1314         return mAllowHoldingVideoCall;
1315     }
1316 
setAllowHoldingVideoCall(boolean allowHoldingVideoCall)1317     public void setAllowHoldingVideoCall(boolean allowHoldingVideoCall) {
1318         mAllowHoldingVideoCall = allowHoldingVideoCall;
1319     }
1320 
1321     /**
1322      * Sets whether the connection is the result of an external call which was pulled to the local
1323      * device.
1324      *
1325      * @param isPulledCall {@code true} if this connection is the result of pulling an external call
1326      *      to the local device.
1327      */
setIsPulledCall(boolean isPulledCall)1328     public void setIsPulledCall(boolean isPulledCall) {
1329         mIsPulledCall = isPulledCall;
1330     }
1331 
isPulledCall()1332     public boolean isPulledCall() {
1333         return mIsPulledCall;
1334     }
1335 
1336     /**
1337      * For an external call which is being pulled (e.g. {@link #isPulledCall()} is {@code true}),
1338      * sets the dialog Id for the external call.  Used to handle failures to pull a call so that the
1339      * pulled call can be reconciled with its original external connection.
1340      *
1341      * @param pulledDialogId The dialog id associated with a pulled call.
1342      */
setPulledDialogId(int pulledDialogId)1343     public void setPulledDialogId(int pulledDialogId) {
1344         mPulledDialogId = pulledDialogId;
1345     }
1346 
getPulledDialogId()1347     public int getPulledDialogId() {
1348         return mPulledDialogId;
1349     }
1350 
1351     /**
1352      * Sets the call substate for the current connection and reports the changes to all listeners.
1353      * Valid call substates are defined in {@link android.telecom.Connection}.
1354      *
1355      * @return The call substate.
1356      */
setCallSubstate(int callSubstate)1357     public void setCallSubstate(int callSubstate) {
1358         mCallSubstate = callSubstate;
1359         for (Listener l : mListeners) {
1360             l.onCallSubstateChanged(mCallSubstate);
1361         }
1362     }
1363 
1364     /**
1365      * Sets the {@link android.telecom.Connection.VideoProvider} for the connection.
1366      *
1367      * @param videoProvider The video call provider.
1368      */
setVideoProvider(android.telecom.Connection.VideoProvider videoProvider)1369     public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) {
1370         mVideoProvider = videoProvider;
1371         for (Listener l : mListeners) {
1372             l.onVideoProviderChanged(mVideoProvider);
1373         }
1374     }
1375 
1376     /**
1377      * {@link CallTracker#convertNumberIfNecessary(Phone, String)} can be used to convert a dialed
1378      * number to another number based on carrier config.  This is used where a carrier wishes to
1379      * redirect certain short codes such as *55 to another number (e.g. a 1-800 service number).
1380      * The {@link CallTracker} sub-classes call
1381      * {@link CallTracker#convertNumberIfNecessary(Phone, String)} to retrieve the newly converted
1382      * number and instantiate the {@link Connection} instance using the converted number so that the
1383      * system will dial out the substitution number instead of the originally dialed one.  This gem
1384      * of a method is called after the dialing process to restore the originally dialed number and
1385      * keep track of the fact that a converted number was used to place the call.
1386      * @param oriNumber The original number prior to conversion.
1387      */
restoreDialedNumberAfterConversion(String oriNumber)1388     public void restoreDialedNumberAfterConversion(String oriNumber) {
1389         mNumberConverted = true;
1390         mConvertedNumber = mAddress;
1391         mAddress = oriNumber;
1392         mDialString = oriNumber;
1393     }
1394 
1395     /**
1396      * Changes the address and presentation for this call.
1397      * @param newAddress The new address.
1398      * @param numberPresentation The number presentation for the address.
1399      */
setAddress(String newAddress, int numberPresentation)1400     public void setAddress(String newAddress, int numberPresentation) {
1401         Rlog.i(TAG, "setAddress = " + newAddress);
1402         mAddress = newAddress;
1403         mNumberPresentation = numberPresentation;
1404     }
1405 
setDialString(String newDialString)1406     public void setDialString(String newDialString) {
1407         mDialString = newDialString;
1408     }
1409 
1410     /**
1411      * Notifies listeners of a change to conference participant(s).
1412      *
1413      * @param conferenceParticipants The participant(s).
1414      */
updateConferenceParticipants(List<ConferenceParticipant> conferenceParticipants)1415     public void updateConferenceParticipants(List<ConferenceParticipant> conferenceParticipants) {
1416         for (Listener l : mListeners) {
1417             l.onConferenceParticipantsChanged(conferenceParticipants);
1418         }
1419     }
1420 
1421     /**
1422      * Notifies listeners of a change to the multiparty state of the connection.
1423      *
1424      * @param isMultiparty The participant(s).
1425      */
updateMultipartyState(boolean isMultiparty)1426     public void updateMultipartyState(boolean isMultiparty) {
1427         for (Listener l : mListeners) {
1428             l.onMultipartyStateChanged(isMultiparty);
1429         }
1430     }
1431 
1432     /**
1433      * Notifies listeners of a failure in merging this connection with the background connection.
1434      */
onConferenceMergeFailed()1435     public void onConferenceMergeFailed() {
1436         for (Listener l : mListeners) {
1437             l.onConferenceMergedFailed();
1438         }
1439     }
1440 
1441     /**
1442      * Notifies that the underlying phone has exited ECM mode.
1443      */
onExitedEcmMode()1444     public void onExitedEcmMode() {
1445         for (Listener l : mListeners) {
1446             l.onExitedEcmMode();
1447         }
1448     }
1449 
1450     /**
1451      * Notifies the connection that a call to {@link #pullExternalCall()} has failed to pull the
1452      * call to the local device.
1453      *
1454      * @param externalConnection The original
1455      *      {@link com.android.internal.telephony.imsphone.ImsExternalConnection} from which the
1456      *      pull was initiated.
1457      */
onCallPullFailed(Connection externalConnection)1458     public void onCallPullFailed(Connection externalConnection) {
1459         for (Listener l : mListeners) {
1460             l.onCallPullFailed(externalConnection);
1461         }
1462     }
1463 
onOriginalConnectionReplaced(Connection newConnection)1464     public void onOriginalConnectionReplaced(Connection newConnection) {
1465         for (Listener l : mListeners) {
1466             l.onOriginalConnectionReplaced(newConnection);
1467         }
1468     }
1469     /**
1470      * Notifies the connection that there was a failure while handing over to WIFI.
1471      */
onHandoverToWifiFailed()1472     public void onHandoverToWifiFailed() {
1473         for (Listener l : mListeners) {
1474             l.onHandoverToWifiFailed();
1475         }
1476     }
1477 
1478     /**
1479      * Notifies the connection of a connection event.
1480      */
onConnectionEvent(String event, Bundle extras)1481     public void onConnectionEvent(String event, Bundle extras) {
1482         for (Listener l : mListeners) {
1483             l.onConnectionEvent(event, extras);
1484         }
1485     }
1486 
1487     /**
1488      * Notifies this Connection of a request to disconnect a participant of the conference managed
1489      * by the connection.
1490      *
1491      * @param endpoint the {@link Uri} of the participant to disconnect.
1492      */
onDisconnectConferenceParticipant(Uri endpoint)1493     public void onDisconnectConferenceParticipant(Uri endpoint) {
1494     }
1495 
1496     /**
1497      * Called by a {@link android.telecom.Connection} to indicate that this call should be pulled
1498      * to the local device.
1499      */
pullExternalCall()1500     public void pullExternalCall() {
1501     }
1502 
onRttModifyRequestReceived()1503     public void onRttModifyRequestReceived() {
1504         for (Listener l : mListeners) {
1505             l.onRttModifyRequestReceived();
1506         }
1507     }
1508 
onRttModifyResponseReceived(int status)1509     public void onRttModifyResponseReceived(int status) {
1510         for (Listener l : mListeners) {
1511             l.onRttModifyResponseReceived(status);
1512         }
1513     }
1514 
onRttInitiated()1515     public void onRttInitiated() {
1516         for (Listener l : mListeners) {
1517             l.onRttInitiated();
1518         }
1519     }
1520 
onRttTerminated()1521     public void onRttTerminated() {
1522         for (Listener l : mListeners) {
1523             l.onRttTerminated();
1524         }
1525     }
1526     /**
1527      * Notify interested parties that this connection disconnected.
1528      * {@code TelephonyConnection}, for example, uses this.
1529      * @param reason the disconnect code, per {@link DisconnectCause}.
1530      */
notifyDisconnect(int reason)1531     protected void notifyDisconnect(int reason) {
1532         Rlog.i(TAG, "notifyDisconnect: callId=" + getTelecomCallId() + ", reason=" + reason);
1533         for (Listener l : mListeners) {
1534             l.onDisconnect(reason);
1535         }
1536     }
1537 
1538     /**
1539      *
1540      */
getPhoneType()1541     public int getPhoneType() {
1542         return mPhoneType;
1543     }
1544 
1545     /**
1546      * Reset the Connection time and Duration
1547      */
resetConnectionTime()1548     public void resetConnectionTime() {
1549         if (mPhoneType == PhoneConstants.PHONE_TYPE_CDMA_LTE ||
1550                 mPhoneType == PhoneConstants.PHONE_TYPE_CDMA) {
1551             mConnectTime = System.currentTimeMillis();
1552             mConnectTimeReal = SystemClock.elapsedRealtime();
1553             mDuration = 0;
1554         }
1555     }
1556 
1557     /**
1558      * Sets whether this {@link Connection} has been identified by the network as an emergency call.
1559      * @param isNetworkIdentifiedEmergencyCall {@code true} if ecall, {@code false} otherwise.
1560      */
setIsNetworkIdentifiedEmergencyCall(boolean isNetworkIdentifiedEmergencyCall)1561     public void setIsNetworkIdentifiedEmergencyCall(boolean isNetworkIdentifiedEmergencyCall) {
1562         mIsNetworkIdentifiedEmergencyCall = isNetworkIdentifiedEmergencyCall;
1563         for (Listener l : mListeners) {
1564             l.onIsNetworkEmergencyCallChanged(isNetworkIdentifiedEmergencyCall);
1565         }
1566     }
1567 
1568     /**
1569      * @return Whether this {@link Connection} has been identified by the network as an emergency
1570      * call.
1571      */
isNetworkIdentifiedEmergencyCall()1572     public boolean isNetworkIdentifiedEmergencyCall() {
1573         return mIsNetworkIdentifiedEmergencyCall;
1574     }
1575 
1576     /**
1577      * Build a human representation of a connection instance, suitable for debugging.
1578      * Don't log personal stuff unless in debug mode.
1579      * @return a string representing the internal state of this connection.
1580      */
toString()1581     public String toString() {
1582         StringBuilder str = new StringBuilder(128);
1583 
1584         str.append(" callId: " + getTelecomCallId());
1585         str.append(" objId: " + System.identityHashCode(this));
1586         str.append(" isExternal: " + (((mConnectionCapabilities & Capability.IS_EXTERNAL_CONNECTION)
1587                 == Capability.IS_EXTERNAL_CONNECTION) ? "Y" : "N"));
1588         if (Rlog.isLoggable(LOG_TAG, Log.DEBUG)) {
1589             str.append("addr: " + getAddress())
1590                     .append(" pres.: " + getNumberPresentation())
1591                     .append(" dial: " + getOrigDialString())
1592                     .append(" postdial: " + getRemainingPostDialString())
1593                     .append(" cnap name: " + getCnapName())
1594                     .append("(" + getCnapNamePresentation() + ")");
1595         }
1596         str.append(" incoming: " + isIncoming())
1597                 .append(" state: " + getState())
1598                 .append(" post dial state: " + getPostDialState());
1599         return str.toString();
1600     }
1601 
1602     /**
1603      * Get current audio codec.
1604      * @return current audio codec.
1605      */
getAudioCodec()1606     public int getAudioCodec() {
1607         return mAudioCodec;
1608     }
1609 
1610     /**
1611      * @return the audio codec bitrate in kbps.
1612      */
getAudioCodecBitrateKbps()1613     public float getAudioCodecBitrateKbps() {
1614         return mAudioCodecBitrateKbps;
1615     }
1616 
1617     /**
1618      * @return the audio codec bandwidth in kHz.
1619      */
getAudioCodecBandwidthKhz()1620     public float getAudioCodecBandwidthKhz() {
1621         return mAudioCodecBandwidthKhz;
1622     }
1623 
1624     /**
1625      * @return The number verification status; only applicable for IMS calls.
1626      */
getNumberVerificationStatus()1627     public @android.telecom.Connection.VerificationStatus int getNumberVerificationStatus() {
1628         return mNumberVerificationStatus;
1629     }
1630 
1631     /**
1632      * Sets the number verification status.
1633      * @param verificationStatus The new verification status
1634      */
setNumberVerificationStatus( @ndroid.telecom.Connection.VerificationStatus int verificationStatus)1635     public void setNumberVerificationStatus(
1636             @android.telecom.Connection.VerificationStatus int verificationStatus) {
1637         mNumberVerificationStatus = verificationStatus;
1638     }
1639 
1640     /**
1641      * Called to report a DTMF digit received from the network.
1642      * @param digit the received digit.
1643      */
receivedDtmfDigit(char digit)1644     public void receivedDtmfDigit(char digit) {
1645         for (Listener l : mListeners) {
1646             l.onReceivedDtmfDigit(digit);
1647         }
1648     }
1649 
1650     /**
1651      * Called to report audio mode changed for Voip.
1652      * @param imsAudioHandler the received value to handle the audio for this IMS call.
1653      */
onAudioModeIsVoipChanged(@msAudioHandler int imsAudioHandler)1654     public void onAudioModeIsVoipChanged(@ImsAudioHandler int imsAudioHandler) {
1655         Rlog.i(TAG, "onAudioModeIsVoipChanged: conn imsAudioHandler " + imsAudioHandler);
1656 
1657         boolean isVoip = imsAudioHandler == MmTelFeature.AUDIO_HANDLER_ANDROID;
1658         if (isVoip == mAudioModeIsVoip) return;
1659         mAudioModeIsVoip = isVoip;
1660 
1661         Rlog.i(TAG, "onAudioModeIsVoipChanged: isVoip: " + isVoip
1662                 + "mAudioModeIsVoip:" + mAudioModeIsVoip);
1663 
1664         for (Listener l : mListeners) {
1665             l.onAudioModeIsVoipChanged(imsAudioHandler);
1666         }
1667     }
1668 
1669     /**
1670      * Called to report RTP header extensions received from the network.
1671      * @param extensionData the received extension data.
1672      */
receivedRtpHeaderExtensions(@onNull Set<RtpHeaderExtension> extensionData)1673     public void receivedRtpHeaderExtensions(@NonNull Set<RtpHeaderExtension> extensionData) {
1674         for (Listener l : mListeners) {
1675             l.onReceivedRtpHeaderExtensions(extensionData);
1676         }
1677     }
1678 }
1679