blob: aaa68d6f7d57fd4fd0eef09803c7d435472baba6 [file] [log] [blame]
/*
* Copyright (C) 2018 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 android.telephony.ims;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.telecom.VideoProfile;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.emergency.EmergencyNumber.EmergencyCallRouting;
import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
import android.telephony.ims.feature.MmTelFeature;
import android.util.ArraySet;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.util.TelephonyUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* A Parcelable object to handle the IMS call profile, which provides the service, call type, and
* additional information related to the call.
* <p>
* See the following specifications for more information about this class: GSMA IR.92/IR.94,
* 3GPP TS 24.229/TS 26.114/TS26.111.
* @hide
*/
@SystemApi
public final class ImsCallProfile implements Parcelable {
private static final String TAG = "ImsCallProfile";
/**
* Service types
*/
/**
* It is for a special case. It helps that the application can make a call
* without IMS connection (not registered).
* In the moment of the call initiation, the device try to connect to the IMS network
* and initiates the call.
*/
public static final int SERVICE_TYPE_NONE = 0;
/**
* It is a default type and can be selected when the device is connected to the IMS network.
*/
public static final int SERVICE_TYPE_NORMAL = 1;
/**
* It is for an emergency call.
*/
public static final int SERVICE_TYPE_EMERGENCY = 2;
/**
* Call types
*/
/**
* IMSPhone to support IR.92 & IR.94 (voice + video upgrade/downgrade)
*/
public static final int CALL_TYPE_VOICE_N_VIDEO = 1;
/**
* IR.92 (Voice only)
*/
public static final int CALL_TYPE_VOICE = 2;
/**
* VT to support IR.92 & IR.94 (voice + video upgrade/downgrade)
*/
public static final int CALL_TYPE_VIDEO_N_VOICE = 3;
/**
* Video Telephony (audio / video two way)
*/
public static final int CALL_TYPE_VT = 4;
/**
* Video Telephony (audio two way / video TX one way)
*/
public static final int CALL_TYPE_VT_TX = 5;
/**
* Video Telephony (audio two way / video RX one way)
*/
public static final int CALL_TYPE_VT_RX = 6;
/**
* Video Telephony (audio two way / video inactive)
*/
public static final int CALL_TYPE_VT_NODIR = 7;
/**
* VideoShare (video two way)
*/
public static final int CALL_TYPE_VS = 8;
/**
* VideoShare (video TX one way)
*/
public static final int CALL_TYPE_VS_TX = 9;
/**
* VideoShare (video RX one way)
*/
public static final int CALL_TYPE_VS_RX = 10;
/**
* Extra properties for IMS call.
*/
/**
* Boolean extra properties - "true" / "false"
* conference : Indicates if the session is for the conference call or not.
* e_call : Indicates if the session is for the emergency call or not.
* vms : Indicates if the session is connected to the voice mail system or not.
* call_mode_changeable : Indicates if the session is able to upgrade/downgrade
* the video during voice call.
* conference_avail : Indicates if the session can be extended to the conference.
*/
/**
* @hide
*/
public static final String EXTRA_CONFERENCE = "conference";
/**
* Boolean extra property set on an {@link ImsCallProfile} to indicate that this call is an
* emergency call. The {@link ImsService} sets this on a call to indicate that the network has
* identified the call as an emergency call.
*/
public static final String EXTRA_EMERGENCY_CALL = "e_call";
/**
* @hide
*/
public static final String EXTRA_VMS = "vms";
/**
* @hide
*/
public static final String EXTRA_CALL_MODE_CHANGEABLE = "call_mode_changeable";
/**
* @hide
*/
public static final String EXTRA_CONFERENCE_AVAIL = "conference_avail";
/**
* Extra key used to store a Bundle containing proprietary extras to send to the ImsService.
* Use {@link #getProprietaryCallExtras()} instead.
* @hide
*/
@TestApi
public static final String EXTRA_OEM_EXTRAS = "android.telephony.ims.extra.OEM_EXTRAS";
/**
* Rule for originating identity (number) presentation, MO/MT.
* {@link ImsCallProfile#OIR_DEFAULT}
* {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
* {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
*/
public static final String EXTRA_OIR = "oir";
/**
* Rule for calling name presentation
* {@link ImsCallProfile#OIR_DEFAULT}
* {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
* {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
*/
public static final String EXTRA_CNAP = "cnap";
/**
* To identify the Ims call type, MO
* {@link ImsCallProfile#DIALSTRING_NORMAL}
* {@link ImsCallProfile#DIALSTRING_SS_CONF}
* {@link ImsCallProfile#DIALSTRING_USSD}
*/
public static final String EXTRA_DIALSTRING = "dialstring";
/**
* This extra holds call fail cause because of which redial is attempted.
* see {@link android.telephony.ims.ImsReasonInfo} {@code CODE_*}
* for possible values this extra can hold.
*
* @hide
*/
public static final String EXTRA_RETRY_CALL_FAIL_REASON =
"android.telephony.ims.extra.RETRY_CALL_FAIL_REASON";
/**
* This extra holds call network type on which lower layers
* may try attempting redial.
* See {@link TelephonyManager} {@code NETWORK_TYPE_*}
* for possible values this extra can hold.
*
* @hide
*/
public static final String EXTRA_RETRY_CALL_FAIL_NETWORKTYPE =
"android.telephony.ims.extra.RETRY_CALL_FAIL_NETWORKTYPE";
/**
* Extra for the call composer call priority, either {@link ImsCallProfile#PRIORITY_NORMAL} or
* {@link ImsCallProfile#PRIORITY_URGENT}. It can be set via
* {@link #setCallExtraInt(String, int)}.
*
* Reference: RCC.20 Section 2.4.4.2
*/
public static final String EXTRA_PRIORITY = "android.telephony.ims.extra.PRIORITY";
// TODO(hallliu) remove the reference to the maximum length and update it later.
/**
* Extra for the call composer call subject, a string of maximum length 60 characters.
* It can be set via {@link #setCallExtra(String, String)}.
*
* Reference: RCC.20 Section 2.4.3.2
*/
public static final String EXTRA_CALL_SUBJECT = "android.telephony.ims.extra.CALL_SUBJECT";
/**
* Extra for the call composer call location, an {@Link android.location.Location} parcelable
* class to represent the geolocation as a latitude and longitude pair. It can be set via
* {@link #setCallExtraParcelable(String, Parcelable)}.
*
* Reference: RCC.20 Section 2.4.3.2
*/
public static final String EXTRA_LOCATION = "android.telephony.ims.extra.LOCATION";
/**
* Extra for the call composer picture URL, a String that indicates the URL on the carrier’s
* server infrastructure to get the picture. It can be set via
* {@link #setCallExtra(String, String)}.
*
* Reference: RCC.20 Section 2.4.3.2
*/
public static final String EXTRA_PICTURE_URL = "android.telephony.ims.extra.PICTURE_URL";
/**
* Values for EXTRA_OIR / EXTRA_CNAP
*/
/**
* Default presentation for Originating Identity.
*/
public static final int OIR_DEFAULT = 0; // "user subscription default value"
/**
* Restricted presentation for Originating Identity.
*/
public static final int OIR_PRESENTATION_RESTRICTED = 1;
/**
* Not restricted presentation for Originating Identity.
*/
public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2;
/**
* Presentation unknown for Originating Identity.
*/
public static final int OIR_PRESENTATION_UNKNOWN = 3;
/**
* Payphone presentation for Originating Identity.
*/
public static final int OIR_PRESENTATION_PAYPHONE = 4;
//Values for EXTRA_DIALSTRING
/**
* A default or normal normal call.
*/
public static final int DIALSTRING_NORMAL = 0;
/**
* Call for SIP-based user configuration
*/
public static final int DIALSTRING_SS_CONF = 1;
/**
* Call for USSD message
*/
public static final int DIALSTRING_USSD = 2;
// Values for EXTRA_PRIORITY
/**
* Indicates the call composer call priority is normal.
*
* Reference: RCC.20 Section 2.4.4.2
*/
public static final int PRIORITY_NORMAL = 0;
/**
* Indicates the call composer call priority is urgent.
*
* Reference: RCC.20 Section 2.4.4.2
*/
public static final int PRIORITY_URGENT = 1;
/**
* Call is not restricted on peer side and High Definition media is supported
*/
public static final int CALL_RESTRICT_CAUSE_NONE = 0;
/**
* High Definition media is not supported on the peer side due to the Radio Access Technology
* (RAT) it is are connected to.
*/
public static final int CALL_RESTRICT_CAUSE_RAT = 1;
/**
* The service has been disabled on the peer side.
*/
public static final int CALL_RESTRICT_CAUSE_DISABLED = 2;
/**
* High definition media is not currently supported.
*/
public static final int CALL_RESTRICT_CAUSE_HD = 3;
/**@hide*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "CALL_RESTRICT_CAUSE_", value = {
CALL_RESTRICT_CAUSE_NONE,
CALL_RESTRICT_CAUSE_RAT,
CALL_RESTRICT_CAUSE_DISABLED,
CALL_RESTRICT_CAUSE_HD
})
public @interface CallRestrictCause {}
/**
* String extra properties
* oi : Originating identity (number), MT only
* cna : Calling name
* ussd : For network-initiated USSD, MT only
* remote_uri : Connected user identity (it can be used for the conference)
* ChildNum: Child number info.
* Codec: Codec info.
* DisplayText: Display text for the call.
* AdditionalCallInfo: Additional call info.
* CallPull: Boolean value specifying if the call is a pulled call.
*/
public static final String EXTRA_OI = "oi";
public static final String EXTRA_CNA = "cna";
public static final String EXTRA_USSD = "ussd";
public static final String EXTRA_REMOTE_URI = "remote_uri";
public static final String EXTRA_CHILD_NUMBER = "ChildNum";
public static final String EXTRA_CODEC = "Codec";
public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
public static final String EXTRA_IS_CALL_PULL = "CallPull";
/**
* String extra property
* Containing fields from the SIP INVITE message for an IMS call
*/
public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS =
"android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS";
/**
* CallDisconnectCause: Specify call disconnect cause. This extra should be a code
* corresponding to ImsReasonInfo and should only be populated in the case that the
* call has already been missed
*/
public static final String EXTRA_CALL_DISCONNECT_CAUSE =
"android.telephony.ims.extra.CALL_DISCONNECT_CAUSE";
/**
* Extra key which the RIL can use to indicate the radio technology used for a call.
* Valid values are:
* {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE},
* {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_IWLAN}, and the other defined
* {@code RIL_RADIO_TECHNOLOGY_*} constants.
* Note: Despite the fact the {@link android.telephony.ServiceState} values are integer
* constants, the values passed for the {@link #EXTRA_CALL_RAT_TYPE} should be strings (e.g.
* "14" vs (int) 14).
* Note: This is used by {@link com.android.internal.telephony.imsphone.ImsPhoneConnection#
* updateImsCallRatFromExtras(Bundle)} to determine whether to set the
* {@link android.telecom.TelecomManager#EXTRA_CALL_NETWORK_TYPE} extra value and
* {@link android.telecom.Connection#PROPERTY_WIFI} property on a connection.
* @deprecated the constants associated with this extra are hidden, instead use
* {@link #EXTRA_CALL_NETWORK_TYPE}.
*/
@Deprecated
public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
/**
* Extra key with an {@code int} value which can be set in {@link #setCallExtraInt(String, int)}
* to indicate the network type used for a call.
* <p>
* Valid values are defined by {@code TelephonyManager.NETWORK_TYPE_*} constants. An example may
* be {@link android.telephony.TelephonyManager#NETWORK_TYPE_LTE}.
*/
public static final String EXTRA_CALL_NETWORK_TYPE =
"android.telephony.ims.extra.CALL_NETWORK_TYPE";
/**
* Similar to {@link #EXTRA_CALL_RAT_TYPE}, except with a lowercase 'c'. Used to ensure
* compatibility with modems that are non-compliant with the {@link #EXTRA_CALL_RAT_TYPE}
* extra key. Should be removed when the non-compliant modems are fixed.
* @hide
* @deprecated Use {@link #EXTRA_CALL_NETWORK_TYPE} instead.
*/
@Deprecated
public static final String EXTRA_CALL_RAT_TYPE_ALT = "callRadioTech";
/**
* String extra property containing forwarded numbers associated with the current connection
* for an IMS call. The value is string array, and it can include multiple numbers, and
* the array values are expected E164 (e.g. +1 (650) 253-0000) format.
*/
public static final String EXTRA_FORWARDED_NUMBER =
"android.telephony.ims.extra.FORWARDED_NUMBER";
/** @hide */
public int mServiceType;
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int mCallType;
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public @CallRestrictCause int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
/**
* The VERSTAT for an incoming call's phone number.
*/
private @VerificationStatus int mCallerNumberVerificationStatus;
/**
* Indicates that the network could not perform verification.
*/
public static final int VERIFICATION_STATUS_NOT_VERIFIED = 0;
/**
* Indicates that verification by the network passed. This indicates there is a high likelihood
* that the call originated from a valid source.
*/
public static final int VERIFICATION_STATUS_PASSED = 1;
/**
* Indicates that verification by the network failed. This indicates there is a high likelihood
* that the call did not originate from a valid source.
*/
public static final int VERIFICATION_STATUS_FAILED = 2;
/**@hide*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "VERIFICATION_STATUS_", value = {
VERIFICATION_STATUS_NOT_VERIFIED,
VERIFICATION_STATUS_PASSED,
VERIFICATION_STATUS_FAILED
})
public @interface VerificationStatus {}
/**
* The emergency service categories, only valid if {@link #getServiceType} returns
* {@link #SERVICE_TYPE_EMERGENCY}
*
* If valid, the value is the bitwise-OR combination of the following constants:
* <ol>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_POLICE} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AMBULANCE} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MIEC} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AIEC} </li>
* </ol>
*
* Reference: 3gpp 23.167, Section 6 - Functional description;
* 3gpp 22.101, Section 10 - Emergency Calls.
*/
private @EmergencyServiceCategories int mEmergencyServiceCategories =
EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
/**
* The emergency Uniform Resource Names (URN), only valid if {@link #getServiceType} returns
* {@link #SERVICE_TYPE_EMERGENCY}.
*
* Reference: 3gpp 24.503, Section 5.1.6.8.1 - General;
* 3gpp 22.101, Section 10 - Emergency Calls.
*/
private List<String> mEmergencyUrns = new ArrayList<>();
/**
* The emergency call routing, only valid if {@link #getServiceType} returns
* {@link #SERVICE_TYPE_EMERGENCY}
*
* If valid, the value is any of the following constants:
* <ol>
* <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_UNKNOWN} </li>
* <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_NORMAL} </li>
* <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_EMERGENCY} </li>
* </ol>
*/
private @EmergencyCallRouting int mEmergencyCallRouting =
EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
/** Indicates if the call is for testing purpose */
private boolean mEmergencyCallTesting = false;
/** Indicates if we have known the intent of the user for the call is emergency */
private boolean mHasKnownUserIntentEmergency = false;
private Set<RtpHeaderExtensionType> mAcceptedRtpHeaderExtensionTypes = new ArraySet<>();
/**
* Extras associated with this {@link ImsCallProfile}.
* <p>
* Valid data types include:
* <ul>
* <li>{@link Integer} (and int)</li>
* <li>{@link Long} (and long)</li>
* <li>{@link Double} (and double)</li>
* <li>{@link String}</li>
* <li>{@code int[]}</li>
* <li>{@code long[]}</li>
* <li>{@code double[]}</li>
* <li>{@code String[]}</li>
* <li>{@link android.os.PersistableBundle}</li>
* <li>{@link Boolean} (and boolean)</li>
* <li>{@code boolean[]}</li>
* <li>Other {@link Parcelable} classes in the {@code android.*} namespace.</li>
* </ul>
* <p>
* Invalid types will be removed when the {@link ImsCallProfile} is parceled for transmit across
* a {@link android.os.Binder}.
*/
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public Bundle mCallExtras;
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public ImsStreamMediaProfile mMediaProfile;
/** @hide */
public ImsCallProfile(Parcel in) {
readFromParcel(in);
}
/**
* Default Constructor that initializes the call profile with service type
* {@link #SERVICE_TYPE_NORMAL} and call type {@link #CALL_TYPE_VIDEO_N_VOICE}
*/
public ImsCallProfile() {
mServiceType = SERVICE_TYPE_NORMAL;
mCallType = CALL_TYPE_VOICE_N_VIDEO;
mCallExtras = new Bundle();
mMediaProfile = new ImsStreamMediaProfile();
}
/**
* Constructor.
*
* @param serviceType the service type for the call. Can be one of the following:
* {@link #SERVICE_TYPE_NONE},
* {@link #SERVICE_TYPE_NORMAL},
* {@link #SERVICE_TYPE_EMERGENCY}
* @param callType the call type. Can be one of the following:
* {@link #CALL_TYPE_VOICE_N_VIDEO},
* {@link #CALL_TYPE_VOICE},
* {@link #CALL_TYPE_VIDEO_N_VOICE},
* {@link #CALL_TYPE_VT},
* {@link #CALL_TYPE_VT_TX},
* {@link #CALL_TYPE_VT_RX},
* {@link #CALL_TYPE_VT_NODIR},
* {@link #CALL_TYPE_VS},
* {@link #CALL_TYPE_VS_TX},
* {@link #CALL_TYPE_VS_RX}
*/
public ImsCallProfile(int serviceType, int callType) {
mServiceType = serviceType;
mCallType = callType;
mCallExtras = new Bundle();
mMediaProfile = new ImsStreamMediaProfile();
}
/**
* Constructor.
*
* @param serviceType the service type for the call. Can be one of the following:
* {@link #SERVICE_TYPE_NONE},
* {@link #SERVICE_TYPE_NORMAL},
* {@link #SERVICE_TYPE_EMERGENCY}
* @param callType the call type. Can be one of the following:
* {@link #CALL_TYPE_VOICE_N_VIDEO},
* {@link #CALL_TYPE_VOICE},
* {@link #CALL_TYPE_VIDEO_N_VOICE},
* {@link #CALL_TYPE_VT},
* {@link #CALL_TYPE_VT_TX},
* {@link #CALL_TYPE_VT_RX},
* {@link #CALL_TYPE_VT_NODIR},
* {@link #CALL_TYPE_VS},
* {@link #CALL_TYPE_VS_TX},
* {@link #CALL_TYPE_VS_RX}
* @param callExtras A bundle with the call extras.
* @param mediaProfile The IMS stream media profile.
*/
public ImsCallProfile(int serviceType, int callType, Bundle callExtras,
ImsStreamMediaProfile mediaProfile) {
mServiceType = serviceType;
mCallType = callType;
mCallExtras = callExtras;
mMediaProfile = mediaProfile;
}
public String getCallExtra(String name) {
return getCallExtra(name, "");
}
public String getCallExtra(String name, String defaultValue) {
if (mCallExtras == null) {
return defaultValue;
}
return mCallExtras.getString(name, defaultValue);
}
public boolean getCallExtraBoolean(String name) {
return getCallExtraBoolean(name, false);
}
public boolean getCallExtraBoolean(String name, boolean defaultValue) {
if (mCallExtras == null) {
return defaultValue;
}
return mCallExtras.getBoolean(name, defaultValue);
}
public int getCallExtraInt(String name) {
return getCallExtraInt(name, -1);
}
public int getCallExtraInt(String name, int defaultValue) {
if (mCallExtras == null) {
return defaultValue;
}
return mCallExtras.getInt(name, defaultValue);
}
/**
* Get the call extras (Parcelable), given the extra name.
* @param name call extra name
* @return the corresponding call extra Parcelable or null if not applicable
*/
@Nullable
public <T extends Parcelable> T getCallExtraParcelable(@Nullable String name) {
if (mCallExtras != null) {
return mCallExtras.getParcelable(name);
}
return null;
}
public void setCallExtra(String name, String value) {
if (mCallExtras != null) {
mCallExtras.putString(name, value);
}
}
public void setCallExtraBoolean(String name, boolean value) {
if (mCallExtras != null) {
mCallExtras.putBoolean(name, value);
}
}
public void setCallExtraInt(String name, int value) {
if (mCallExtras != null) {
mCallExtras.putInt(name, value);
}
}
/**
* Set the call extra value (Parcelable), given the call extra name.
* @param name call extra name
* @param parcelable call extra value
*/
public void setCallExtraParcelable(@NonNull String name, @NonNull Parcelable parcelable) {
if (mCallExtras != null) {
mCallExtras.putParcelable(name, parcelable);
}
}
/**
* Set the call restrict cause, which provides the reason why a call has been restricted from
* using High Definition media.
*/
public void setCallRestrictCause(@CallRestrictCause int cause) {
mRestrictCause = cause;
}
public void updateCallType(ImsCallProfile profile) {
mCallType = profile.mCallType;
}
public void updateCallExtras(ImsCallProfile profile) {
mCallExtras.clear();
mCallExtras = (Bundle) profile.mCallExtras.clone();
}
/**
* Updates the media profile for the call.
*
* @param profile Call profile with new media profile.
*/
public void updateMediaProfile(ImsCallProfile profile) {
mMediaProfile = profile.mMediaProfile;
}
/**
* Sets the verification status for the phone number of an incoming call as identified in
* ATIS-1000082.
* <p>
* The ImsService should parse the verstat information from the SIP INVITE headers for the call
* to determine this information. It is typically found in the P-Asserted-Identity OR From
* header fields.
* @param callerNumberVerificationStatus the new verification status.
*/
public void setCallerNumberVerificationStatus(
@VerificationStatus int callerNumberVerificationStatus) {
mCallerNumberVerificationStatus = callerNumberVerificationStatus;
}
/**
* Gets the verification status for the phone number of an incoming call as identified in
* ATIS-1000082.
* @return the verification status.
*/
public @VerificationStatus int getCallerNumberVerificationStatus() {
return mCallerNumberVerificationStatus;
}
@NonNull
@Override
public String toString() {
return "{ serviceType=" + mServiceType
+ ", callType=" + mCallType
+ ", restrictCause=" + mRestrictCause
+ ", mediaProfile=" + (mMediaProfile != null ? mMediaProfile.toString() : "null")
+ ", emergencyServiceCategories=" + mEmergencyServiceCategories
+ ", emergencyUrns=" + mEmergencyUrns
+ ", emergencyCallRouting=" + mEmergencyCallRouting
+ ", emergencyCallTesting=" + mEmergencyCallTesting
+ ", hasKnownUserIntentEmergency=" + mHasKnownUserIntentEmergency
+ ", mRestrictCause=" + mRestrictCause
+ ", mCallerNumberVerstat= " + mCallerNumberVerificationStatus + " }";
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
Bundle filteredExtras = maybeCleanseExtras(mCallExtras);
out.writeInt(mServiceType);
out.writeInt(mCallType);
out.writeBundle(filteredExtras);
out.writeParcelable(mMediaProfile, 0);
out.writeInt(mEmergencyServiceCategories);
out.writeStringList(mEmergencyUrns);
out.writeInt(mEmergencyCallRouting);
out.writeBoolean(mEmergencyCallTesting);
out.writeBoolean(mHasKnownUserIntentEmergency);
out.writeInt(mRestrictCause);
out.writeInt(mCallerNumberVerificationStatus);
out.writeArray(mAcceptedRtpHeaderExtensionTypes.toArray());
}
private void readFromParcel(Parcel in) {
mServiceType = in.readInt();
mCallType = in.readInt();
mCallExtras = in.readBundle();
mMediaProfile = in.readParcelable(ImsStreamMediaProfile.class.getClassLoader());
mEmergencyServiceCategories = in.readInt();
mEmergencyUrns = in.createStringArrayList();
mEmergencyCallRouting = in.readInt();
mEmergencyCallTesting = in.readBoolean();
mHasKnownUserIntentEmergency = in.readBoolean();
mRestrictCause = in.readInt();
mCallerNumberVerificationStatus = in.readInt();
Object[] accepted = in.readArray(RtpHeaderExtensionType.class.getClassLoader());
mAcceptedRtpHeaderExtensionTypes = Arrays.stream(accepted)
.map(o -> (RtpHeaderExtensionType) o).collect(Collectors.toSet());
}
public static final @android.annotation.NonNull Creator<ImsCallProfile> CREATOR =
new Creator<ImsCallProfile>() {
@Override
public ImsCallProfile createFromParcel(Parcel in) {
return new ImsCallProfile(in);
}
@Override
public ImsCallProfile[] newArray(int size) {
return new ImsCallProfile[size];
}
};
public int getServiceType() {
return mServiceType;
}
public int getCallType() {
return mCallType;
}
/**
* @return The call restrict cause, which provides the reason why a call has been restricted
* from using High Definition media.
*/
public @CallRestrictCause int getRestrictCause() {
return mRestrictCause;
}
public Bundle getCallExtras() {
return mCallExtras;
}
/**
* Get the proprietary extras set for this ImsCallProfile.
* @return A {@link Bundle} containing proprietary call extras that were not set by the
* platform.
*/
public @NonNull Bundle getProprietaryCallExtras() {
if (mCallExtras == null) {
return new Bundle();
}
Bundle proprietaryExtras = mCallExtras.getBundle(EXTRA_OEM_EXTRAS);
if (proprietaryExtras == null) {
return new Bundle();
}
// Make a copy so users do not accidentally change this copy of the extras.
return new Bundle(proprietaryExtras);
}
public ImsStreamMediaProfile getMediaProfile() {
return mMediaProfile;
}
/**
* Converts from the call types defined in {@link ImsCallProfile} to the
* video state values defined in {@link VideoProfile}.
*
* @param callProfile The call profile.
* @return The video state.
*/
public static int getVideoStateFromImsCallProfile(ImsCallProfile callProfile) {
int videostate = getVideoStateFromCallType(callProfile.mCallType);
if (callProfile.isVideoPaused() && !VideoProfile.isAudioOnly(videostate)) {
videostate |= VideoProfile.STATE_PAUSED;
} else {
videostate &= ~VideoProfile.STATE_PAUSED;
}
return videostate;
}
/**
* Translates a {@link ImsCallProfile} {@code CALL_TYPE_*} constant into a video state.
* @param callType The call type.
* @return The video state.
*/
public static int getVideoStateFromCallType(int callType) {
int videostate = VideoProfile.STATE_AUDIO_ONLY;
switch (callType) {
case CALL_TYPE_VT_TX:
videostate = VideoProfile.STATE_TX_ENABLED;
break;
case CALL_TYPE_VT_RX:
videostate = VideoProfile.STATE_RX_ENABLED;
break;
case CALL_TYPE_VT:
videostate = VideoProfile.STATE_BIDIRECTIONAL;
break;
case CALL_TYPE_VOICE:
videostate = VideoProfile.STATE_AUDIO_ONLY;
break;
default:
videostate = VideoProfile.STATE_AUDIO_ONLY;
break;
}
return videostate;
}
/**
* Converts from the video state values defined in {@link VideoProfile}
* to the call types defined in {@link ImsCallProfile}.
*
* @param videoState The video state.
* @return The call type.
*/
public static int getCallTypeFromVideoState(int videoState) {
boolean videoTx = isVideoStateSet(videoState, VideoProfile.STATE_TX_ENABLED);
boolean videoRx = isVideoStateSet(videoState, VideoProfile.STATE_RX_ENABLED);
boolean isPaused = isVideoStateSet(videoState, VideoProfile.STATE_PAUSED);
if (isPaused) {
return ImsCallProfile.CALL_TYPE_VT_NODIR;
} else if (videoTx && !videoRx) {
return ImsCallProfile.CALL_TYPE_VT_TX;
} else if (!videoTx && videoRx) {
return ImsCallProfile.CALL_TYPE_VT_RX;
} else if (videoTx && videoRx) {
return ImsCallProfile.CALL_TYPE_VT;
}
return ImsCallProfile.CALL_TYPE_VOICE;
}
/**
* Badly named old method, kept for compatibility.
* See {@link #presentationToOir(int)}.
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static int presentationToOIR(int presentation) {
switch (presentation) {
case PhoneConstants.PRESENTATION_RESTRICTED:
return ImsCallProfile.OIR_PRESENTATION_RESTRICTED;
case PhoneConstants.PRESENTATION_ALLOWED:
return ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED;
case PhoneConstants.PRESENTATION_PAYPHONE:
return ImsCallProfile.OIR_PRESENTATION_PAYPHONE;
case PhoneConstants.PRESENTATION_UNKNOWN:
return ImsCallProfile.OIR_PRESENTATION_UNKNOWN;
default:
return ImsCallProfile.OIR_DEFAULT;
}
}
/**
* Translate presentation value to OIR value
* @param presentation
* @return OIR values
*/
public static int presentationToOir(int presentation) {
return presentationToOIR(presentation);
}
/**
* Translate OIR value to presentation value
* @param oir value
* @return presentation value
* @hide
*/
public static int OIRToPresentation(int oir) {
switch(oir) {
case ImsCallProfile.OIR_PRESENTATION_RESTRICTED:
return PhoneConstants.PRESENTATION_RESTRICTED;
case ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED:
return PhoneConstants.PRESENTATION_ALLOWED;
case ImsCallProfile.OIR_PRESENTATION_PAYPHONE:
return PhoneConstants.PRESENTATION_PAYPHONE;
case ImsCallProfile.OIR_PRESENTATION_UNKNOWN:
return PhoneConstants.PRESENTATION_UNKNOWN;
default:
return PhoneConstants.PRESENTATION_UNKNOWN;
}
}
/**
* Checks if video call is paused
* @return true if call is video paused
*/
public boolean isVideoPaused() {
return mMediaProfile.mVideoDirection == ImsStreamMediaProfile.DIRECTION_INACTIVE;
}
/**
* Determines if the {@link ImsCallProfile} represents a video call.
*
* @return {@code true} if the profile is for a video call, {@code false} otherwise.
*/
public boolean isVideoCall() {
return VideoProfile.isVideo(getVideoStateFromCallType(mCallType));
}
/**
* Cleanses a {@link Bundle} to ensure that it contains only data of type:
* 1. Primitive data types (e.g. int, bool, and other values determined by
* {@link android.os.PersistableBundle#isValidType(Object)}).
* 2. Other Bundles.
* 3. {@link Parcelable} objects in the {@code android.*} namespace.
* @param extras the source {@link Bundle}
* @return where all elements are valid types the source {@link Bundle} is returned unmodified,
* otherwise a copy of the {@link Bundle} with the invalid elements is returned.
*/
private Bundle maybeCleanseExtras(Bundle extras) {
if (extras == null) {
return null;
}
int startSize = extras.size();
Bundle filtered = TelephonyUtils.filterValues(extras);
int endSize = filtered.size();
if (startSize != endSize) {
Log.i(TAG, "maybeCleanseExtras: " + (startSize - endSize) + " extra values were "
+ "removed - only primitive types and system parcelables are permitted.");
}
return filtered;
}
/**
* Determines if a video state is set in a video state bit-mask.
*
* @param videoState The video state bit mask.
* @param videoStateToCheck The particular video state to check.
* @return True if the video state is set in the bit-mask.
*/
private static boolean isVideoStateSet(int videoState, int videoStateToCheck) {
return (videoState & videoStateToCheck) == videoStateToCheck;
}
/**
* Set the emergency number information. The set value is valid
* only if {@link #getServiceType} returns {@link #SERVICE_TYPE_EMERGENCY}
*
* Reference: 3gpp 23.167, Section 6 - Functional description;
* 3gpp 24.503, Section 5.1.6.8.1 - General;
* 3gpp 22.101, Section 10 - Emergency Calls.
*
* @hide
*/
public void setEmergencyCallInfo(EmergencyNumber num, boolean hasKnownUserIntentEmergency) {
setEmergencyServiceCategories(num.getEmergencyServiceCategoryBitmaskInternalDial());
setEmergencyUrns(num.getEmergencyUrns());
setEmergencyCallRouting(num.getEmergencyCallRouting());
setEmergencyCallTesting(num.getEmergencyNumberSourceBitmask()
== EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST);
setHasKnownUserIntentEmergency(hasKnownUserIntentEmergency);
}
/**
* Set the emergency service categories. The set value is valid only if
* {@link #getServiceType} returns {@link #SERVICE_TYPE_EMERGENCY}
*
* If valid, the value is the bitwise-OR combination of the following constants:
* <ol>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_POLICE} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AMBULANCE} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MIEC} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AIEC} </li>
* </ol>
*
* Reference: 3gpp 23.167, Section 6 - Functional description;
* 3gpp 22.101, Section 10 - Emergency Calls.
*/
@VisibleForTesting
public void setEmergencyServiceCategories(
@EmergencyServiceCategories int emergencyServiceCategories) {
mEmergencyServiceCategories = emergencyServiceCategories;
}
/**
* Set the emergency Uniform Resource Names (URN), only valid if {@link #getServiceType}
* returns {@link #SERVICE_TYPE_EMERGENCY}.
*
* Reference: 3gpp 24.503, Section 5.1.6.8.1 - General;
* 3gpp 22.101, Section 10 - Emergency Calls.
*/
@VisibleForTesting
public void setEmergencyUrns(@NonNull List<String> emergencyUrns) {
mEmergencyUrns = emergencyUrns;
}
/**
* Set the emergency call routing, only valid if {@link #getServiceType} returns
* {@link #SERVICE_TYPE_EMERGENCY}
*
* If valid, the value is any of the following constants:
* <ol>
* <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_UNKNOWN} </li>
* <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_NORMAL} </li>
* <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_EMERGENCY} </li>
* </ol>
*/
@VisibleForTesting
public void setEmergencyCallRouting(@EmergencyCallRouting int emergencyCallRouting) {
mEmergencyCallRouting = emergencyCallRouting;
}
/**
* Set if this is for testing emergency call, only valid if {@link #getServiceType} returns
* {@link #SERVICE_TYPE_EMERGENCY}.
*/
@VisibleForTesting
public void setEmergencyCallTesting(boolean isTesting) {
mEmergencyCallTesting = isTesting;
}
/**
* Set if we have known the user intent of the call is emergency.
*
* This is only used to specify when the dialed number is ambiguous when it can be 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.
*/
@VisibleForTesting
public void setHasKnownUserIntentEmergency(boolean hasKnownUserIntentEmergency) {
mHasKnownUserIntentEmergency = hasKnownUserIntentEmergency;
}
/**
* Get the emergency service categories, only valid if {@link #getServiceType} returns
* {@link #SERVICE_TYPE_EMERGENCY}
*
* @return the emergency service categories,
*
* If valid, the value is the bitwise-OR combination of the following constants:
* <ol>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_POLICE} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AMBULANCE} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MIEC} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AIEC} </li>
* </ol>
*
* Reference: 3gpp 23.167, Section 6 - Functional description;
* 3gpp 22.101, Section 10 - Emergency Calls.
*/
public @EmergencyServiceCategories int getEmergencyServiceCategories() {
return mEmergencyServiceCategories;
}
/**
* Get the emergency Uniform Resource Names (URN), only valid if {@link #getServiceType}
* returns {@link #SERVICE_TYPE_EMERGENCY}.
*
* Reference: 3gpp 24.503, Section 5.1.6.8.1 - General;
* 3gpp 22.101, Section 10 - Emergency Calls.
*/
public @NonNull List<String> getEmergencyUrns() {
return mEmergencyUrns;
}
/**
* Get the emergency call routing, only valid if {@link #getServiceType} returns
* {@link #SERVICE_TYPE_EMERGENCY}
*
* If valid, the value is any of the following constants:
* <ol>
* <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_UNKNOWN} </li>
* <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_NORMAL} </li>
* <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_EMERGENCY} </li>
* </ol>
*/
public @EmergencyCallRouting int getEmergencyCallRouting() {
return mEmergencyCallRouting;
}
/**
* Get if the emergency call is for testing purpose.
*/
public boolean isEmergencyCallTesting() {
return mEmergencyCallTesting;
}
/**
* Checks if we have known the user intent of the call is emergency.
*
* This is only used to specify when the dialed number is ambiguous when it can be 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.
*/
public boolean hasKnownUserIntentEmergency() {
return mHasKnownUserIntentEmergency;
}
/**
* Gets the {@link RtpHeaderExtensionType}s which have been accepted by both ends of the call.
* <p>
* According to RFC8285, RTP header extensions available to a call are determined using the
* offer/accept phase of the SDP protocol (see RFC4566).
* <p>
* The offered header extension types supported by the framework and exposed to the
* {@link ImsService} via {@link MmTelFeature#changeOfferedRtpHeaderExtensionTypes(Set)}.
*
* @return the {@link RtpHeaderExtensionType}s which were accepted by the other end of the call.
*/
public @NonNull Set<RtpHeaderExtensionType> getAcceptedRtpHeaderExtensionTypes() {
return mAcceptedRtpHeaderExtensionTypes;
}
/**
* Sets the accepted {@link RtpHeaderExtensionType}s for this call.
* <p>
* According to RFC8285, RTP header extensions available to a call are determined using the
* offer/accept phase of the SDP protocol (see RFC4566).
*
* @param rtpHeaderExtensions
*/
public void setAcceptedRtpHeaderExtensionTypes(@NonNull Set<RtpHeaderExtensionType>
rtpHeaderExtensions) {
mAcceptedRtpHeaderExtensionTypes.clear();
mAcceptedRtpHeaderExtensionTypes.addAll(rtpHeaderExtensions);
}
}