1617 lines
53 KiB
Java
1617 lines
53 KiB
Java
/*
|
|
* Copyright (C) 2006 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.internal.telephony;
|
|
|
|
import android.annotation.NonNull;
|
|
import android.compat.annotation.UnsupportedAppUsage;
|
|
import android.net.Uri;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.os.SystemClock;
|
|
import android.telephony.DisconnectCause;
|
|
import android.telephony.ServiceState;
|
|
import android.telephony.ServiceState.RilRadioTechnology;
|
|
import android.telephony.emergency.EmergencyNumber;
|
|
import android.telephony.ims.RtpHeaderExtension;
|
|
import android.telephony.ims.feature.MmTelFeature;
|
|
import android.telephony.ims.feature.MmTelFeature.ImsAudioHandler;
|
|
import android.util.Log;
|
|
|
|
import com.android.ims.internal.ConferenceParticipant;
|
|
import com.android.internal.annotations.VisibleForTesting;
|
|
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
|
|
import com.android.internal.telephony.util.TelephonyUtils;
|
|
import com.android.telephony.Rlog;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.concurrent.CopyOnWriteArraySet;
|
|
|
|
/**
|
|
* {@hide}
|
|
*/
|
|
public abstract class Connection {
|
|
private static final String TAG = "Connection";
|
|
|
|
public static final String ADHOC_CONFERENCE_ADDRESS = "tel:conf-factory";
|
|
|
|
public interface PostDialListener {
|
|
void onPostDialWait();
|
|
void onPostDialChar(char c);
|
|
}
|
|
|
|
/**
|
|
* Capabilities that will be mapped to telecom connection
|
|
* capabilities.
|
|
*/
|
|
public static class Capability {
|
|
|
|
/**
|
|
* For an IMS video call, indicates that the local side of the call supports downgrading
|
|
* from a video call to an audio-only call.
|
|
*/
|
|
public static final int SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL = 0x00000001;
|
|
|
|
/**
|
|
* For an IMS video call, indicates that the peer supports downgrading to an audio-only
|
|
* call.
|
|
*/
|
|
public static final int SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE = 0x00000002;
|
|
|
|
/**
|
|
* For an IMS call, indicates that the call supports video locally.
|
|
*/
|
|
public static final int SUPPORTS_VT_LOCAL_BIDIRECTIONAL = 0x00000004;
|
|
|
|
/**
|
|
* For an IMS call, indicates that the peer supports video.
|
|
*/
|
|
public static final int SUPPORTS_VT_REMOTE_BIDIRECTIONAL = 0x00000008;
|
|
|
|
/**
|
|
* Indicates that the connection is an external connection (e.g. an instance of the class
|
|
* {@link com.android.internal.telephony.imsphone.ImsExternalConnection}.
|
|
*/
|
|
public static final int IS_EXTERNAL_CONNECTION = 0x00000010;
|
|
|
|
/**
|
|
* Indicates that this external connection can be pulled from the remote device to the
|
|
* local device.
|
|
*/
|
|
public static final int IS_PULLABLE = 0x00000020;
|
|
|
|
/**
|
|
* For an IMS call, indicates that the peer supports RTT.
|
|
*/
|
|
public static final int SUPPORTS_RTT_REMOTE = 0x00000040;
|
|
}
|
|
|
|
/**
|
|
* Listener interface for events related to the connection which should be reported to the
|
|
* {@link android.telecom.Connection}.
|
|
*/
|
|
public interface Listener {
|
|
public void onVideoStateChanged(int videoState);
|
|
public void onConnectionCapabilitiesChanged(int capability);
|
|
public void onCallRadioTechChanged(@RilRadioTechnology int vrat);
|
|
public void onVideoProviderChanged(
|
|
android.telecom.Connection.VideoProvider videoProvider);
|
|
public void onAudioQualityChanged(int audioQuality);
|
|
public void onMediaAttributesChanged();
|
|
public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants);
|
|
public void onCallSubstateChanged(int callSubstate);
|
|
public void onMultipartyStateChanged(boolean isMultiParty);
|
|
public void onConferenceMergedFailed();
|
|
public void onExtrasChanged(Bundle extras);
|
|
public void onExitedEcmMode();
|
|
public void onCallPullFailed(Connection externalConnection);
|
|
public void onHandoverToWifiFailed();
|
|
public void onConnectionEvent(String event, Bundle extras);
|
|
public void onRttModifyRequestReceived();
|
|
public void onRttModifyResponseReceived(int status);
|
|
public void onDisconnect(int cause);
|
|
public void onRttInitiated();
|
|
public void onRttTerminated();
|
|
public void onOriginalConnectionReplaced(Connection newConnection);
|
|
public void onIsNetworkEmergencyCallChanged(boolean isEmergencyCall);
|
|
|
|
/**
|
|
* Indicates a DTMF digit has been received from the network.
|
|
* @param digit The DTMF digit.
|
|
*/
|
|
public void onReceivedDtmfDigit(char digit);
|
|
|
|
/**
|
|
* Indicates data from an RTP header extension has been received from the network.
|
|
* @param extensionData The extension data.
|
|
*/
|
|
public void onReceivedRtpHeaderExtensions(@NonNull Set<RtpHeaderExtension> extensionData);
|
|
|
|
/**
|
|
* Indicates that the audio handler for this connection is changed.
|
|
*
|
|
* @param imsAudioHandler {@link MmTelFeature#ImsAudioHandler}.
|
|
*/
|
|
void onAudioModeIsVoipChanged(@ImsAudioHandler int imsAudioHandler);
|
|
}
|
|
|
|
/**
|
|
* Base listener implementation.
|
|
*/
|
|
public abstract static class ListenerBase implements Listener {
|
|
@Override
|
|
public void onVideoStateChanged(int videoState) {}
|
|
@Override
|
|
public void onConnectionCapabilitiesChanged(int capability) {}
|
|
@Override
|
|
public void onCallRadioTechChanged(@RilRadioTechnology int vrat) {}
|
|
@Override
|
|
public void onVideoProviderChanged(
|
|
android.telecom.Connection.VideoProvider videoProvider) {}
|
|
@Override
|
|
public void onAudioQualityChanged(int audioQuality) {}
|
|
@Override
|
|
public void onMediaAttributesChanged() {}
|
|
@Override
|
|
public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants) {}
|
|
@Override
|
|
public void onCallSubstateChanged(int callSubstate) {}
|
|
@Override
|
|
public void onMultipartyStateChanged(boolean isMultiParty) {}
|
|
@Override
|
|
public void onConferenceMergedFailed() {}
|
|
@Override
|
|
public void onExtrasChanged(Bundle extras) {}
|
|
@Override
|
|
public void onExitedEcmMode() {}
|
|
@Override
|
|
public void onCallPullFailed(Connection externalConnection) {}
|
|
@Override
|
|
public void onHandoverToWifiFailed() {}
|
|
@Override
|
|
public void onConnectionEvent(String event, Bundle extras) {}
|
|
@Override
|
|
public void onRttModifyRequestReceived() {}
|
|
@Override
|
|
public void onRttModifyResponseReceived(int status) {}
|
|
@Override
|
|
public void onDisconnect(int cause) {}
|
|
@Override
|
|
public void onRttInitiated() {}
|
|
@Override
|
|
public void onRttTerminated() {}
|
|
@Override
|
|
public void onOriginalConnectionReplaced(Connection newConnection) {}
|
|
@Override
|
|
public void onIsNetworkEmergencyCallChanged(boolean isEmergencyCall) {}
|
|
@Override
|
|
public void onReceivedDtmfDigit(char digit) {}
|
|
@Override
|
|
public void onReceivedRtpHeaderExtensions(@NonNull Set<RtpHeaderExtension> extensionData) {}
|
|
@Override
|
|
public void onAudioModeIsVoipChanged(@ImsAudioHandler int imsAudioHandler) {}
|
|
}
|
|
|
|
public static final int AUDIO_QUALITY_STANDARD = 1;
|
|
public static final int AUDIO_QUALITY_HIGH_DEFINITION = 2;
|
|
// the threshold used to compare mAudioCodecBitrateKbps and mAudioCodecBandwidth.
|
|
public static final float THRESHOLD = 0.01f;
|
|
|
|
/**
|
|
* The telecom internal call ID associated with this connection. Only to be used for debugging
|
|
* purposes.
|
|
*/
|
|
private String mTelecomCallId;
|
|
|
|
//Caller Name Display
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
protected String mCnapName;
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
protected int mCnapNamePresentation = PhoneConstants.PRESENTATION_ALLOWED;
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
protected String mAddress; // MAY BE NULL!!!
|
|
// The VERSTAT number verification status; defaults to not verified.
|
|
protected @android.telecom.Connection.VerificationStatus int mNumberVerificationStatus =
|
|
android.telecom.Connection.VERIFICATION_STATUS_NOT_VERIFIED;
|
|
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
protected String mDialString; // outgoing calls only
|
|
protected String[] mParticipantsToDial;// outgoing calls only
|
|
protected boolean mIsAdhocConference;
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
protected int mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
protected boolean mIsIncoming;
|
|
/*
|
|
* These time/timespan values are based on System.currentTimeMillis(),
|
|
* i.e., "wall clock" time.
|
|
*/
|
|
protected long mCreateTime;
|
|
protected long mConnectTime;
|
|
/*
|
|
* These time/timespan values are based on SystemClock.elapsedRealTime(),
|
|
* i.e., time since boot. They are appropriate for comparison and
|
|
* calculating deltas.
|
|
*/
|
|
protected long mConnectTimeReal;
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
protected long mDuration;
|
|
protected long mHoldingStartTime; // The time when the Connection last transitioned
|
|
// into HOLDING
|
|
protected Connection mOrigConnection;
|
|
private List<PostDialListener> mPostDialListeners = new ArrayList<>();
|
|
public Set<Listener> mListeners = new CopyOnWriteArraySet<>();
|
|
|
|
protected boolean mNumberConverted = false;
|
|
protected String mConvertedNumber;
|
|
|
|
protected ArrayList<String> mForwardedNumber = null; //May be null. Incoming calls only.
|
|
|
|
protected String mPostDialString; // outgoing calls only
|
|
protected int mNextPostDialChar; // index into postDialString
|
|
|
|
protected int mCause = DisconnectCause.NOT_DISCONNECTED;
|
|
protected PostDialState mPostDialState = PostDialState.NOT_STARTED;
|
|
|
|
// Store the current audio code
|
|
protected int mAudioCodec;
|
|
// audio codec bitrate in kbps
|
|
protected float mAudioCodecBitrateKbps;
|
|
// audio codec bandwidth in kHz
|
|
protected float mAudioCodecBandwidthKhz;
|
|
|
|
@UnsupportedAppUsage
|
|
private static String LOG_TAG = "Connection";
|
|
|
|
Object mUserData;
|
|
private int mVideoState;
|
|
private int mConnectionCapabilities;
|
|
/**
|
|
* Determines the call radio technology for current connection.
|
|
*
|
|
* This is used to propagate the call radio technology to upper layer.
|
|
*/
|
|
private @RilRadioTechnology int mCallRadioTech =
|
|
ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
|
|
private boolean mAudioModeIsVoip;
|
|
private int mAudioQuality;
|
|
private int mCallSubstate;
|
|
private android.telecom.Connection.VideoProvider mVideoProvider;
|
|
public Call.State mPreHandoverState = Call.State.IDLE;
|
|
private Bundle mExtras;
|
|
private int mPhoneType;
|
|
private boolean mAnsweringDisconnectsActiveCall;
|
|
private boolean mAllowAddCallDuringVideoCall;
|
|
private boolean mAllowHoldingVideoCall;
|
|
|
|
private boolean mIsEmergencyCall;
|
|
|
|
/**
|
|
* The emergency number information, only valid if {@link #isEmergencyCall} returns
|
|
* {@code true}.
|
|
*/
|
|
private EmergencyNumber mEmergencyNumberInfo;
|
|
|
|
/**
|
|
* Whether the call is from emergency dialer, only valid if {@link #isEmergencyCall} returns
|
|
* {@code true}.
|
|
*/
|
|
private boolean mHasKnownUserIntentEmergency;
|
|
|
|
/**
|
|
* When {@code true}, the network has indicated that this is an emergency call.
|
|
*/
|
|
private boolean mIsNetworkIdentifiedEmergencyCall;
|
|
|
|
/**
|
|
* Used to indicate that this originated from pulling a {@link android.telecom.Connection} with
|
|
* {@link android.telecom.Connection#PROPERTY_IS_EXTERNAL_CALL}.
|
|
*/
|
|
private boolean mIsPulledCall = false;
|
|
|
|
/**
|
|
* Where {@link #mIsPulledCall} is {@code true}, contains the dialog Id of the external call
|
|
* which is being pulled (e.g.
|
|
* {@link com.android.internal.telephony.imsphone.ImsExternalConnection#getCallId()}).
|
|
*/
|
|
private int mPulledDialogId;
|
|
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
protected Connection(int phoneType) {
|
|
mPhoneType = phoneType;
|
|
}
|
|
|
|
/* Instance Methods */
|
|
|
|
/**
|
|
* PhoneFactory Dependencies for testing.
|
|
*/
|
|
@VisibleForTesting
|
|
public interface PhoneFactoryProxy {
|
|
Phone getPhone(int index);
|
|
Phone getDefaultPhone();
|
|
Phone[] getPhones();
|
|
}
|
|
|
|
private PhoneFactoryProxy mPhoneFactoryProxy = new PhoneFactoryProxy() {
|
|
@Override
|
|
public Phone getPhone(int index) {
|
|
return PhoneFactory.getPhone(index);
|
|
}
|
|
|
|
@Override
|
|
public Phone getDefaultPhone() {
|
|
return PhoneFactory.getDefaultPhone();
|
|
}
|
|
|
|
@Override
|
|
public Phone[] getPhones() {
|
|
return PhoneFactory.getPhones();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Overrides PhoneFactory dependencies for testing.
|
|
*/
|
|
@VisibleForTesting
|
|
public void setPhoneFactoryProxy(PhoneFactoryProxy proxy) {
|
|
mPhoneFactoryProxy = proxy;
|
|
}
|
|
|
|
/**
|
|
* @return The telecom internal call ID associated with this connection. Only to be used for
|
|
* debugging purposes.
|
|
*/
|
|
public String getTelecomCallId() {
|
|
return mTelecomCallId;
|
|
}
|
|
|
|
/**
|
|
* Sets the telecom call ID associated with this connection.
|
|
*
|
|
* @param telecomCallId The telecom call ID.
|
|
*/
|
|
public void setTelecomCallId(String telecomCallId) {
|
|
mTelecomCallId = telecomCallId;
|
|
}
|
|
|
|
/**
|
|
* Gets address (e.g. phone number) associated with connection.
|
|
* TODO: distinguish reasons for unavailability
|
|
*
|
|
* @return address or null if unavailable
|
|
*/
|
|
|
|
@UnsupportedAppUsage
|
|
public String getAddress() {
|
|
return mAddress;
|
|
}
|
|
|
|
/**
|
|
* Gets the participants address (e.g. phone number) associated with connection.
|
|
*
|
|
* @return address or null if unavailable
|
|
*/
|
|
public String[] getParticipantsToDial() {
|
|
return mParticipantsToDial;
|
|
}
|
|
|
|
// return whether connection is AdhocConference or not
|
|
public boolean isAdhocConference() {
|
|
return mIsAdhocConference;
|
|
}
|
|
|
|
/**
|
|
* Gets redirecting address (e.g. phone number) associated with connection.
|
|
*
|
|
* @return ArrayList of the forwarded number or null if unavailable
|
|
*/
|
|
public ArrayList<String> getForwardedNumber() {
|
|
return mForwardedNumber;
|
|
}
|
|
|
|
/**
|
|
* Gets CNAP name associated with connection.
|
|
* @return cnap name or null if unavailable
|
|
*/
|
|
public String getCnapName() {
|
|
return mCnapName;
|
|
}
|
|
|
|
/**
|
|
* Get original dial string.
|
|
* @return original dial string or null if unavailable
|
|
*/
|
|
public String getOrigDialString(){
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get the number, as set by {@link #restoreDialedNumberAfterConversion(String)}.
|
|
* @return The converted number.
|
|
*/
|
|
@VisibleForTesting
|
|
public String getConvertedNumber() {
|
|
return mConvertedNumber;
|
|
}
|
|
|
|
/**
|
|
* Gets CNAP presentation associated with connection.
|
|
* @return cnap name or null if unavailable
|
|
*/
|
|
|
|
public int getCnapNamePresentation() {
|
|
return mCnapNamePresentation;
|
|
}
|
|
|
|
/**
|
|
* @return Call that owns this Connection, or null if none
|
|
*/
|
|
@UnsupportedAppUsage
|
|
public abstract Call getCall();
|
|
|
|
/**
|
|
* Connection create time in currentTimeMillis() format
|
|
* Basically, set when object is created.
|
|
* Effectively, when an incoming call starts ringing or an
|
|
* outgoing call starts dialing
|
|
*/
|
|
@UnsupportedAppUsage
|
|
public long getCreateTime() {
|
|
return mCreateTime;
|
|
}
|
|
|
|
/**
|
|
* Connection connect time in currentTimeMillis() format.
|
|
* For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition.
|
|
* For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition.
|
|
* Returns 0 before then.
|
|
*/
|
|
@UnsupportedAppUsage
|
|
public long getConnectTime() {
|
|
return mConnectTime;
|
|
}
|
|
|
|
/**
|
|
* Sets the Connection connect time in currentTimeMillis() format.
|
|
*
|
|
* @param connectTime the new connect time.
|
|
*/
|
|
public void setConnectTime(long connectTime) {
|
|
mConnectTime = connectTime;
|
|
}
|
|
|
|
/**
|
|
* Sets the Connection connect time in {@link SystemClock#elapsedRealtime()} format.
|
|
*
|
|
* @param connectTimeReal the new connect time.
|
|
*/
|
|
public void setConnectTimeReal(long connectTimeReal) {
|
|
mConnectTimeReal = connectTimeReal;
|
|
}
|
|
|
|
/**
|
|
* Connection connect time in elapsedRealtime() format.
|
|
* For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition.
|
|
* For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition.
|
|
* Returns 0 before then.
|
|
*/
|
|
public long getConnectTimeReal() {
|
|
return mConnectTimeReal;
|
|
}
|
|
|
|
/**
|
|
* Disconnect time in currentTimeMillis() format.
|
|
* The time when this Connection makes a transition into ENDED or FAIL.
|
|
* Returns 0 before then.
|
|
*/
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
public abstract long getDisconnectTime();
|
|
|
|
/**
|
|
* Returns the number of milliseconds the call has been connected,
|
|
* or 0 if the call has never connected.
|
|
* If the call is still connected, then returns the elapsed
|
|
* time since connect.
|
|
*/
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
public long getDurationMillis() {
|
|
if (mConnectTimeReal == 0) {
|
|
return 0;
|
|
} else if (mDuration == 0) {
|
|
return SystemClock.elapsedRealtime() - mConnectTimeReal;
|
|
} else {
|
|
return mDuration;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The time when this Connection last transitioned into HOLDING
|
|
* in elapsedRealtime() format.
|
|
* Returns 0, if it has never made a transition into HOLDING.
|
|
*/
|
|
public long getHoldingStartTime() {
|
|
return mHoldingStartTime;
|
|
}
|
|
|
|
/**
|
|
* If this connection is HOLDING, return the number of milliseconds
|
|
* that it has been on hold for (approximately).
|
|
* If this connection is in any other state, return 0.
|
|
*/
|
|
|
|
public abstract long getHoldDurationMillis();
|
|
|
|
/**
|
|
* Returns call disconnect cause. Values are defined in
|
|
* {@link android.telephony.DisconnectCause}. If the call is not yet
|
|
* disconnected, NOT_DISCONNECTED is returned.
|
|
*/
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
public int getDisconnectCause() {
|
|
return mCause;
|
|
}
|
|
|
|
/**
|
|
* Returns a string disconnect cause which is from vendor.
|
|
* Vendors may use this string to explain the underline causes of failed calls.
|
|
* There is no guarantee that it is non-null nor it'll have meaningful stable values.
|
|
* Only use it when getDisconnectCause() returns a value that is not specific enough, like
|
|
* ERROR_UNSPECIFIED.
|
|
*/
|
|
public abstract String getVendorDisconnectCause();
|
|
|
|
/**
|
|
* Returns true of this connection originated elsewhere
|
|
* ("MT" or mobile terminated; another party called this terminal)
|
|
* or false if this call originated here (MO or mobile originated).
|
|
*/
|
|
@UnsupportedAppUsage
|
|
public boolean isIncoming() {
|
|
return mIsIncoming;
|
|
}
|
|
|
|
/**
|
|
* Sets whether this call is an incoming call or not.
|
|
* @param isIncoming {@code true} if the call is an incoming call, {@code false} if it is an
|
|
* outgoing call.
|
|
*/
|
|
public void setIsIncoming(boolean isIncoming) {
|
|
mIsIncoming = isIncoming;
|
|
}
|
|
|
|
/**
|
|
* Checks if the connection is for an emergency call.
|
|
*
|
|
* @return {@code true} if the call is an emergency call
|
|
* or {@code false} otherwise.
|
|
*/
|
|
public boolean isEmergencyCall() {
|
|
return mIsEmergencyCall;
|
|
}
|
|
|
|
/**
|
|
* Get the emergency number info. The value is valid only if {@link #isEmergencyCall()}
|
|
* returns {@code true}.
|
|
*
|
|
* @return the emergency number info
|
|
*/
|
|
public EmergencyNumber getEmergencyNumberInfo() {
|
|
return mEmergencyNumberInfo;
|
|
}
|
|
|
|
/**
|
|
* Checks if we have known the user's intent for the call is emergency.
|
|
*
|
|
* This is only used to specify when the dialed number is ambiguous, identified as both
|
|
* emergency number and any other non-emergency number; e.g. in some situation, 611 could
|
|
* be both an emergency number in a country and a non-emergency number of a carrier's
|
|
* customer service hotline.
|
|
*
|
|
* @return whether the call is from emergency dialer
|
|
*/
|
|
public boolean hasKnownUserIntentEmergency() {
|
|
return mHasKnownUserIntentEmergency;
|
|
}
|
|
|
|
/**
|
|
* Set the emergency number information if it is an emergency call.
|
|
*
|
|
* @hide
|
|
*/
|
|
public void setEmergencyCallInfo(CallTracker ct) {
|
|
if (ct != null) {
|
|
Phone currentPhone = ct.getPhone();
|
|
if (currentPhone != null) {
|
|
EmergencyNumberTracker tracker = currentPhone.getEmergencyNumberTracker();
|
|
if (tracker != null) {
|
|
EmergencyNumber num = tracker.getEmergencyNumber(mAddress);
|
|
Phone[] allPhones = mPhoneFactoryProxy.getPhones();
|
|
if (num != null) {
|
|
mIsEmergencyCall = true;
|
|
mEmergencyNumberInfo = num;
|
|
} else if (allPhones.length > 1) {
|
|
// If there are multiple active SIMs, check all instances:
|
|
boolean found = false;
|
|
for (Phone phone : allPhones) {
|
|
// If the current iteration was already checked, skip:
|
|
if (phone.getPhoneId() == currentPhone.getPhoneId()){
|
|
continue;
|
|
}
|
|
num = phone.getEmergencyNumberTracker()
|
|
.getEmergencyNumber(mAddress);
|
|
if (num != null){
|
|
found = true;
|
|
mIsEmergencyCall = true;
|
|
mEmergencyNumberInfo = num;
|
|
break;
|
|
}
|
|
}
|
|
if (!found){
|
|
Rlog.e(TAG, "setEmergencyCallInfo: emergency number is null");
|
|
}
|
|
} else {
|
|
Rlog.e(TAG, "setEmergencyCallInfo: emergency number is null");
|
|
}
|
|
} else {
|
|
Rlog.e(TAG, "setEmergencyCallInfo: emergency number tracker is null");
|
|
}
|
|
} else {
|
|
Rlog.e(TAG, "setEmergencyCallInfo: phone is null");
|
|
}
|
|
} else {
|
|
Rlog.e(TAG, "setEmergencyCallInfo: call tracker is null");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the non-detectable emergency number information.
|
|
*/
|
|
public void setNonDetectableEmergencyCallInfo(int eccCategory) {
|
|
if (!mIsEmergencyCall) {
|
|
mIsEmergencyCall = true;
|
|
mEmergencyNumberInfo = new EmergencyNumber(mAddress, ""/*countryIso*/,
|
|
""/*mnc*/, eccCategory,
|
|
new ArrayList<String>(),
|
|
EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
|
|
EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set if we have known the user's intent for the call is emergency.
|
|
*
|
|
* This is only used to specify when the dialed number is ambiguous, identified as both
|
|
* emergency number and any other non-emergency number; e.g. in some situation, 611 could
|
|
* be both an emergency number in a country and a non-emergency number of a carrier's
|
|
* customer service hotline.
|
|
*
|
|
* @hide
|
|
*/
|
|
public void setHasKnownUserIntentEmergency(boolean hasKnownUserIntentEmergency) {
|
|
mHasKnownUserIntentEmergency = hasKnownUserIntentEmergency;
|
|
}
|
|
|
|
/**
|
|
* If this Connection is connected, then it is associated with
|
|
* a Call.
|
|
*
|
|
* Returns getCall().getState() or Call.State.IDLE if not
|
|
* connected
|
|
*/
|
|
@UnsupportedAppUsage
|
|
public Call.State getState() {
|
|
Call c;
|
|
|
|
c = getCall();
|
|
|
|
if (c == null) {
|
|
return Call.State.IDLE;
|
|
} else {
|
|
return c.getState();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* If this connection went through handover return the state of the
|
|
* call that contained this connection before handover.
|
|
*/
|
|
public Call.State getStateBeforeHandover() {
|
|
return mPreHandoverState;
|
|
}
|
|
|
|
/**
|
|
* Get the details of conference participants. Expected to be
|
|
* overwritten by the Connection subclasses.
|
|
*/
|
|
public List<ConferenceParticipant> getConferenceParticipants() {
|
|
Call c;
|
|
|
|
c = getCall();
|
|
|
|
if (c == null) {
|
|
return null;
|
|
} else {
|
|
return c.getConferenceParticipants();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* isAlive()
|
|
*
|
|
* @return true if the connection isn't disconnected
|
|
* (could be active, holding, ringing, dialing, etc)
|
|
*/
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
public boolean
|
|
isAlive() {
|
|
return getState().isAlive();
|
|
}
|
|
|
|
/**
|
|
* Returns true if Connection is connected and is INCOMING or WAITING
|
|
*/
|
|
public boolean
|
|
isRinging() {
|
|
return getState().isRinging();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return the userdata set in setUserData()
|
|
*/
|
|
@UnsupportedAppUsage
|
|
public Object getUserData() {
|
|
return mUserData;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param userdata user can store an any userdata in the Connection object.
|
|
*/
|
|
public void setUserData(Object userdata) {
|
|
mUserData = userdata;
|
|
}
|
|
|
|
/**
|
|
* Deflect individual Connection
|
|
*/
|
|
public abstract void deflect(String number) throws CallStateException;
|
|
|
|
/**
|
|
* Transfer individual Connection
|
|
*/
|
|
public abstract void transfer(String number, boolean isConfirmationRequired)
|
|
throws CallStateException;
|
|
|
|
/**
|
|
* Transfer individual Connection for consultative transfer
|
|
*/
|
|
public abstract void consultativeTransfer(Connection other) throws CallStateException;
|
|
|
|
/**
|
|
* Hangup individual Connection
|
|
*/
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
public abstract void hangup() throws CallStateException;
|
|
|
|
/**
|
|
* Separate this call from its owner Call and assigns it to a new Call
|
|
* (eg if it is currently part of a Conference call
|
|
* TODO: Throw exception? Does GSM require error display on failure here?
|
|
*/
|
|
public abstract void separate() throws CallStateException;
|
|
|
|
public enum PostDialState {
|
|
@UnsupportedAppUsage
|
|
NOT_STARTED, /* The post dial string playback hasn't
|
|
been started, or this call is not yet
|
|
connected, or this is an incoming call */
|
|
@UnsupportedAppUsage
|
|
STARTED, /* The post dial string playback has begun */
|
|
@UnsupportedAppUsage
|
|
WAIT, /* The post dial string playback is waiting for a
|
|
call to proceedAfterWaitChar() */
|
|
@UnsupportedAppUsage
|
|
WILD, /* The post dial string playback is waiting for a
|
|
call to proceedAfterWildChar() */
|
|
@UnsupportedAppUsage
|
|
COMPLETE, /* The post dial string playback is complete */
|
|
@UnsupportedAppUsage
|
|
CANCELLED, /* The post dial string playback was cancelled
|
|
with cancelPostDial() */
|
|
PAUSE /* The post dial string playback is pausing for a
|
|
call to processNextPostDialChar*/
|
|
}
|
|
|
|
public void clearUserData(){
|
|
mUserData = null;
|
|
}
|
|
|
|
public void addPostDialListener(PostDialListener listener) {
|
|
if (!mPostDialListeners.contains(listener)) {
|
|
mPostDialListeners.add(listener);
|
|
}
|
|
}
|
|
|
|
public final void removePostDialListener(PostDialListener listener) {
|
|
mPostDialListeners.remove(listener);
|
|
}
|
|
|
|
protected final void clearPostDialListeners() {
|
|
if (mPostDialListeners != null) {
|
|
mPostDialListeners.clear();
|
|
}
|
|
}
|
|
|
|
protected final void notifyPostDialListeners() {
|
|
if (getPostDialState() == PostDialState.WAIT) {
|
|
for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) {
|
|
listener.onPostDialWait();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected final void notifyPostDialListenersNextChar(char c) {
|
|
for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) {
|
|
listener.onPostDialChar(c);
|
|
}
|
|
}
|
|
|
|
public PostDialState getPostDialState() {
|
|
return mPostDialState;
|
|
}
|
|
|
|
/**
|
|
* Returns the portion of the post dial string that has not
|
|
* yet been dialed, or "" if none
|
|
*/
|
|
public String getRemainingPostDialString() {
|
|
if (mPostDialState == PostDialState.CANCELLED
|
|
|| mPostDialState == PostDialState.COMPLETE
|
|
|| mPostDialString == null
|
|
|| mPostDialString.length() <= mNextPostDialChar) {
|
|
return "";
|
|
}
|
|
|
|
return mPostDialString.substring(mNextPostDialChar);
|
|
}
|
|
|
|
/**
|
|
* See Phone.setOnPostDialWaitCharacter()
|
|
*/
|
|
|
|
public abstract void proceedAfterWaitChar();
|
|
|
|
/**
|
|
* See Phone.setOnPostDialWildCharacter()
|
|
*/
|
|
public abstract void proceedAfterWildChar(String str);
|
|
/**
|
|
* Cancel any post
|
|
*/
|
|
public abstract void cancelPostDial();
|
|
|
|
/** Called when the connection has been disconnected */
|
|
public boolean onDisconnect(int cause) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns the caller id presentation type for incoming and waiting calls
|
|
* @return one of PRESENTATION_*
|
|
*/
|
|
public abstract int getNumberPresentation();
|
|
|
|
/**
|
|
* Returns the User to User Signaling (UUS) information associated with
|
|
* incoming and waiting calls
|
|
* @return UUSInfo containing the UUS userdata.
|
|
*/
|
|
public abstract UUSInfo getUUSInfo();
|
|
|
|
/**
|
|
* Returns the CallFail reason provided by the RIL with the result of
|
|
* RIL_REQUEST_LAST_CALL_FAIL_CAUSE
|
|
*/
|
|
public abstract int getPreciseDisconnectCause();
|
|
|
|
/**
|
|
* Returns the original Connection instance associated with
|
|
* this Connection
|
|
*/
|
|
public Connection getOrigConnection() {
|
|
return mOrigConnection;
|
|
}
|
|
|
|
/**
|
|
* Returns whether the original ImsPhoneConnection was a member
|
|
* of a conference call
|
|
* @return valid only when getOrigConnection() is not null
|
|
*/
|
|
public abstract boolean isMultiparty();
|
|
|
|
/**
|
|
* Applicable only for IMS Call. Determines if this call is the origin of the conference call
|
|
* (i.e. {@code #isConferenceHost()} is {@code true}), or if it is a member of a conference
|
|
* hosted on another device.
|
|
*
|
|
* @return {@code true} if this call is the origin of the conference call it is a member of,
|
|
* {@code false} otherwise.
|
|
*/
|
|
public boolean isConferenceHost() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Applicable only for IMS Call. Determines if a connection is a member of a conference hosted
|
|
* on another device.
|
|
*
|
|
* @return {@code true} if the connection is a member of a conference hosted on another device.
|
|
*/
|
|
public boolean isMemberOfPeerConference() {
|
|
return false;
|
|
}
|
|
|
|
public void migrateFrom(Connection c) {
|
|
if (c == null) return;
|
|
mListeners = c.mListeners;
|
|
mDialString = c.getOrigDialString();
|
|
mCreateTime = c.getCreateTime();
|
|
mConnectTime = c.getConnectTime();
|
|
mConnectTimeReal = c.getConnectTimeReal();
|
|
mHoldingStartTime = c.getHoldingStartTime();
|
|
mOrigConnection = c.getOrigConnection();
|
|
mPostDialString = c.mPostDialString;
|
|
mNextPostDialChar = c.mNextPostDialChar;
|
|
mPostDialState = c.mPostDialState;
|
|
|
|
// Migrate Emergency call parameters
|
|
mIsEmergencyCall = c.isEmergencyCall();
|
|
mEmergencyNumberInfo = c.getEmergencyNumberInfo();
|
|
mHasKnownUserIntentEmergency = c.hasKnownUserIntentEmergency();
|
|
}
|
|
|
|
/**
|
|
* Assign a listener to be notified of state changes.
|
|
*
|
|
* @param listener A listener.
|
|
*/
|
|
public void addListener(Listener listener) {
|
|
mListeners.add(listener);
|
|
}
|
|
|
|
/**
|
|
* Removes a listener.
|
|
*
|
|
* @param listener A listener.
|
|
*/
|
|
public final void removeListener(Listener listener) {
|
|
mListeners.remove(listener);
|
|
}
|
|
|
|
/**
|
|
* Returns the current video state of the connection.
|
|
*
|
|
* @return The video state of the connection.
|
|
*/
|
|
public int getVideoState() {
|
|
return mVideoState;
|
|
}
|
|
|
|
/**
|
|
* Called to get Connection capabilities.Returns Capabilities bitmask.
|
|
* @See Connection.Capability.
|
|
*/
|
|
public int getConnectionCapabilities() {
|
|
return mConnectionCapabilities;
|
|
}
|
|
|
|
/**
|
|
* @return {@code} true if the connection has the specified capabilities.
|
|
*/
|
|
public boolean hasCapabilities(int connectionCapabilities) {
|
|
return (mConnectionCapabilities & connectionCapabilities) == connectionCapabilities;
|
|
}
|
|
|
|
/**
|
|
* Applies a capability to a capabilities bit-mask.
|
|
*
|
|
* @param capabilities The capabilities bit-mask.
|
|
* @param capability The capability to apply.
|
|
* @return The capabilities bit-mask with the capability applied.
|
|
*/
|
|
public static int addCapability(int capabilities, int capability) {
|
|
return capabilities | capability;
|
|
}
|
|
|
|
/**
|
|
* Removes a capability to a capabilities bit-mask.
|
|
*
|
|
* @param capabilities The capabilities bit-mask.
|
|
* @param capability The capability to remove.
|
|
* @return The capabilities bit-mask with the capability removed.
|
|
*/
|
|
public static int removeCapability(int capabilities, int capability) {
|
|
return capabilities & ~capability;
|
|
}
|
|
|
|
/**
|
|
* Returns whether the connection is using a wifi network.
|
|
*
|
|
* @return {@code True} if the connection is using a wifi network.
|
|
*/
|
|
public boolean isWifi() {
|
|
return getCallRadioTech() == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
|
|
}
|
|
|
|
/**
|
|
* Returns radio technology is used for the connection.
|
|
*
|
|
* @return the RIL Voice Radio Technology used for current connection,
|
|
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
|
|
*/
|
|
public @RilRadioTechnology int getCallRadioTech() {
|
|
return mCallRadioTech;
|
|
}
|
|
|
|
/**
|
|
* Returns whether the connection uses voip audio mode
|
|
*
|
|
* @return {@code True} if the connection uses voip audio mode
|
|
*/
|
|
public boolean getAudioModeIsVoip() {
|
|
return mAudioModeIsVoip;
|
|
}
|
|
|
|
/**
|
|
* Returns the {@link android.telecom.Connection.VideoProvider} for the connection.
|
|
*
|
|
* @return The {@link android.telecom.Connection.VideoProvider}.
|
|
*/
|
|
public android.telecom.Connection.VideoProvider getVideoProvider() {
|
|
return mVideoProvider;
|
|
}
|
|
|
|
/**
|
|
* Returns the audio-quality for the connection.
|
|
*
|
|
* @return The audio quality for the connection.
|
|
*/
|
|
public int getAudioQuality() {
|
|
return mAudioQuality;
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns the current call substate of the connection.
|
|
*
|
|
* @return The call substate of the connection.
|
|
*/
|
|
public int getCallSubstate() {
|
|
return mCallSubstate;
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets the videoState for the current connection and reports the changes to all listeners.
|
|
* Valid video states are defined in {@link android.telecom.VideoProfile}.
|
|
*
|
|
* @return The video state.
|
|
*/
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
public void setVideoState(int videoState) {
|
|
mVideoState = videoState;
|
|
for (Listener l : mListeners) {
|
|
l.onVideoStateChanged(mVideoState);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called to set Connection capabilities. This will take Capabilities bitmask as input which is
|
|
* converted from Capabilities constants.
|
|
*
|
|
* @See Connection.Capability.
|
|
* @param capabilities The Capabilities bitmask.
|
|
*/
|
|
public void setConnectionCapabilities(int capabilities) {
|
|
if (mConnectionCapabilities != capabilities) {
|
|
mConnectionCapabilities = capabilities;
|
|
for (Listener l : mListeners) {
|
|
l.onConnectionCapabilitiesChanged(mConnectionCapabilities);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets RIL voice radio technology used for current connection.
|
|
*
|
|
* @param vrat the RIL voice radio technology for current connection,
|
|
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
|
|
*/
|
|
public void setCallRadioTech(@RilRadioTechnology int vrat) {
|
|
if (mCallRadioTech == vrat) {
|
|
return;
|
|
}
|
|
mCallRadioTech = vrat;
|
|
for (Listener l : mListeners) {
|
|
l.onCallRadioTechChanged(vrat);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the voip audio mode for the connection
|
|
*
|
|
* @param isVoip {@code True} if voip audio mode is being used.
|
|
*/
|
|
public void setAudioModeIsVoip(boolean isVoip) {
|
|
mAudioModeIsVoip = isVoip;
|
|
}
|
|
|
|
/**
|
|
* Set the audio quality for the connection.
|
|
*
|
|
* @param audioQuality The audio quality.
|
|
*/
|
|
public void setAudioQuality(int audioQuality) {
|
|
mAudioQuality = audioQuality;
|
|
for (Listener l : mListeners) {
|
|
l.onAudioQualityChanged(mAudioQuality);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notifies interested parties of changes to the media attributes of the call.
|
|
*/
|
|
public void notifyMediaAttributesChanged() {
|
|
for (Listener l: mListeners) {
|
|
l.onMediaAttributesChanged();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notifies listeners that connection extras has changed.
|
|
* @param extras New connection extras. This Bundle will be cloned to ensure that any concurrent
|
|
* modifications to the extras Bundle do not affect Bundle operations in the onExtrasChanged
|
|
* listeners.
|
|
*/
|
|
public void setConnectionExtras(Bundle extras) {
|
|
if (extras != null) {
|
|
mExtras = new Bundle(extras);
|
|
|
|
int previousCount = mExtras.size();
|
|
// Prevent vendors from passing in extras other than primitive types and android API
|
|
// parcelables.
|
|
mExtras = TelephonyUtils.filterValues(mExtras);
|
|
int filteredCount = mExtras.size();
|
|
if (filteredCount != previousCount) {
|
|
Rlog.i(TAG, "setConnectionExtras: filtering " + (previousCount - filteredCount)
|
|
+ " invalid extras.");
|
|
}
|
|
} else {
|
|
mExtras = null;
|
|
}
|
|
|
|
for (Listener l : mListeners) {
|
|
l.onExtrasChanged(mExtras);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieves the current connection extras.
|
|
* @return the connection extras.
|
|
*/
|
|
public Bundle getConnectionExtras() {
|
|
return mExtras == null ? null : new Bundle(mExtras);
|
|
}
|
|
|
|
/**
|
|
* @return {@code true} if answering the call will cause the current active call to be
|
|
* disconnected, {@code false} otherwise.
|
|
*/
|
|
public boolean isActiveCallDisconnectedOnAnswer() {
|
|
return mAnsweringDisconnectsActiveCall;
|
|
}
|
|
|
|
/**
|
|
* Sets whether answering this call will cause the active call to be disconnected.
|
|
* <p>
|
|
* Should only be set {@code true} if there is an active call and this call is ringing.
|
|
*
|
|
* @param answeringDisconnectsActiveCall {@code true} if answering the call will call the active
|
|
* call to be disconnected.
|
|
*/
|
|
public void setActiveCallDisconnectedOnAnswer(boolean answeringDisconnectsActiveCall) {
|
|
mAnsweringDisconnectsActiveCall = answeringDisconnectsActiveCall;
|
|
}
|
|
|
|
public boolean shouldAllowAddCallDuringVideoCall() {
|
|
return mAllowAddCallDuringVideoCall;
|
|
}
|
|
|
|
public void setAllowAddCallDuringVideoCall(boolean allowAddCallDuringVideoCall) {
|
|
mAllowAddCallDuringVideoCall = allowAddCallDuringVideoCall;
|
|
}
|
|
|
|
public boolean shouldAllowHoldingVideoCall() {
|
|
return mAllowHoldingVideoCall;
|
|
}
|
|
|
|
public void setAllowHoldingVideoCall(boolean allowHoldingVideoCall) {
|
|
mAllowHoldingVideoCall = allowHoldingVideoCall;
|
|
}
|
|
|
|
/**
|
|
* Sets whether the connection is the result of an external call which was pulled to the local
|
|
* device.
|
|
*
|
|
* @param isPulledCall {@code true} if this connection is the result of pulling an external call
|
|
* to the local device.
|
|
*/
|
|
public void setIsPulledCall(boolean isPulledCall) {
|
|
mIsPulledCall = isPulledCall;
|
|
}
|
|
|
|
public boolean isPulledCall() {
|
|
return mIsPulledCall;
|
|
}
|
|
|
|
/**
|
|
* For an external call which is being pulled (e.g. {@link #isPulledCall()} is {@code true}),
|
|
* sets the dialog Id for the external call. Used to handle failures to pull a call so that the
|
|
* pulled call can be reconciled with its original external connection.
|
|
*
|
|
* @param pulledDialogId The dialog id associated with a pulled call.
|
|
*/
|
|
public void setPulledDialogId(int pulledDialogId) {
|
|
mPulledDialogId = pulledDialogId;
|
|
}
|
|
|
|
public int getPulledDialogId() {
|
|
return mPulledDialogId;
|
|
}
|
|
|
|
/**
|
|
* Sets the call substate for the current connection and reports the changes to all listeners.
|
|
* Valid call substates are defined in {@link android.telecom.Connection}.
|
|
*
|
|
* @return The call substate.
|
|
*/
|
|
public void setCallSubstate(int callSubstate) {
|
|
mCallSubstate = callSubstate;
|
|
for (Listener l : mListeners) {
|
|
l.onCallSubstateChanged(mCallSubstate);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the {@link android.telecom.Connection.VideoProvider} for the connection.
|
|
*
|
|
* @param videoProvider The video call provider.
|
|
*/
|
|
public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) {
|
|
mVideoProvider = videoProvider;
|
|
for (Listener l : mListeners) {
|
|
l.onVideoProviderChanged(mVideoProvider);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@link CallTracker#convertNumberIfNecessary(Phone, String)} can be used to convert a dialed
|
|
* number to another number based on carrier config. This is used where a carrier wishes to
|
|
* redirect certain short codes such as *55 to another number (e.g. a 1-800 service number).
|
|
* The {@link CallTracker} sub-classes call
|
|
* {@link CallTracker#convertNumberIfNecessary(Phone, String)} to retrieve the newly converted
|
|
* number and instantiate the {@link Connection} instance using the converted number so that the
|
|
* system will dial out the substitution number instead of the originally dialed one. This gem
|
|
* of a method is called after the dialing process to restore the originally dialed number and
|
|
* keep track of the fact that a converted number was used to place the call.
|
|
* @param oriNumber The original number prior to conversion.
|
|
*/
|
|
public void restoreDialedNumberAfterConversion(String oriNumber) {
|
|
mNumberConverted = true;
|
|
mConvertedNumber = mAddress;
|
|
mAddress = oriNumber;
|
|
mDialString = oriNumber;
|
|
}
|
|
|
|
/**
|
|
* Changes the address and presentation for this call.
|
|
* @param newAddress The new address.
|
|
* @param numberPresentation The number presentation for the address.
|
|
*/
|
|
public void setAddress(String newAddress, int numberPresentation) {
|
|
Rlog.i(TAG, "setAddress = " + newAddress);
|
|
mAddress = newAddress;
|
|
mNumberPresentation = numberPresentation;
|
|
}
|
|
|
|
public void setDialString(String newDialString) {
|
|
mDialString = newDialString;
|
|
}
|
|
|
|
/**
|
|
* Notifies listeners of a change to conference participant(s).
|
|
*
|
|
* @param conferenceParticipants The participant(s).
|
|
*/
|
|
public void updateConferenceParticipants(List<ConferenceParticipant> conferenceParticipants) {
|
|
for (Listener l : mListeners) {
|
|
l.onConferenceParticipantsChanged(conferenceParticipants);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notifies listeners of a change to the multiparty state of the connection.
|
|
*
|
|
* @param isMultiparty The participant(s).
|
|
*/
|
|
public void updateMultipartyState(boolean isMultiparty) {
|
|
for (Listener l : mListeners) {
|
|
l.onMultipartyStateChanged(isMultiparty);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notifies listeners of a failure in merging this connection with the background connection.
|
|
*/
|
|
public void onConferenceMergeFailed() {
|
|
for (Listener l : mListeners) {
|
|
l.onConferenceMergedFailed();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notifies that the underlying phone has exited ECM mode.
|
|
*/
|
|
public void onExitedEcmMode() {
|
|
for (Listener l : mListeners) {
|
|
l.onExitedEcmMode();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notifies the connection that a call to {@link #pullExternalCall()} has failed to pull the
|
|
* call to the local device.
|
|
*
|
|
* @param externalConnection The original
|
|
* {@link com.android.internal.telephony.imsphone.ImsExternalConnection} from which the
|
|
* pull was initiated.
|
|
*/
|
|
public void onCallPullFailed(Connection externalConnection) {
|
|
for (Listener l : mListeners) {
|
|
l.onCallPullFailed(externalConnection);
|
|
}
|
|
}
|
|
|
|
public void onOriginalConnectionReplaced(Connection newConnection) {
|
|
for (Listener l : mListeners) {
|
|
l.onOriginalConnectionReplaced(newConnection);
|
|
}
|
|
}
|
|
/**
|
|
* Notifies the connection that there was a failure while handing over to WIFI.
|
|
*/
|
|
public void onHandoverToWifiFailed() {
|
|
for (Listener l : mListeners) {
|
|
l.onHandoverToWifiFailed();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notifies the connection of a connection event.
|
|
*/
|
|
public void onConnectionEvent(String event, Bundle extras) {
|
|
for (Listener l : mListeners) {
|
|
l.onConnectionEvent(event, extras);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notifies this Connection of a request to disconnect a participant of the conference managed
|
|
* by the connection.
|
|
*
|
|
* @param endpoint the {@link Uri} of the participant to disconnect.
|
|
*/
|
|
public void onDisconnectConferenceParticipant(Uri endpoint) {
|
|
}
|
|
|
|
/**
|
|
* Called by a {@link android.telecom.Connection} to indicate that this call should be pulled
|
|
* to the local device.
|
|
*/
|
|
public void pullExternalCall() {
|
|
}
|
|
|
|
public void onRttModifyRequestReceived() {
|
|
for (Listener l : mListeners) {
|
|
l.onRttModifyRequestReceived();
|
|
}
|
|
}
|
|
|
|
public void onRttModifyResponseReceived(int status) {
|
|
for (Listener l : mListeners) {
|
|
l.onRttModifyResponseReceived(status);
|
|
}
|
|
}
|
|
|
|
public void onRttInitiated() {
|
|
for (Listener l : mListeners) {
|
|
l.onRttInitiated();
|
|
}
|
|
}
|
|
|
|
public void onRttTerminated() {
|
|
for (Listener l : mListeners) {
|
|
l.onRttTerminated();
|
|
}
|
|
}
|
|
/**
|
|
* Notify interested parties that this connection disconnected.
|
|
* {@code TelephonyConnection}, for example, uses this.
|
|
* @param reason the disconnect code, per {@link DisconnectCause}.
|
|
*/
|
|
protected void notifyDisconnect(int reason) {
|
|
Rlog.i(TAG, "notifyDisconnect: callId=" + getTelecomCallId() + ", reason=" + reason);
|
|
for (Listener l : mListeners) {
|
|
l.onDisconnect(reason);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
public int getPhoneType() {
|
|
return mPhoneType;
|
|
}
|
|
|
|
/**
|
|
* Reset the Connection time and Duration
|
|
*/
|
|
public void resetConnectionTime() {
|
|
if (mPhoneType == PhoneConstants.PHONE_TYPE_CDMA_LTE ||
|
|
mPhoneType == PhoneConstants.PHONE_TYPE_CDMA) {
|
|
mConnectTime = System.currentTimeMillis();
|
|
mConnectTimeReal = SystemClock.elapsedRealtime();
|
|
mDuration = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets whether this {@link Connection} has been identified by the network as an emergency call.
|
|
* @param isNetworkIdentifiedEmergencyCall {@code true} if ecall, {@code false} otherwise.
|
|
*/
|
|
public void setIsNetworkIdentifiedEmergencyCall(boolean isNetworkIdentifiedEmergencyCall) {
|
|
mIsNetworkIdentifiedEmergencyCall = isNetworkIdentifiedEmergencyCall;
|
|
for (Listener l : mListeners) {
|
|
l.onIsNetworkEmergencyCallChanged(isNetworkIdentifiedEmergencyCall);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return Whether this {@link Connection} has been identified by the network as an emergency
|
|
* call.
|
|
*/
|
|
public boolean isNetworkIdentifiedEmergencyCall() {
|
|
return mIsNetworkIdentifiedEmergencyCall;
|
|
}
|
|
|
|
/**
|
|
* Build a human representation of a connection instance, suitable for debugging.
|
|
* Don't log personal stuff unless in debug mode.
|
|
* @return a string representing the internal state of this connection.
|
|
*/
|
|
public String toString() {
|
|
StringBuilder str = new StringBuilder(128);
|
|
|
|
str.append(" callId: " + getTelecomCallId());
|
|
str.append(" objId: " + System.identityHashCode(this));
|
|
str.append(" isExternal: " + (((mConnectionCapabilities & Capability.IS_EXTERNAL_CONNECTION)
|
|
== Capability.IS_EXTERNAL_CONNECTION) ? "Y" : "N"));
|
|
if (Rlog.isLoggable(LOG_TAG, Log.DEBUG)) {
|
|
str.append("addr: " + getAddress())
|
|
.append(" pres.: " + getNumberPresentation())
|
|
.append(" dial: " + getOrigDialString())
|
|
.append(" postdial: " + getRemainingPostDialString())
|
|
.append(" cnap name: " + getCnapName())
|
|
.append("(" + getCnapNamePresentation() + ")");
|
|
}
|
|
str.append(" incoming: " + isIncoming())
|
|
.append(" state: " + getState())
|
|
.append(" post dial state: " + getPostDialState());
|
|
return str.toString();
|
|
}
|
|
|
|
/**
|
|
* Get current audio codec.
|
|
* @return current audio codec.
|
|
*/
|
|
public int getAudioCodec() {
|
|
return mAudioCodec;
|
|
}
|
|
|
|
/**
|
|
* @return the audio codec bitrate in kbps.
|
|
*/
|
|
public float getAudioCodecBitrateKbps() {
|
|
return mAudioCodecBitrateKbps;
|
|
}
|
|
|
|
/**
|
|
* @return the audio codec bandwidth in kHz.
|
|
*/
|
|
public float getAudioCodecBandwidthKhz() {
|
|
return mAudioCodecBandwidthKhz;
|
|
}
|
|
|
|
/**
|
|
* @return The number verification status; only applicable for IMS calls.
|
|
*/
|
|
public @android.telecom.Connection.VerificationStatus int getNumberVerificationStatus() {
|
|
return mNumberVerificationStatus;
|
|
}
|
|
|
|
/**
|
|
* Sets the number verification status.
|
|
* @param verificationStatus The new verification status
|
|
*/
|
|
public void setNumberVerificationStatus(
|
|
@android.telecom.Connection.VerificationStatus int verificationStatus) {
|
|
mNumberVerificationStatus = verificationStatus;
|
|
}
|
|
|
|
/**
|
|
* Called to report a DTMF digit received from the network.
|
|
* @param digit the received digit.
|
|
*/
|
|
public void receivedDtmfDigit(char digit) {
|
|
for (Listener l : mListeners) {
|
|
l.onReceivedDtmfDigit(digit);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called to report audio mode changed for Voip.
|
|
* @param imsAudioHandler the received value to handle the audio for this IMS call.
|
|
*/
|
|
public void onAudioModeIsVoipChanged(@ImsAudioHandler int imsAudioHandler) {
|
|
Rlog.i(TAG, "onAudioModeIsVoipChanged: conn imsAudioHandler " + imsAudioHandler);
|
|
|
|
boolean isVoip = imsAudioHandler == MmTelFeature.AUDIO_HANDLER_ANDROID;
|
|
if (isVoip == mAudioModeIsVoip) return;
|
|
mAudioModeIsVoip = isVoip;
|
|
|
|
Rlog.i(TAG, "onAudioModeIsVoipChanged: isVoip: " + isVoip
|
|
+ "mAudioModeIsVoip:" + mAudioModeIsVoip);
|
|
|
|
for (Listener l : mListeners) {
|
|
l.onAudioModeIsVoipChanged(imsAudioHandler);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called to report RTP header extensions received from the network.
|
|
* @param extensionData the received extension data.
|
|
*/
|
|
public void receivedRtpHeaderExtensions(@NonNull Set<RtpHeaderExtension> extensionData) {
|
|
for (Listener l : mListeners) {
|
|
l.onReceivedRtpHeaderExtensions(extensionData);
|
|
}
|
|
}
|
|
}
|